From 306e6a85db0e8f218c863fc8582bd17a7fbaee5e Mon Sep 17 00:00:00 2001 From: Dan Elbert Date: Sat, 9 Jun 2018 13:15:07 -0500 Subject: [PATCH] removed old view files --- app/assets/images/grey_wash_wall.png | Bin 47433 -> 0 bytes app/assets/images/old_map.png | Bin 32184 -> 0 bytes app/assets/images/old_mathematics.png | Bin 48689 -> 0 bytes app/assets/javascripts/application.js | 20 +- app/assets/javascripts/calculator.js | 124 - app/assets/javascripts/checkable.js | 36 - app/assets/javascripts/flash_messages.js | 46 - app/assets/javascripts/ingredients.js | 88 - app/assets/javascripts/logs.js | 7 - app/assets/javascripts/recipe_editor.js | 393 - app/assets/javascripts/recipes.js | 33 - app/assets/javascripts/star_rating.js | 133 - app/assets/javascripts/typeahead_search.js | 112 - app/assets/javascripts/typeahead_selector.js | 70 - app/assets/stylesheets/application.scss | 93 - app/assets/stylesheets/codemirror_custom.scss | 5 - app/assets/stylesheets/flash_messages.scss | 44 - app/assets/stylesheets/font_references.scss | 105 - app/assets/stylesheets/ingredients.scss | 3 - .../stylesheets/journal_custom_colors.scss | 5 - app/assets/stylesheets/recipes.scss | 76 - app/assets/stylesheets/star_rating.scss | 36 - .../stylesheets/typeahead-bootstrap.scss | 64 - app/helpers/application_helper.rb | 53 - app/helpers/ingredients_helper.rb | 7 - app/helpers/recipes_helper.rb | 68 - app/views/admin/users/edit.html.erb | 0 app/views/admin/users/index.html.erb | 42 - app/views/admin/users/show.html.erb | 0 app/views/calculator/index.html.erb | 49 - app/views/ingredients/_form.html.erb | 151 - .../_ingredient_unit_fields.html.erb | 22 - app/views/ingredients/edit.html.erb | 11 - app/views/ingredients/index.html.erb | 58 - app/views/ingredients/new.html.erb | 11 - app/views/ingredients/select_ndbn.js.erb | 3 - .../ingredients/usda_food_search.html.erb | 30 - app/views/kaminari/_first_page.html.erb | 3 - app/views/kaminari/_gap.html.erb | 3 - app/views/kaminari/_last_page.html.erb | 3 - app/views/kaminari/_next_page.html.erb | 3 - app/views/kaminari/_page.html.erb | 9 - app/views/kaminari/_paginator.html.erb | 15 - app/views/kaminari/_prev_page.html.erb | 3 - app/views/layouts/_flash_messages.html.erb | 10 - app/views/layouts/application.html.erb | 41 - app/views/logs/_form.html.erb | 46 - app/views/logs/edit.html.erb | 12 - app/views/logs/index.html.erb | 40 - app/views/logs/new.html.erb | 12 - app/views/logs/show.html.erb | 92 - app/views/notes/_form.html.erb | 13 - app/views/notes/edit.html.erb | 11 - app/views/notes/index.html.erb | 47 - app/views/notes/new.html.erb | 11 - app/views/notes/show.html.erb | 15 - app/views/recipes/_editor.html.erb | 101 - app/views/recipes/_form.html.erb | 11 - app/views/recipes/edit.html.erb | 12 - .../editor/_bulk_ingredient_dialog.html.erb | 48 - .../recipes/editor/_bulk_step_dialog.html.erb | 46 - .../recipes/editor/_conversion_form.html.erb | 48 - app/views/recipes/editor/_ingredient.html.erb | 57 - app/views/recipes/editor/_step.html.erb | 25 - app/views/recipes/index.html.erb | 96 - app/views/recipes/new.html.erb | 12 - app/views/recipes/show.html.erb | 203 - app/views/shared/_error_list.html.erb | 11 - app/views/users/_form.html.erb | 30 - app/views/users/edit.html.erb | 11 - app/views/users/login.html.erb | 31 - app/views/users/new.html.erb | 11 - vendor/assets/fonts/inconsolata-bold.woff2 | Bin 11008 -> 0 bytes vendor/assets/fonts/inconsolata.woff2 | Bin 9564 -> 0 bytes vendor/assets/fonts/news-cycle-bold.woff2 | Bin 13392 -> 0 bytes vendor/assets/fonts/news-cycle.woff2 | Bin 12600 -> 0 bytes .../assets/fonts/open-sans-bold-italic.woff2 | Bin 10636 -> 0 bytes vendor/assets/fonts/open-sans-bold.woff2 | Bin 10284 -> 0 bytes vendor/assets/fonts/open-sans-italic.woff2 | Bin 10920 -> 0 bytes .../assets/fonts/open-sans-light-italic.woff2 | Bin 10928 -> 0 bytes vendor/assets/fonts/open-sans-light.woff2 | Bin 10200 -> 0 bytes vendor/assets/fonts/open-sans.woff2 | Bin 10352 -> 0 bytes vendor/assets/fonts/raleway-bold.woff2 | Bin 15008 -> 0 bytes vendor/assets/fonts/raleway.woff2 | Bin 15032 -> 0 bytes vendor/assets/fonts/roboto-bold.woff2 | Bin 10276 -> 0 bytes vendor/assets/fonts/roboto-light.woff2 | Bin 10324 -> 0 bytes vendor/assets/fonts/roboto-medium.woff2 | Bin 10248 -> 0 bytes vendor/assets/fonts/roboto.woff2 | Bin 10292 -> 0 bytes vendor/assets/images/chosen-sprite.png | Bin 538 -> 0 bytes vendor/assets/images/chosen-sprite@2x.png | Bin 738 -> 0 bytes vendor/assets/javascripts/.keep | 0 vendor/assets/javascripts/autosize.js | 243 - .../javascripts/bootstrap-datepicker.js | 2089 ---- .../assets/javascripts/bootstrap-tagsinput.js | 682 -- vendor/assets/javascripts/chosen.jquery.js | 1257 --- vendor/assets/javascripts/codemirror.js | 9304 ----------------- vendor/assets/javascripts/markdown.js | 808 -- vendor/assets/javascripts/typeahead.js | 2451 ----- vendor/assets/javascripts/underscore.js | 1548 --- vendor/assets/stylesheets/.keep | 0 .../stylesheets/bootstrap-datepicker3.css | 680 -- .../bootstrap-tagsinput-typeahead.css | 54 - .../stylesheets/bootstrap-tagsinput.css | 60 - vendor/assets/stylesheets/chosen.css | 450 - vendor/assets/stylesheets/codemirror.css | 340 - .../stylesheets/journal/_bootswatch.scss | 145 - .../stylesheets/journal/_variables.scss | 870 -- .../assets/stylesheets/paper/_bootswatch.scss | 611 -- .../assets/stylesheets/paper/_variables.scss | 870 -- .../stylesheets/readable/_bootswatch.scss | 183 - .../stylesheets/readable/_variables.scss | 870 -- .../stylesheets/sandstone/_bootswatch.scss | 195 - .../stylesheets/sandstone/_variables.scss | 870 -- .../stylesheets/spacelab/_bootswatch.scss | 142 - .../stylesheets/spacelab/_variables.scss | 870 -- .../assets/stylesheets/yeti/_bootswatch.scss | 440 - .../assets/stylesheets/yeti/_variables.scss | 870 -- 117 files changed, 1 insertion(+), 30041 deletions(-) delete mode 100644 app/assets/images/grey_wash_wall.png delete mode 100644 app/assets/images/old_map.png delete mode 100644 app/assets/images/old_mathematics.png delete mode 100644 app/assets/javascripts/calculator.js delete mode 100644 app/assets/javascripts/checkable.js delete mode 100644 app/assets/javascripts/flash_messages.js delete mode 100644 app/assets/javascripts/ingredients.js delete mode 100644 app/assets/javascripts/logs.js delete mode 100644 app/assets/javascripts/recipe_editor.js delete mode 100644 app/assets/javascripts/recipes.js delete mode 100644 app/assets/javascripts/star_rating.js delete mode 100644 app/assets/javascripts/typeahead_search.js delete mode 100644 app/assets/javascripts/typeahead_selector.js delete mode 100644 app/assets/stylesheets/codemirror_custom.scss delete mode 100644 app/assets/stylesheets/flash_messages.scss delete mode 100644 app/assets/stylesheets/font_references.scss delete mode 100644 app/assets/stylesheets/ingredients.scss delete mode 100644 app/assets/stylesheets/journal_custom_colors.scss delete mode 100644 app/assets/stylesheets/recipes.scss delete mode 100644 app/assets/stylesheets/star_rating.scss delete mode 100644 app/assets/stylesheets/typeahead-bootstrap.scss delete mode 100644 app/views/admin/users/edit.html.erb delete mode 100644 app/views/admin/users/index.html.erb delete mode 100644 app/views/admin/users/show.html.erb delete mode 100644 app/views/calculator/index.html.erb delete mode 100644 app/views/ingredients/_form.html.erb delete mode 100644 app/views/ingredients/_ingredient_unit_fields.html.erb delete mode 100644 app/views/ingredients/edit.html.erb delete mode 100644 app/views/ingredients/index.html.erb delete mode 100644 app/views/ingredients/new.html.erb delete mode 100644 app/views/ingredients/select_ndbn.js.erb delete mode 100644 app/views/ingredients/usda_food_search.html.erb delete mode 100644 app/views/kaminari/_first_page.html.erb delete mode 100644 app/views/kaminari/_gap.html.erb delete mode 100644 app/views/kaminari/_last_page.html.erb delete mode 100644 app/views/kaminari/_next_page.html.erb delete mode 100644 app/views/kaminari/_page.html.erb delete mode 100644 app/views/kaminari/_paginator.html.erb delete mode 100644 app/views/kaminari/_prev_page.html.erb delete mode 100644 app/views/layouts/_flash_messages.html.erb delete mode 100644 app/views/logs/_form.html.erb delete mode 100644 app/views/logs/edit.html.erb delete mode 100644 app/views/logs/index.html.erb delete mode 100644 app/views/logs/new.html.erb delete mode 100644 app/views/logs/show.html.erb delete mode 100644 app/views/notes/_form.html.erb delete mode 100644 app/views/notes/edit.html.erb delete mode 100644 app/views/notes/index.html.erb delete mode 100644 app/views/notes/new.html.erb delete mode 100644 app/views/notes/show.html.erb delete mode 100644 app/views/recipes/_editor.html.erb delete mode 100644 app/views/recipes/_form.html.erb delete mode 100644 app/views/recipes/edit.html.erb delete mode 100644 app/views/recipes/editor/_bulk_ingredient_dialog.html.erb delete mode 100644 app/views/recipes/editor/_bulk_step_dialog.html.erb delete mode 100644 app/views/recipes/editor/_conversion_form.html.erb delete mode 100644 app/views/recipes/editor/_ingredient.html.erb delete mode 100644 app/views/recipes/editor/_step.html.erb delete mode 100644 app/views/recipes/index.html.erb delete mode 100644 app/views/recipes/new.html.erb delete mode 100644 app/views/recipes/show.html.erb delete mode 100644 app/views/shared/_error_list.html.erb delete mode 100644 app/views/users/_form.html.erb delete mode 100644 app/views/users/edit.html.erb delete mode 100644 app/views/users/login.html.erb delete mode 100644 app/views/users/new.html.erb delete mode 100644 vendor/assets/fonts/inconsolata-bold.woff2 delete mode 100644 vendor/assets/fonts/inconsolata.woff2 delete mode 100644 vendor/assets/fonts/news-cycle-bold.woff2 delete mode 100644 vendor/assets/fonts/news-cycle.woff2 delete mode 100644 vendor/assets/fonts/open-sans-bold-italic.woff2 delete mode 100644 vendor/assets/fonts/open-sans-bold.woff2 delete mode 100644 vendor/assets/fonts/open-sans-italic.woff2 delete mode 100644 vendor/assets/fonts/open-sans-light-italic.woff2 delete mode 100644 vendor/assets/fonts/open-sans-light.woff2 delete mode 100644 vendor/assets/fonts/open-sans.woff2 delete mode 100644 vendor/assets/fonts/raleway-bold.woff2 delete mode 100644 vendor/assets/fonts/raleway.woff2 delete mode 100644 vendor/assets/fonts/roboto-bold.woff2 delete mode 100644 vendor/assets/fonts/roboto-light.woff2 delete mode 100644 vendor/assets/fonts/roboto-medium.woff2 delete mode 100644 vendor/assets/fonts/roboto.woff2 delete mode 100644 vendor/assets/images/chosen-sprite.png delete mode 100644 vendor/assets/images/chosen-sprite@2x.png delete mode 100644 vendor/assets/javascripts/.keep delete mode 100644 vendor/assets/javascripts/autosize.js delete mode 100644 vendor/assets/javascripts/bootstrap-datepicker.js delete mode 100644 vendor/assets/javascripts/bootstrap-tagsinput.js delete mode 100644 vendor/assets/javascripts/chosen.jquery.js delete mode 100644 vendor/assets/javascripts/codemirror.js delete mode 100644 vendor/assets/javascripts/markdown.js delete mode 100644 vendor/assets/javascripts/typeahead.js delete mode 100644 vendor/assets/javascripts/underscore.js delete mode 100644 vendor/assets/stylesheets/.keep delete mode 100644 vendor/assets/stylesheets/bootstrap-datepicker3.css delete mode 100644 vendor/assets/stylesheets/bootstrap-tagsinput-typeahead.css delete mode 100644 vendor/assets/stylesheets/bootstrap-tagsinput.css delete mode 100644 vendor/assets/stylesheets/chosen.css delete mode 100644 vendor/assets/stylesheets/codemirror.css delete mode 100644 vendor/assets/stylesheets/journal/_bootswatch.scss delete mode 100644 vendor/assets/stylesheets/journal/_variables.scss delete mode 100644 vendor/assets/stylesheets/paper/_bootswatch.scss delete mode 100644 vendor/assets/stylesheets/paper/_variables.scss delete mode 100644 vendor/assets/stylesheets/readable/_bootswatch.scss delete mode 100644 vendor/assets/stylesheets/readable/_variables.scss delete mode 100644 vendor/assets/stylesheets/sandstone/_bootswatch.scss delete mode 100644 vendor/assets/stylesheets/sandstone/_variables.scss delete mode 100644 vendor/assets/stylesheets/spacelab/_bootswatch.scss delete mode 100644 vendor/assets/stylesheets/spacelab/_variables.scss delete mode 100644 vendor/assets/stylesheets/yeti/_bootswatch.scss delete mode 100644 vendor/assets/stylesheets/yeti/_variables.scss diff --git a/app/assets/images/grey_wash_wall.png b/app/assets/images/grey_wash_wall.png deleted file mode 100644 index d54e8899498d67c0367db2096c8f7c371c41461c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47433 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 diff --git a/app/assets/images/old_map.png b/app/assets/images/old_map.png deleted file mode 100644 index eb2373bf2436f57da04c3e3154de12d95210814f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32184 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 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 52f2c50..b741814 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -10,24 +10,6 @@ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // -//= require jquery -//= require jquery_ujs -//= require turbolinks -//= require bootstrap-sprockets -//= require bootstrap-datepicker -//= require bootstrap-tagsinput -//= require cocoon -//= require typeahead -//= require autosize -//= require chosen.jquery -//= require codemirror -//= require markdown -//= require underscore + //= require_tree . -// Setup star rating automagic -$(document).on("turbolinks:load", function() { - - $("input[data-rating='true']").starRating(); - -}); \ No newline at end of file diff --git a/app/assets/javascripts/calculator.js b/app/assets/javascripts/calculator.js deleted file mode 100644 index 106b795..0000000 --- a/app/assets/javascripts/calculator.js +++ /dev/null @@ -1,124 +0,0 @@ -(function($) { - - function State() { - this.input = null; - this.outputUnit = null; - this.density = null; - this.changed = false; - } - - State.prototype.setInput = function(value) { - if (value != this.input) { - this.changed = true; - this.input = value; - } - }; - - State.prototype.setDensity = function(value) { - if (value != this.density) { - this.changed = true; - this.density = value; - } - }; - - State.prototype.setOutputUnit = function(value) { - if (value != this.outputUnit) { - this.changed = true; - this.outputUnit = value; - } - }; - - State.prototype.is_changed = function() { - return this.changed; - }; - - State.prototype.reset = function() { - this.changed = false; - }; - - var ingredientSearchEngine = new Bloodhound({ - initialize: false, - datumTokenizer: function(datum) { - return Bloodhound.tokenizers.whitespace(datum.name); - }, - queryTokenizer: Bloodhound.tokenizers.whitespace, - identify: function(datum) { return datum.id; }, - sorter: function(a, b) { - if (a.name < b.name) { - return -1; - } else if (b.name < a.name) { - return 1; - } else { - return 0; - } - }, - remote: { - url: '/calculator/ingredient_search.json?query=%QUERY', - wildcard: '%QUERY' - } - }); - - $(document).on("turbolinks:load", function() { - - var state = new State(); - var $input = $("#input"); - var $output = $("#output"); - var $density = $("#density"); - var $outputUnit = $("#output_unit"); - - var performUpdate = _.debounce(function() { - $.getJSON( - "/calculator/calculate", - {input: $input.val(), output_unit: $outputUnit.val(), density: $density.val()}, - function(data) { - if (data.errors.length) { - $("#errors_panel").show(); - $("#errors_container").html(data.errors.join(" ")); - } else { - $("#errors_panel").hide(); - } - - $output.val(data.output); - } - ); - - }, 500); - - var ingredientPicked = function(i) { - $density.val(i.density); - $density.trigger('change'); - }; - - $input.add($outputUnit).add($density).on('change blur keyup', function(evt) { - state.setInput($input.val()); - state.setOutputUnit($outputUnit.val()); - state.setDensity($density.val()); - - if (state.is_changed()) { - performUpdate(); - state.reset(); - } - }); - - if ($("#calculator").length) { - ingredientSearchEngine.initialize(false); - - $("#ingredient").typeahead({}, - { - name: 'ingredients', - source: ingredientSearchEngine, - display: function(datum) { - return datum.name; - } - }) - .on("typeahead:select", function(evt, value) { - ingredientPicked(value); - }) - .on("typeahead:autocomplete", function(evt, value) { - ingredientPicked(value); - }); - } - - }); - -})(jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/checkable.js b/app/assets/javascripts/checkable.js deleted file mode 100644 index 42f5893..0000000 --- a/app/assets/javascripts/checkable.js +++ /dev/null @@ -1,36 +0,0 @@ -(function($) { - - var pluginName = "checkable"; - - var defaultOptions = { - childrenSelector: "li", - selectedClass: "checked" - }; - - var methods = { - initialize: function (opts, sources) { - - return this.each(function() { - var options = $.extend({}, defaultOptions, opts); - $(this).on("click", options.childrenSelector, function(evt) { - $(evt.currentTarget).toggleClass(options.selectedClass); - }); - }); - } - }; - - var privateMethods = { - - }; - - $.fn[pluginName] = function (method) { - if (methods[method]) { - return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); - } else if (typeof method === 'object' || ! method) { - return methods.initialize.apply(this, arguments); - } else { - $.error('Method ' + method + ' does not exist on jQuery.' + pluginName); - } - }; - -})(jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/flash_messages.js b/app/assets/javascripts/flash_messages.js deleted file mode 100644 index a603ecf..0000000 --- a/app/assets/javascripts/flash_messages.js +++ /dev/null @@ -1,46 +0,0 @@ - -var flashMessageTypeMap = { - error: "danger", - notice: "success" -}; - -function flashMessage(flashType, message) { - - var timeoutIdContainer = {}; - - if (flashMessageTypeMap[flashType]) { - flashType = flashMessageTypeMap[flashType]; - } - - var closeButton = $(" - - - - - -
-
- -
- <%= f.label :density, class: 'control-label' %> - <%= f.text_field :density, class: 'form-control', disabled: has_ndbn %> -
- -
-
-

Ingredient Units

-
-
-
- <%= f.fields_for :ingredient_units do |iu_form| %> - <%= render partial: 'ingredients/ingredient_unit_fields', locals: {f: iu_form } %> - <% end %> - - <%= link_to_add_association 'add unit', f, :ingredient_units, class: 'btn btn-primary' %> -
-
-
- - <% if has_ndbn %> - -
-
-

NDBN Unit Weights

-
-
- - - - - - - - <% @ingredient.usda_food.usda_food_weights.each do |w| %> - - - - - <% end %> -
NameGrams
<%= "#{w.amount} #{w.description}" %><%= w.gram_weight %>
-
-
- - <% end %> - -
- <%= f.label :notes, class: 'control-label' %> - <%= f.text_area :notes, class: 'form-control' %> -
- -
-
-

Nutrition Per 100 grams

-
-
-
> - -
-
-
- <%= f.label :water, "Grams of Water", class: 'control-label' %> - <%= f.text_field :water, class: 'form-control' %> -
- -
- <%= f.label :protein, "Grams of Protein", class: 'control-label' %> - <%= f.text_field :protein, class: 'form-control' %> -
- -
- <%= f.label :lipids, "Grams of Fat", class: 'control-label' %> - <%= f.text_field :lipids, class: 'form-control' %> -
- -
- <%= f.label :carbohydrates, "Grams of Carbohydrates", class: 'control-label' %> - <%= f.text_field :carbohydrates, class: 'form-control' %> -
- -
- <%= f.label :kcal, "Calories", class: 'control-label' %> - <%= f.text_field :kcal, class: 'form-control' %> -
- -
- <%= f.label :fiber, "Grams of Fiber", class: 'control-label' %> - <%= f.text_field :fiber, class: 'form-control' %> -
- -
- <%= f.label :sugar, "Grams of Sugar", class: 'control-label' %> - <%= f.text_field :sugar, class: 'form-control' %> -
-
-
-
- <%= f.label :calcium, "Miligrams of Calcium", class: 'control-label' %> - <%= f.text_field :calcium, class: 'form-control' %> -
- -
- <%= f.label :sodium, "Miligrams of Sodium", class: 'control-label' %> - <%= f.text_field :sodium, class: 'form-control' %> -
- -
- <%= f.label :vit_k, "Micrograms of Vitamin K", class: 'control-label' %> - <%= f.text_field :vit_k, class: 'form-control' %> -
-
-
-
-
-
- -
- <%= f.submit class: 'btn btn-primary' %> -
- -<% end %> diff --git a/app/views/ingredients/_ingredient_unit_fields.html.erb b/app/views/ingredients/_ingredient_unit_fields.html.erb deleted file mode 100644 index 804bbf8..0000000 --- a/app/views/ingredients/_ingredient_unit_fields.html.erb +++ /dev/null @@ -1,22 +0,0 @@ -
- -
- <%= f.label :name, class: 'control-label' %> - <%= f.text_field :name, class: 'form-control' %> -
- -
- <%= f.label :gram_weight, 'Grams', class: 'control-label' %> - <%= f.text_field :gram_weight, class: 'form-control' %> -
- -
- -

- <%= link_to_remove_association f, class: 'btn btn-danger btn-sm' do %> - - <% end %> -

-
- -
\ No newline at end of file diff --git a/app/views/ingredients/edit.html.erb b/app/views/ingredients/edit.html.erb deleted file mode 100644 index 9e14d8a..0000000 --- a/app/views/ingredients/edit.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
-
- -

Editing Ingredient

- - <%= render 'form' %> - - <%= link_to 'Back', ingredients_path, class: 'btn btn-default' %> - -
-
\ No newline at end of file diff --git a/app/views/ingredients/index.html.erb b/app/views/ingredients/index.html.erb deleted file mode 100644 index 1639e4c..0000000 --- a/app/views/ingredients/index.html.erb +++ /dev/null @@ -1,58 +0,0 @@ -
-
- - - <% if @ingredients.empty? %> -

No Ingredients

- <% else %> - - <% if current_user? %> - <%= link_to 'New Ingredient', new_ingredient_path, class: 'btn btn-default' %> - <% end %> - -
- - - - - - - - - <% if current_user? %> - - <% end %> - - - - - <% decorate(@ingredients, IngredientDecorator).each do |ingredient| %> - - - - - - <% if current_user? %> - - <% end %> - - <% end %> - -
NameUSDAKCal per 100gDensity (oz/cup)
<%= link_to_if current_user?, ingredient.name, edit_ingredient_path(ingredient) %><%= ingredient.ndbn_check %><%= ingredient.kcal %><%= ingredient.density %> - <%= link_to ingredient, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-xs btn-danger' do %> - - <% end %> -
- <% end %> - -
- - <% if current_user? %> - <%= link_to 'New Ingredient', new_ingredient_path, class: 'btn btn-default' %> - <% end %> - - -
-
diff --git a/app/views/ingredients/new.html.erb b/app/views/ingredients/new.html.erb deleted file mode 100644 index 2262b48..0000000 --- a/app/views/ingredients/new.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
-
- -

New Ingredient

- - <%= render 'form' %> - - <%= link_to 'Back', ingredients_path, class: 'btn btn-primary' %> - -
-
diff --git a/app/views/ingredients/select_ndbn.js.erb b/app/views/ingredients/select_ndbn.js.erb deleted file mode 100644 index 4eb7e32..0000000 --- a/app/views/ingredients/select_ndbn.js.erb +++ /dev/null @@ -1,3 +0,0 @@ - -$("#ingredient_form").replaceWith($("<%= escape_javascript(render(partial: 'ingredients/form')) %>")); -window.INGREDIENT_API.initialize(); \ No newline at end of file diff --git a/app/views/ingredients/usda_food_search.html.erb b/app/views/ingredients/usda_food_search.html.erb deleted file mode 100644 index d8db16a..0000000 --- a/app/views/ingredients/usda_food_search.html.erb +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - -<% @foods.each do |f| %> - - - - - - - - - -<% end %> - -
per 100 grams
NDBNNameKCalCarbsSugar
<%= f.ndbn %><%= link_to f.long_description, '#', class: 'food_result', data: {ndbn: f.ndbn} %><%= f.kcal %><%= f.carbohydrates %><%= f.sugar %>
\ No newline at end of file diff --git a/app/views/kaminari/_first_page.html.erb b/app/views/kaminari/_first_page.html.erb deleted file mode 100644 index bf23ff0..0000000 --- a/app/views/kaminari/_first_page.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -
  • - <%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote %> -
  • diff --git a/app/views/kaminari/_gap.html.erb b/app/views/kaminari/_gap.html.erb deleted file mode 100644 index 6d3a149..0000000 --- a/app/views/kaminari/_gap.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -
  • - <%= content_tag :a, raw(t 'views.pagination.truncate') %> -
  • diff --git a/app/views/kaminari/_last_page.html.erb b/app/views/kaminari/_last_page.html.erb deleted file mode 100644 index fb619ea..0000000 --- a/app/views/kaminari/_last_page.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -
  • - <%= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote} %> -
  • diff --git a/app/views/kaminari/_next_page.html.erb b/app/views/kaminari/_next_page.html.erb deleted file mode 100644 index 15e10e4..0000000 --- a/app/views/kaminari/_next_page.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -
  • - <%= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote %> -
  • diff --git a/app/views/kaminari/_page.html.erb b/app/views/kaminari/_page.html.erb deleted file mode 100644 index 8028b45..0000000 --- a/app/views/kaminari/_page.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<% if page.current? %> -
  • - <%= content_tag :a, page, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)) %> -
  • -<% else %> -
  • - <%= link_to page, url, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)) %> -
  • -<% end %> diff --git a/app/views/kaminari/_paginator.html.erb b/app/views/kaminari/_paginator.html.erb deleted file mode 100644 index 2c8757b..0000000 --- a/app/views/kaminari/_paginator.html.erb +++ /dev/null @@ -1,15 +0,0 @@ -<%= paginator.render do -%> -
      - <%= first_page_tag unless current_page.first? %> - <%= prev_page_tag unless current_page.first? %> - <% each_page do |page| -%> - <% if page.left_outer? || page.right_outer? || page.inside_window? -%> - <%= page_tag page %> - <% elsif !page.was_truncated? -%> - <%= gap_tag %> - <% end -%> - <% end -%> - <%= next_page_tag unless current_page.last? %> - <%= last_page_tag unless current_page.last? %> -
    -<% end -%> diff --git a/app/views/kaminari/_prev_page.html.erb b/app/views/kaminari/_prev_page.html.erb deleted file mode 100644 index d94a50a..0000000 --- a/app/views/kaminari/_prev_page.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -
  • - <%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %> -
  • diff --git a/app/views/layouts/_flash_messages.html.erb b/app/views/layouts/_flash_messages.html.erb deleted file mode 100644 index e4e8932..0000000 --- a/app/views/layouts/_flash_messages.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -
    - -
    - <% flash.each do |type, values| %> - <% Array.wrap(values).each do |value| %> -
    <%= value %>
    - <% end %> - <% end %> -
    - diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index e4e688b..7ad8e82 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,40 +9,11 @@ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> - - <%= csrf_meta_tags %> -
    - -<%= render partial: 'layouts/flash_messages' %>
    @@ -50,18 +21,6 @@
    - - - - - - - - - - -<%= yield(:page_bottom) %> - \ No newline at end of file diff --git a/app/views/logs/_form.html.erb b/app/views/logs/_form.html.erb deleted file mode 100644 index fd51552..0000000 --- a/app/views/logs/_form.html.erb +++ /dev/null @@ -1,46 +0,0 @@ -<% @log = decorate(@log, LogDecorator) %> - -<%= form_for([@recipe, @log], html: {class: 'log-form'}) do |f| %> - - <%= render partial: 'shared/error_list', locals: {model: @log} %> - -
    -
    -
    - <%= f.label :date, class: 'control-label' %> - <%= f.text_field :date, class: 'form-control datepicker', value: @log.date %> -
    -
    - -
    -
    - <%= f.label :rating, class: 'control-label' %> - <%= f.text_field :rating, class: 'form-control', data: {rating: 'true'} %> -
    -
    - -
    -
    - <%= f.label :notes, 'Log Notes', class: 'control-label' %> - <%= f.text_area :notes, class: 'form-control' %> -
    -
    - -
    -
    - <%= f.submit class: 'btn btn-primary' %> -
    -
    -
    - - <%= f.fields_for(:recipe, include_id: false) do |rf| %> - <%= render partial: 'recipes/editor', locals: {f: rf} %> - <% end %> -

    - -
    - <%= f.submit class: 'btn btn-primary' %> -
    - -<% end %> - diff --git a/app/views/logs/edit.html.erb b/app/views/logs/edit.html.erb deleted file mode 100644 index 4a704e2..0000000 --- a/app/views/logs/edit.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -
    -
    - - - <%= render 'form' %> - - <%= link_to 'Back', logs_path, class: 'btn btn-default' %> - -
    -
    diff --git a/app/views/logs/index.html.erb b/app/views/logs/index.html.erb deleted file mode 100644 index d0ef92a..0000000 --- a/app/views/logs/index.html.erb +++ /dev/null @@ -1,40 +0,0 @@ -
    -
    - - - - <% if @logs.empty? %> -

    No Entries

    - <% else %> - -
    - - - - - - - - - - - - <% decorate(@logs, LogDecorator).each do |log| %> - - - - - - - <% end %> - -
    RecipeDateRatingNotes
    <%= link_to log.recipe.short_name, log %><%= log.date %><%= text_field_tag('rating', log.rating, disabled: true, data: {rating: true}) %><%= log.notes %>
    -
    - - <% end %> - -
    -
    - diff --git a/app/views/logs/new.html.erb b/app/views/logs/new.html.erb deleted file mode 100644 index 0fd5857..0000000 --- a/app/views/logs/new.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -
    -
    - - - <%= render 'form' %> - - <%= link_to 'Back', recipes_path, class: 'btn btn-default' %> - -
    -
    diff --git a/app/views/logs/show.html.erb b/app/views/logs/show.html.erb deleted file mode 100644 index 7019342..0000000 --- a/app/views/logs/show.html.erb +++ /dev/null @@ -1,92 +0,0 @@ - -<% - @log = decorate(@log, LogDecorator) - @recipe = @log.recipe -%> - -
    - -
    -
    - - -

    Date: <%= @log.date %>

    -

    Rating: <%= text_field_tag('rating', @log.rating, disabled: true, data: {rating: true}) %>

    -

    Notes: <%= @log.notes %>

    - -

    - <%= @recipe.description %> -

    -
    -
    - -
    - <% if @recipe.total_time.present? || @recipe.active_time.present? %> -
    -

    <%= recipe_time(@recipe) %>

    -
    - <% end %> - - <% if @recipe.yields.present? %> -
    -

    Yields

    <%= @recipe.yields %>

    -
    - <% end %> - - <% if @recipe.source.present? %> -
    -

    Source

    <%= @recipe.source_markup %>

    -
    - <% end %> - -
    - -
    -
    -
    -
    - -
    -

    Ingredients

    -
    - - -
    -
    -
      - <% @recipe.recipe_ingredients.each do |i| %> -
    • <%= i.display_name %>
    • - <% end %> -
    -
    -
    - -
    - -
    -
    -
    -

    Directions

    -
    -
    - <%= @recipe.step_text %> -
    -
    -
    -
    - -
    - -
    -
    - - <%= link_to 'Edit', edit_log_path(@log), class: 'btn btn-default' %> - <%= link_to 'Back', logs_path, class: 'btn btn-default' %> - -
    -
    - diff --git a/app/views/notes/_form.html.erb b/app/views/notes/_form.html.erb deleted file mode 100644 index fbb7551..0000000 --- a/app/views/notes/_form.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -<%= form_for(note) do |f| %> - <%= render partial: 'shared/error_list', locals: {model: @note} %> - -
    - <%= f.label :content, 'Note', class: 'control-label' %> - <%= f.text_field :content, class: 'form-control' %> -
    - -
    - <%= f.submit class: 'btn btn-primary' %> - <%= link_to 'Back', notes_path, class: 'btn btn-default' %> -
    -<% end %> diff --git a/app/views/notes/edit.html.erb b/app/views/notes/edit.html.erb deleted file mode 100644 index e20934a..0000000 --- a/app/views/notes/edit.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
    -
    - - - <%= render 'form', note: @note %> - -
    -
    - diff --git a/app/views/notes/index.html.erb b/app/views/notes/index.html.erb deleted file mode 100644 index 12f72a4..0000000 --- a/app/views/notes/index.html.erb +++ /dev/null @@ -1,47 +0,0 @@ -
    -
    - - - <% if @notes.empty? %> -

    No Notes

    - <% else %> - - <%= link_to 'New Note', new_note_path, class: 'btn btn-default' %> - -
    - - - - - - - - - - - - <% decorate(@notes, NoteDecorator).each do |note| %> - - - - - - <% end %> - -
    NoteDate
    <%= note.content %><%= note.created_at %> - <%= link_to note, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-xs btn-danger' do %> - - <% end %> -
    - <% end %> - -
    - - <%= link_to 'New Note', new_note_path, class: 'btn btn-default' %> - - -
    -
    - diff --git a/app/views/notes/new.html.erb b/app/views/notes/new.html.erb deleted file mode 100644 index ee95407..0000000 --- a/app/views/notes/new.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
    -
    - - - <%= render 'form', note: @note %> - -
    -
    - diff --git a/app/views/notes/show.html.erb b/app/views/notes/show.html.erb deleted file mode 100644 index b711b58..0000000 --- a/app/views/notes/show.html.erb +++ /dev/null @@ -1,15 +0,0 @@ -
    -
    - - -

    - <%= @note.content %> -

    - - <%= link_to 'Back', notes_path, class: 'btn btn-default' %> - -
    -
    - diff --git a/app/views/recipes/_editor.html.erb b/app/views/recipes/_editor.html.erb deleted file mode 100644 index d7bc818..0000000 --- a/app/views/recipes/_editor.html.erb +++ /dev/null @@ -1,101 +0,0 @@ - -
    - -
    -
    -
    - <%= f.label :name, class: "control-label" %> - <%= f.text_field :name, class: 'form-control' %> -
    -
    - -
    -
    - <%= f.label :source, class: "control-label" %> - <%= f.text_field :source, class: 'form-control' %> -
    -
    -
    - - -
    - <%= f.label :description, class: "control-label" %> - <%= f.text_area :description, class: 'form-control' %> -
    - -
    - <%= f.label :tag_names, class: "control-label" %> - <%= f.select :tag_names, options_for_select(f.object.tag_names), {}, multiple: true, class: 'form-control tag_names' %> -
    - -
    -
    -
    - <%= f.label :yields, class: "control-label" %> - <%= f.text_field :yields, class: 'form-control', placeholder: 'Servings' %> -
    -
    -
    -
    - <%= f.label :total_time, class: "control-label" %> - <%= f.number_field :total_time, class: 'form-control', placeholder: 'Minutes' %> -
    -
    -
    -
    - <%= f.label :active_time, class: "control-label" %> - <%= f.number_field :active_time, class: 'form-control', placeholder: 'Minutes' %> -
    -
    -
    - - -

    Ingredients

    - -
    - <%= f.fields_for :recipe_ingredients do |ri_form| %> - <%= render partial: 'recipes/editor/ingredient', locals: { f: ri_form } %> - <% end %> -
    - -
    - - <%= link_to_add_association 'Add Ingredient', f, :recipe_ingredients, partial: 'recipes/editor/ingredient', :'data-association-insertion-node' => '#ingredient-list', :'data-association-insertion-method' => 'append', class: 'btn btn-primary', id: 'addIngredientButton' %> - - -

    Steps

    -
    -
    - <%= f.text_area :step_text, class: 'form-control', rows: 15 %> -
    -
    - - <% content_for(:page_bottom) do %> - - <%= render partial: 'recipes/editor/bulk_ingredient_dialog' %> - - - - <% end %> - -
    \ No newline at end of file diff --git a/app/views/recipes/_form.html.erb b/app/views/recipes/_form.html.erb deleted file mode 100644 index 9f9f31b..0000000 --- a/app/views/recipes/_form.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<%= form_for(@recipe, {html: {class: 'recipe-form'}}) do |f| %> - - <%= render partial: 'shared/error_list', locals: {model: @recipe} %> - - <%= render partial: 'editor', locals: {f: f} %> -

    - -
    - <%= f.submit class: 'btn btn-primary' %> -
    -<% end %> diff --git a/app/views/recipes/edit.html.erb b/app/views/recipes/edit.html.erb deleted file mode 100644 index 4ba4b0c..0000000 --- a/app/views/recipes/edit.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -
    -
    - -

    Editing Recipe

    - - <%= render 'form' %> - - <%= link_to 'Show', @recipe, class: 'btn btn-primary' %> | - <%= link_to 'Back', recipes_path, class: 'btn btn-primary' %> - -
    -
    \ No newline at end of file diff --git a/app/views/recipes/editor/_bulk_ingredient_dialog.html.erb b/app/views/recipes/editor/_bulk_ingredient_dialog.html.erb deleted file mode 100644 index c8b9da4..0000000 --- a/app/views/recipes/editor/_bulk_ingredient_dialog.html.erb +++ /dev/null @@ -1,48 +0,0 @@ - \ No newline at end of file diff --git a/app/views/recipes/editor/_bulk_step_dialog.html.erb b/app/views/recipes/editor/_bulk_step_dialog.html.erb deleted file mode 100644 index e407abb..0000000 --- a/app/views/recipes/editor/_bulk_step_dialog.html.erb +++ /dev/null @@ -1,46 +0,0 @@ - \ No newline at end of file diff --git a/app/views/recipes/editor/_conversion_form.html.erb b/app/views/recipes/editor/_conversion_form.html.erb deleted file mode 100644 index 0841085..0000000 --- a/app/views/recipes/editor/_conversion_form.html.erb +++ /dev/null @@ -1,48 +0,0 @@ - - - - diff --git a/app/views/recipes/editor/_ingredient.html.erb b/app/views/recipes/editor/_ingredient.html.erb deleted file mode 100644 index ae4ab29..0000000 --- a/app/views/recipes/editor/_ingredient.html.erb +++ /dev/null @@ -1,57 +0,0 @@ -
    - - -
    -
    - -
    - -
    -
    - <%= f.label :quantity, class: "control-label" %> - <%= f.text_field :quantity, class: 'form-control quantity' %> -
    -
    - -
    -
    - <%= f.label :units, class: "control-label" %> -
    - <%= f.text_field :units, class: 'form-control units' %> - - - -
    -
    -
    - -
    -
    - <%= f.label :name, class: "control-label" %> - <%= f.text_field :name, class: 'form-control ingredient-typeahead custom' %> -
    -
    - -
    -
    - <%= f.label :preparation, class: "control-label" %> - <%= f.text_field :preparation, class: 'form-control preparation' %> -
    -
    - -
    -
    - -
    - <%= link_to_remove_association f, class: 'remove-button' do %> - - <% end %> -
    -
    - - <%= f.hidden_field :ingredient_id, class: 'ingredient_id' %> - <%= f.hidden_field :sort_order, class: 'sort_order' %> - -
    \ No newline at end of file diff --git a/app/views/recipes/editor/_step.html.erb b/app/views/recipes/editor/_step.html.erb deleted file mode 100644 index 533ff90..0000000 --- a/app/views/recipes/editor/_step.html.erb +++ /dev/null @@ -1,25 +0,0 @@ -
    - - -
    -
    - <%= f.object ? f.object.sort_order : '' %> -
    - -
    -
    - <%= f.text_area :step, class: 'form-control step' %> -
    -
    - -
    - <%= link_to_remove_association f, class: 'remove-button' do %> - - <% end %> -
    -
    - - <%= f.hidden_field :sort_order, class: 'sort_order' %> - - -
    \ No newline at end of file diff --git a/app/views/recipes/index.html.erb b/app/views/recipes/index.html.erb deleted file mode 100644 index dc83ce2..0000000 --- a/app/views/recipes/index.html.erb +++ /dev/null @@ -1,96 +0,0 @@ -
    -
    - - - - <% if current_user? %> - <%= link_to 'New Recipe', new_recipe_path, class: 'btn btn-default' %>
    - <% end %> - - <%= paginate @recipes %> - - <%= form_for(@criteria, as: :criteria, url: recipes_path, method: :get, html: {id: 'search_form'}) do |f| %> - <%= f.hidden_field :sort_column %> - <%= f.hidden_field :sort_direction %> - <%= f.hidden_field :page %> - <%= f.hidden_field :per %> - <%= f.hidden_field :name %> - <%= f.hidden_field :tags %> - <% end %> - -
    - - - - - - - - - - - - - - - - - - - - - - - - <% decorate(@recipes, RecipeDecorator).each do |recipe| %> - - - - - - - - - - - <% end %> - -
    <%= index_sort_header('Name', :name, @criteria) %>Tags<%= index_sort_header('Rating', :rating, @criteria) %>Yields<%= index_sort_header('Time', :total_time, @criteria) %><%= index_sort_header('Created', :created_at, @criteria) %>
    <%= text_field_tag('name_search', @criteria.name) %><%= text_field_tag('tags_search', @criteria.tags) %>
    <%= link_to recipe.short_name, recipe %>
    <%= recipe.tag_names %>
    - <% if recipe.rating %> - <%= text_field_tag('rating', recipe.rating, disabled: true, data: {rating: true, size: '20px', interval: '0.25'}) %> - <% else %> - -- - <% end %> - <%= recipe.yields %><%= recipe_time(recipe) %><%= recipe.created_at %> - <% if current_user? %> -
    - <%= link_to new_recipe_log_path(recipe), class: 'btn btn-xs btn-primary' do %> - - <% end %> - <%= link_to edit_recipe_path(recipe), class: 'btn btn-xs btn-primary' do %> - - <% end %> - <%= link_to recipe, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-xs btn-danger' do %> - - <% end %> -
    - <% end %> -
    -
    - - <% if @recipes.empty? %> -

    No Recipes

    - <% end %> - - <%= paginate @recipes %> - -
    - - <% if current_user? %> - <%= link_to 'New Recipe', new_recipe_path, class: 'btn btn-default' %>
    - <% end %> - -
    -
    diff --git a/app/views/recipes/new.html.erb b/app/views/recipes/new.html.erb deleted file mode 100644 index ba2bb67..0000000 --- a/app/views/recipes/new.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -
    -
    - - - <%= render 'form' %> - - <%= link_to 'Back', recipes_path, class: 'btn btn-default' %> - -
    -
    \ No newline at end of file diff --git a/app/views/recipes/show.html.erb b/app/views/recipes/show.html.erb deleted file mode 100644 index 585bb6a..0000000 --- a/app/views/recipes/show.html.erb +++ /dev/null @@ -1,203 +0,0 @@ - -
    - -
    -
    - -

    - <%= @recipe.description %> -

    -
    -
    - -
    - <% if @recipe.total_time.present? || @recipe.active_time.present? %> -
    -

    <%= recipe_time(@recipe) %>

    -
    - <% end %> - - <% if @recipe.yields.present? %> -
    -

    Yields

    <%= @recipe.yields %>

    -
    - <% end %> - - <% if @recipe.source.present? %> -
    -

    Source

    <%= @recipe.source_markup %>

    -
    - <% end %> - -
    - -
    -
    -
    -
    - -
    -

    Ingredients

    - -
    - - -
    -
    -
      - <% @recipe.recipe_ingredients.each do |i| %> -
    • <%= i.display_name %>
    • - <% end %> -
    -
    -
    - -
    - -
    -
    -
    -

    Directions

    -
    -
    - <%= @recipe.step_text %> -
    -
    -
    -
    - -
    -
    -
    - -
    - <% decorate(@recipe.nutrition_data, NutritionDataDecorator) do |nutrition_data| %> - - - - - <% if @recipe.parsed_yield %> - - <% end %> - - - - - <% NutritionData::NUTRIENTS.select { |_, v| v.present? }.each do |k, v| %> - <%= nutrient_row(@recipe, nutrition_data, v, k) %> - <% end %> -
    Item<%= @recipe.parsed_yield.label %>Total
    - <% end %> - -

    Nutrition Calculation Warnings

    - -
      - <% @recipe.nutrition_data.errors.each do |err| %> -
    • <%= err %>
    • - <% end %> -
    -
    -
    -
    -
    - -
    - -
    -
    - - <%= link_to 'Edit', edit_recipe_path(@recipe), class: 'btn btn-default' %> - <%= link_to 'Back', recipes_path, class: 'btn btn-default' %> - -
    -
    - - \ No newline at end of file diff --git a/app/views/shared/_error_list.html.erb b/app/views/shared/_error_list.html.erb deleted file mode 100644 index 8ad7638..0000000 --- a/app/views/shared/_error_list.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<% if model.errors.any? %> -
    -

    <%= pluralize(model.errors.count, 'error') %> prohibited this <%= model.model_name.human %> from being saved:

    - -
      - <% model.errors.full_messages.each do |msg| %> -
    • <%= msg %>
    • - <% end %> -
    -
    -<% end %> \ No newline at end of file diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb deleted file mode 100644 index 621dd1f..0000000 --- a/app/views/users/_form.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -<%= form_for(@user, url: user_path) do |f| %> - - <%= render partial: 'shared/error_list', locals: {model: @user} %> - -
    - <%= f.label :username, class: 'control-label' %> - <%= f.text_field :username, autofocus: true, class: 'form-control' %> -
    -
    - <%= f.label :full_name, 'Name', class: 'control-label' %> - <%= f.text_field :full_name, class: 'form-control' %> -
    -
    - <%= f.label :email, class: 'control-label' %> - <%= f.text_field :email, class: 'form-control' %> -
    -
    - <%= f.label :password, class: 'control-label' %> - <%= f.password_field :password, class: 'form-control' %> -
    -
    - <%= f.label :password_confirmation, class: 'control-label' %> - <%= f.password_field :password_confirmation, class: 'form-control' %> -
    - -
    - <%= f.submit class: 'btn btn-primary' %> - <%= link_to "Back", root_path, class: 'btn btn-default' %> -
    -<% end %> diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb deleted file mode 100644 index d15fd3f..0000000 --- a/app/views/users/edit.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
    -
    - - - - <%= render partial: 'form' %> - -
    -
    diff --git a/app/views/users/login.html.erb b/app/views/users/login.html.erb deleted file mode 100644 index c9a58ca..0000000 --- a/app/views/users/login.html.erb +++ /dev/null @@ -1,31 +0,0 @@ - - -
    -
    - - - - - <%= form_tag(login_path, :method => :post) do %> - -
    - <%= label_tag :username, "Username", class: 'control-label' %> - <%= text_field_tag :username, nil, autofocus: true, class: 'form-control' %> -
    - -
    - <%= label_tag :password, "Password", class: 'control-label' %> - <%= password_field_tag :password, nil, class: 'form-control' %> -
    - - <%= submit_tag("Login", class: 'btn btn-primary') %> - <% end %> - -
    - - <%= link_to "Create an Account", new_user_path, class: 'btn btn-default' %> - -
    -
    \ No newline at end of file diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb deleted file mode 100644 index 39b2b52..0000000 --- a/app/views/users/new.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
    -
    - - - - <%= render partial: 'form' %> - -
    -
    diff --git a/vendor/assets/fonts/inconsolata-bold.woff2 b/vendor/assets/fonts/inconsolata-bold.woff2 deleted file mode 100644 index 2e0f28257256ab0f513a48fd46b8f855672d5920..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11008 zcmV+bEC1AYPew8T0RR9104o3h4gdfE09DWc04k{f0RR9100000000000000000000 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 diff --git a/vendor/assets/fonts/inconsolata.woff2 b/vendor/assets/fonts/inconsolata.woff2 deleted file mode 100644 index 1347eb54c22ae839b13159e37e8a023fd7861ba1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9564 zcmV-iC8OGRPew8T0RR9103}=i4gdfE08VrO03`(g0RR9100000000000000000000 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 GKo9`#5?smv diff --git a/vendor/assets/fonts/news-cycle-bold.woff2 b/vendor/assets/fonts/news-cycle-bold.woff2 deleted file mode 100644 index 864e145e2eb13aed31f891cae51bf1d7b4c9bea9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13392 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 diff --git a/vendor/assets/fonts/news-cycle.woff2 b/vendor/assets/fonts/news-cycle.woff2 deleted file mode 100644 index 0762465f47bca03f772dc1b691ce26546ee3a42f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12600 zcmV-8F~`n#Pew8T0RR9105LcK4gdfE0BtM)05ISH0D_MI00000000000000000000 z0000QBpb|19CQX&0D)8y2nzK~-Dd$d0we>61Pg;i00bZff+7cmaT|+XRYnKr0YxC) ze4r>w7b!L(CFj2E|BnUQh@t3#Uu~tRg$8jFilP9`MpG1vx{lSv;+*#Cy?W~Ip8KRp zAvs5W;;Ta3djEw2Eoc z)Z{fgo$$ct+5fpg#Z;*>W(xlF8J&6JC%9t1=*3D~4#74%ospX{12d+WOdABD4G_gb zLIp*gU}GT)qCIELs)h4s^deolD7SYNE+Tn|)&c)!XZAk8#6+WhS20u7NKgcEJA9t+ z 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 iFvf%YV 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 nmV&H5?L=-UWr^^lsjTkygz6 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 diff --git a/vendor/assets/fonts/open-sans-light.woff2 b/vendor/assets/fonts/open-sans-light.woff2 deleted file mode 100644 index cf3ec55eef07d76f2a63b09de4a18973895ee4cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10200 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 diff --git a/vendor/assets/fonts/raleway-bold.woff2 b/vendor/assets/fonts/raleway-bold.woff2 deleted file mode 100644 index 885b5998f37ef46f728226cafa073fcd29cd6241..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15008 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∋*w}z>&mY4CqlpSQeqpq4d;j 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 OuMBQiZEso$5&!^o%n_Ra diff --git a/vendor/assets/fonts/roboto.woff2 b/vendor/assets/fonts/roboto.woff2 deleted file mode 100644 index d1035f9a104819cdd70d3694683c53ce8d9580ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10292 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 GRf+>&>*#?1 diff --git a/vendor/assets/images/chosen-sprite.png b/vendor/assets/images/chosen-sprite.png deleted file mode 100644 index c57da70b4b5b1e08a6977ddde182677af0e5e1b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmV+#0_FXQP)cz2)-WJLkv8J@4bb5L`rsE?Kc|FrXHkKz)ov z76MHYM&Apx%05P7orE!>9=yZ~6O0^V?1%{=1UASqa<2Pgnk7fs!OIs9gh{NCN+@=) z>Gfttd5uq;oeR{%NHjtqV~jEQeY?tDff=(jqx>~SZ_e+iN26HR*`0Q!Re)~HD85p> zbL()Mw}bI^#`7wp0+cv&7*LhrtOmR)?PK>(-BeLm#jL5Jfogv-QS(TBnUb;))Krqm zD}uDDeVLNhm1G*pFB`O?iA=dnWBEpqHk8Yh%Qu45EIG=&F-dDmt|;|nN@|3lOkVZ7>z*~a1?_t?U)c+&|JFJke1`&0-a z#PjhRlg?=$KTo4|rU@NyV_fzDy@>h!lVyKShsO8>V>$xyIXRbHK%H~^Aaz=s$Jz^V zlb?KfaKdZqu3^#m$mintvgJ15@j`sb2Zr%69Sn=xN01Tm5r)NQanT=jhwm7zqj2>O cEB}D~0$b-QdD7|v=>Px#07*qoM6N<$g6AXnUH||9 diff --git a/vendor/assets/images/chosen-sprite@2x.png b/vendor/assets/images/chosen-sprite@2x.png deleted file mode 100644 index 6b50545202cb4770039362c55025b0b9824663ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 738 zcmV<80v-K{P)oJoIWh{eAG@xkM<0ryd(K3(} zP8JV&;uuIJ4nL%g8!wSG9E$P+3QVMGgj><+00}M5I5kMzaT<~M;uJ`UhLfbp9Ahdsrux5(g+(>Q*+9wU{AuYPH0}W_u4`|q(9c->{ zt>Jn|lbhH<_x5jU6prFi#S}&XMZ=~Y5VyC3+ZN%hXciz8 zPcLpJgbIK#a49e31-%wf2zh2F&&(Nq;AL%4zA(=QJRGq`sx3y3#0_cg9Fim739XTOu1NKKjlWs`52Q+3 Uja*K~(*OVf07*qoM6N<$g3mu-GXMYp diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/assets/javascripts/autosize.js b/vendor/assets/javascripts/autosize.js deleted file mode 100644 index cfa49e7..0000000 --- a/vendor/assets/javascripts/autosize.js +++ /dev/null @@ -1,243 +0,0 @@ -/*! - Autosize 3.0.14 - license: MIT - http://www.jacklmoore.com/autosize -*/ -(function (global, factory) { - if (typeof define === 'function' && define.amd) { - define(['exports', 'module'], factory); - } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') { - factory(exports, module); - } else { - var mod = { - exports: {} - }; - factory(mod.exports, mod); - global.autosize = mod.exports; - } -})(this, function (exports, module) { - 'use strict'; - - var set = typeof Set === 'function' ? new Set() : (function () { - var list = []; - - return { - has: function has(key) { - return Boolean(list.indexOf(key) > -1); - }, - add: function add(key) { - list.push(key); - }, - 'delete': function _delete(key) { - list.splice(list.indexOf(key), 1); - } }; - })(); - - function assign(ta) { - var _ref = arguments[1] === undefined ? {} : arguments[1]; - - var _ref$setOverflowX = _ref.setOverflowX; - var setOverflowX = _ref$setOverflowX === undefined ? true : _ref$setOverflowX; - var _ref$setOverflowY = _ref.setOverflowY; - var setOverflowY = _ref$setOverflowY === undefined ? true : _ref$setOverflowY; - - if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || set.has(ta)) return; - - var heightOffset = null; - var overflowY = null; - var clientWidth = ta.clientWidth; - - function init() { - var style = window.getComputedStyle(ta, null); - - overflowY = style.overflowY; - - if (style.resize === 'vertical') { - ta.style.resize = 'none'; - } else if (style.resize === 'both') { - ta.style.resize = 'horizontal'; - } - - if (style.boxSizing === 'content-box') { - heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)); - } else { - heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); - } - // Fix when a textarea is not on document body and heightOffset is Not a Number - if (isNaN(heightOffset)) { - heightOffset = 0; - } - - update(); - } - - function changeOverflow(value) { - { - // Chrome/Safari-specific fix: - // When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space - // made available by removing the scrollbar. The following forces the necessary text reflow. - var width = ta.style.width; - ta.style.width = '0px'; - // Force reflow: - /* jshint ignore:start */ - ta.offsetWidth; - /* jshint ignore:end */ - ta.style.width = width; - } - - overflowY = value; - - if (setOverflowY) { - ta.style.overflowY = value; - } - - resize(); - } - - function resize() { - var htmlTop = window.pageYOffset; - var bodyTop = document.body.scrollTop; - var originalHeight = ta.style.height; - - ta.style.height = 'auto'; - - var endHeight = ta.scrollHeight + heightOffset; - - if (ta.scrollHeight === 0) { - // If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM. - ta.style.height = originalHeight; - return; - } - - ta.style.height = endHeight + 'px'; - - // used to check if an update is actually necessary on window.resize - clientWidth = ta.clientWidth; - - // prevents scroll-position jumping - document.documentElement.scrollTop = htmlTop; - document.body.scrollTop = bodyTop; - } - - function update() { - var startHeight = ta.style.height; - - resize(); - - var style = window.getComputedStyle(ta, null); - - if (style.height !== ta.style.height) { - if (overflowY !== 'visible') { - changeOverflow('visible'); - } - } else { - if (overflowY !== 'hidden') { - changeOverflow('hidden'); - } - } - - if (startHeight !== ta.style.height) { - var evt = document.createEvent('Event'); - evt.initEvent('autosize:resized', true, false); - ta.dispatchEvent(evt); - } - } - - var pageResize = function pageResize() { - if (ta.clientWidth !== clientWidth) { - update(); - } - }; - - var destroy = (function (style) { - window.removeEventListener('resize', pageResize, false); - ta.removeEventListener('input', update, false); - ta.removeEventListener('keyup', update, false); - ta.removeEventListener('autosize:destroy', destroy, false); - ta.removeEventListener('autosize:update', update, false); - set['delete'](ta); - - Object.keys(style).forEach(function (key) { - ta.style[key] = style[key]; - }); - }).bind(ta, { - height: ta.style.height, - resize: ta.style.resize, - overflowY: ta.style.overflowY, - overflowX: ta.style.overflowX, - wordWrap: ta.style.wordWrap }); - - ta.addEventListener('autosize:destroy', destroy, false); - - // IE9 does not fire onpropertychange or oninput for deletions, - // so binding to onkeyup to catch most of those events. - // There is no way that I know of to detect something like 'cut' in IE9. - if ('onpropertychange' in ta && 'oninput' in ta) { - ta.addEventListener('keyup', update, false); - } - - window.addEventListener('resize', pageResize, false); - ta.addEventListener('input', update, false); - ta.addEventListener('autosize:update', update, false); - set.add(ta); - - if (setOverflowX) { - ta.style.overflowX = 'hidden'; - ta.style.wordWrap = 'break-word'; - } - - init(); - } - - function destroy(ta) { - if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return; - var evt = document.createEvent('Event'); - evt.initEvent('autosize:destroy', true, false); - ta.dispatchEvent(evt); - } - - function update(ta) { - if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return; - var evt = document.createEvent('Event'); - evt.initEvent('autosize:update', true, false); - ta.dispatchEvent(evt); - } - - var autosize = null; - - // Do nothing in Node.js environment and IE8 (or lower) - if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') { - autosize = function (el) { - return el; - }; - autosize.destroy = function (el) { - return el; - }; - autosize.update = function (el) { - return el; - }; - } else { - autosize = function (el, options) { - if (el) { - Array.prototype.forEach.call(el.length ? el : [el], function (x) { - return assign(x, options); - }); - } - return el; - }; - autosize.destroy = function (el) { - if (el) { - Array.prototype.forEach.call(el.length ? el : [el], destroy); - } - return el; - }; - autosize.update = function (el) { - if (el) { - Array.prototype.forEach.call(el.length ? el : [el], update); - } - return el; - }; - } - - module.exports = autosize; -}); \ No newline at end of file diff --git a/vendor/assets/javascripts/bootstrap-datepicker.js b/vendor/assets/javascripts/bootstrap-datepicker.js deleted file mode 100644 index d2faff6..0000000 --- a/vendor/assets/javascripts/bootstrap-datepicker.js +++ /dev/null @@ -1,2089 +0,0 @@ -/*! - * Datepicker for Bootstrap v1.6.1 (https://github.com/eternicode/bootstrap-datepicker) - * - * Copyright 2012 Stefan Petre - * Improvements by Andrew Rowls - * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - */(function(factory){ - if (typeof define === "function" && define.amd) { - define(["jquery"], factory); - } else if (typeof exports === 'object') { - factory(require('jquery')); - } else { - factory(jQuery); - } -}(function($, undefined){ - - function UTCDate(){ - return new Date(Date.UTC.apply(Date, arguments)); - } - function UTCToday(){ - var today = new Date(); - return UTCDate(today.getFullYear(), today.getMonth(), today.getDate()); - } - function isUTCEquals(date1, date2) { - return ( - date1.getUTCFullYear() === date2.getUTCFullYear() && - date1.getUTCMonth() === date2.getUTCMonth() && - date1.getUTCDate() === date2.getUTCDate() - ); - } - function alias(method){ - return function(){ - return this[method].apply(this, arguments); - }; - } - function isValidDate(d) { - return d && !isNaN(d.getTime()); - } - - var DateArray = (function(){ - var extras = { - get: function(i){ - return this.slice(i)[0]; - }, - contains: function(d){ - // Array.indexOf is not cross-browser; - // $.inArray doesn't work with Dates - var val = d && d.valueOf(); - for (var i=0, l=this.length; i < l; i++) - if (this[i].valueOf() === val) - return i; - return -1; - }, - remove: function(i){ - this.splice(i,1); - }, - replace: function(new_array){ - if (!new_array) - return; - if (!$.isArray(new_array)) - new_array = [new_array]; - this.clear(); - this.push.apply(this, new_array); - }, - clear: function(){ - this.length = 0; - }, - copy: function(){ - var a = new DateArray(); - a.replace(this); - return a; - } - }; - - return function(){ - var a = []; - a.push.apply(a, arguments); - $.extend(a, extras); - return a; - }; - })(); - - - // Picker object - - var Datepicker = function(element, options){ - $(element).data('datepicker', this); - this._process_options(options); - - this.dates = new DateArray(); - this.viewDate = this.o.defaultViewDate; - this.focusDate = null; - - this.element = $(element); - this.isInput = this.element.is('input'); - this.inputField = this.isInput ? this.element : this.element.find('input'); - this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false; - this.hasInput = this.component && this.inputField.length; - if (this.component && this.component.length === 0) - this.component = false; - this.isInline = !this.component && this.element.is('div'); - - this.picker = $(DPGlobal.template); - - // Checking templates and inserting - if (this._check_template(this.o.templates.leftArrow)) { - this.picker.find('.prev').html(this.o.templates.leftArrow); - } - if (this._check_template(this.o.templates.rightArrow)) { - this.picker.find('.next').html(this.o.templates.rightArrow); - } - - this._buildEvents(); - this._attachEvents(); - - if (this.isInline){ - this.picker.addClass('datepicker-inline').appendTo(this.element); - } - else { - this.picker.addClass('datepicker-dropdown dropdown-menu'); - } - - if (this.o.rtl){ - this.picker.addClass('datepicker-rtl'); - } - - this.viewMode = this.o.startView; - - if (this.o.calendarWeeks) - this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear') - .attr('colspan', function(i, val){ - return parseInt(val) + 1; - }); - - this._allow_update = false; - - this.setStartDate(this._o.startDate); - this.setEndDate(this._o.endDate); - this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled); - this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted); - this.setDatesDisabled(this.o.datesDisabled); - - this.fillDow(); - this.fillMonths(); - - this._allow_update = true; - - this.update(); - this.showMode(); - - if (this.isInline){ - this.show(); - } - }; - - Datepicker.prototype = { - constructor: Datepicker, - - _resolveViewName: function(view, default_value){ - if (view === 0 || view === 'days' || view === 'month') { - return 0; - } - if (view === 1 || view === 'months' || view === 'year') { - return 1; - } - if (view === 2 || view === 'years' || view === 'decade') { - return 2; - } - if (view === 3 || view === 'decades' || view === 'century') { - return 3; - } - if (view === 4 || view === 'centuries' || view === 'millennium') { - return 4; - } - return default_value === undefined ? false : default_value; - }, - - _check_template: function(tmp){ - try { - // If empty - if (tmp === undefined || tmp === "") { - return false; - } - // If no html, everything ok - if ((tmp.match(/[<>]/g) || []).length <= 0) { - return true; - } - // Checking if html is fine - var jDom = $(tmp); - return jDom.length > 0; - } - catch (ex) { - return false; - } - }, - - _process_options: function(opts){ - // Store raw options for reference - this._o = $.extend({}, this._o, opts); - // Processed options - var o = this.o = $.extend({}, this._o); - - // Check if "de-DE" style date is available, if not language should - // fallback to 2 letter code eg "de" - var lang = o.language; - if (!dates[lang]){ - lang = lang.split('-')[0]; - if (!dates[lang]) - lang = defaults.language; - } - o.language = lang; - - // Retrieve view index from any aliases - o.startView = this._resolveViewName(o.startView, 0); - o.minViewMode = this._resolveViewName(o.minViewMode, 0); - o.maxViewMode = this._resolveViewName(o.maxViewMode, 4); - - // Check that the start view is between min and max - o.startView = Math.min(o.startView, o.maxViewMode); - o.startView = Math.max(o.startView, o.minViewMode); - - // true, false, or Number > 0 - if (o.multidate !== true){ - o.multidate = Number(o.multidate) || false; - if (o.multidate !== false) - o.multidate = Math.max(0, o.multidate); - } - o.multidateSeparator = String(o.multidateSeparator); - - o.weekStart %= 7; - o.weekEnd = (o.weekStart + 6) % 7; - - var format = DPGlobal.parseFormat(o.format); - if (o.startDate !== -Infinity){ - if (!!o.startDate){ - if (o.startDate instanceof Date) - o.startDate = this._local_to_utc(this._zero_time(o.startDate)); - else - o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear); - } - else { - o.startDate = -Infinity; - } - } - if (o.endDate !== Infinity){ - if (!!o.endDate){ - if (o.endDate instanceof Date) - o.endDate = this._local_to_utc(this._zero_time(o.endDate)); - else - o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear); - } - else { - o.endDate = Infinity; - } - } - - o.daysOfWeekDisabled = o.daysOfWeekDisabled||[]; - if (!$.isArray(o.daysOfWeekDisabled)) - o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/); - o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){ - return parseInt(d, 10); - }); - - o.daysOfWeekHighlighted = o.daysOfWeekHighlighted||[]; - if (!$.isArray(o.daysOfWeekHighlighted)) - o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/); - o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d){ - return parseInt(d, 10); - }); - - o.datesDisabled = o.datesDisabled||[]; - if (!$.isArray(o.datesDisabled)) { - o.datesDisabled = [ - o.datesDisabled - ]; - } - o.datesDisabled = $.map(o.datesDisabled,function(d){ - return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear); - }); - - var plc = String(o.orientation).toLowerCase().split(/\s+/g), - _plc = o.orientation.toLowerCase(); - plc = $.grep(plc, function(word){ - return /^auto|left|right|top|bottom$/.test(word); - }); - o.orientation = {x: 'auto', y: 'auto'}; - if (!_plc || _plc === 'auto') - ; // no action - else if (plc.length === 1){ - switch (plc[0]){ - case 'top': - case 'bottom': - o.orientation.y = plc[0]; - break; - case 'left': - case 'right': - o.orientation.x = plc[0]; - break; - } - } - else { - _plc = $.grep(plc, function(word){ - return /^left|right$/.test(word); - }); - o.orientation.x = _plc[0] || 'auto'; - - _plc = $.grep(plc, function(word){ - return /^top|bottom$/.test(word); - }); - o.orientation.y = _plc[0] || 'auto'; - } - if (o.defaultViewDate) { - var year = o.defaultViewDate.year || new Date().getFullYear(); - var month = o.defaultViewDate.month || 0; - var day = o.defaultViewDate.day || 1; - o.defaultViewDate = UTCDate(year, month, day); - } else { - o.defaultViewDate = UTCToday(); - } - }, - _events: [], - _secondaryEvents: [], - _applyEvents: function(evs){ - for (var i=0, el, ch, ev; i < evs.length; i++){ - el = evs[i][0]; - if (evs[i].length === 2){ - ch = undefined; - ev = evs[i][1]; - } - else if (evs[i].length === 3){ - ch = evs[i][1]; - ev = evs[i][2]; - } - el.on(ev, ch); - } - }, - _unapplyEvents: function(evs){ - for (var i=0, el, ev, ch; i < evs.length; i++){ - el = evs[i][0]; - if (evs[i].length === 2){ - ch = undefined; - ev = evs[i][1]; - } - else if (evs[i].length === 3){ - ch = evs[i][1]; - ev = evs[i][2]; - } - el.off(ev, ch); - } - }, - _buildEvents: function(){ - var events = { - keyup: $.proxy(function(e){ - if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1) - this.update(); - }, this), - keydown: $.proxy(this.keydown, this), - paste: $.proxy(this.paste, this) - }; - - if (this.o.showOnFocus === true) { - events.focus = $.proxy(this.show, this); - } - - if (this.isInput) { // single input - this._events = [ - [this.element, events] - ]; - } - else if (this.component && this.hasInput) { // component: input + button - this._events = [ - // For components that are not readonly, allow keyboard nav - [this.inputField, events], - [this.component, { - click: $.proxy(this.show, this) - }] - ]; - } - else { - this._events = [ - [this.element, { - click: $.proxy(this.show, this), - keydown: $.proxy(this.keydown, this) - }] - ]; - } - this._events.push( - // Component: listen for blur on element descendants - [this.element, '*', { - blur: $.proxy(function(e){ - this._focused_from = e.target; - }, this) - }], - // Input: listen for blur on element - [this.element, { - blur: $.proxy(function(e){ - this._focused_from = e.target; - }, this) - }] - ); - - if (this.o.immediateUpdates) { - // Trigger input updates immediately on changed year/month - this._events.push([this.element, { - 'changeYear changeMonth': $.proxy(function(e){ - this.update(e.date); - }, this) - }]); - } - - this._secondaryEvents = [ - [this.picker, { - click: $.proxy(this.click, this) - }], - [$(window), { - resize: $.proxy(this.place, this) - }], - [$(document), { - mousedown: $.proxy(function(e){ - // Clicked outside the datepicker, hide it - if (!( - this.element.is(e.target) || - this.element.find(e.target).length || - this.picker.is(e.target) || - this.picker.find(e.target).length || - this.isInline - )){ - this.hide(); - } - }, this) - }] - ]; - }, - _attachEvents: function(){ - this._detachEvents(); - this._applyEvents(this._events); - }, - _detachEvents: function(){ - this._unapplyEvents(this._events); - }, - _attachSecondaryEvents: function(){ - this._detachSecondaryEvents(); - this._applyEvents(this._secondaryEvents); - }, - _detachSecondaryEvents: function(){ - this._unapplyEvents(this._secondaryEvents); - }, - _trigger: function(event, altdate){ - var date = altdate || this.dates.get(-1), - local_date = this._utc_to_local(date); - - this.element.trigger({ - type: event, - date: local_date, - dates: $.map(this.dates, this._utc_to_local), - format: $.proxy(function(ix, format){ - if (arguments.length === 0){ - ix = this.dates.length - 1; - format = this.o.format; - } - else if (typeof ix === 'string'){ - format = ix; - ix = this.dates.length - 1; - } - format = format || this.o.format; - var date = this.dates.get(ix); - return DPGlobal.formatDate(date, format, this.o.language); - }, this) - }); - }, - - show: function(){ - if (this.inputField.prop('disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false)) - return; - if (!this.isInline) - this.picker.appendTo(this.o.container); - this.place(); - this.picker.show(); - this._attachSecondaryEvents(); - this._trigger('show'); - if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) { - $(this.element).blur(); - } - return this; - }, - - hide: function(){ - if (this.isInline || !this.picker.is(':visible')) - return this; - this.focusDate = null; - this.picker.hide().detach(); - this._detachSecondaryEvents(); - this.viewMode = this.o.startView; - this.showMode(); - - if (this.o.forceParse && this.inputField.val()) - this.setValue(); - this._trigger('hide'); - return this; - }, - - destroy: function(){ - this.hide(); - this._detachEvents(); - this._detachSecondaryEvents(); - this.picker.remove(); - delete this.element.data().datepicker; - if (!this.isInput){ - delete this.element.data().date; - } - return this; - }, - - paste: function(evt){ - var dateString; - if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types - && $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) { - dateString = evt.originalEvent.clipboardData.getData('text/plain'); - } - else if (window.clipboardData) { - dateString = window.clipboardData.getData('Text'); - } - else { - return; - } - this.setDate(dateString); - this.update(); - evt.preventDefault(); - }, - - _utc_to_local: function(utc){ - return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000)); - }, - _local_to_utc: function(local){ - return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000)); - }, - _zero_time: function(local){ - return local && new Date(local.getFullYear(), local.getMonth(), local.getDate()); - }, - _zero_utc_time: function(utc){ - return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate())); - }, - - getDates: function(){ - return $.map(this.dates, this._utc_to_local); - }, - - getUTCDates: function(){ - return $.map(this.dates, function(d){ - return new Date(d); - }); - }, - - getDate: function(){ - return this._utc_to_local(this.getUTCDate()); - }, - - getUTCDate: function(){ - var selected_date = this.dates.get(-1); - if (typeof selected_date !== 'undefined') { - return new Date(selected_date); - } else { - return null; - } - }, - - clearDates: function(){ - if (this.inputField) { - this.inputField.val(''); - } - - this.update(); - this._trigger('changeDate'); - - if (this.o.autoclose) { - this.hide(); - } - }, - setDates: function(){ - var args = $.isArray(arguments[0]) ? arguments[0] : arguments; - this.update.apply(this, args); - this._trigger('changeDate'); - this.setValue(); - return this; - }, - - setUTCDates: function(){ - var args = $.isArray(arguments[0]) ? arguments[0] : arguments; - this.update.apply(this, $.map(args, this._utc_to_local)); - this._trigger('changeDate'); - this.setValue(); - return this; - }, - - setDate: alias('setDates'), - setUTCDate: alias('setUTCDates'), - remove: alias('destroy'), - - setValue: function(){ - var formatted = this.getFormattedDate(); - this.inputField.val(formatted); - return this; - }, - - getFormattedDate: function(format){ - if (format === undefined) - format = this.o.format; - - var lang = this.o.language; - return $.map(this.dates, function(d){ - return DPGlobal.formatDate(d, format, lang); - }).join(this.o.multidateSeparator); - }, - - getStartDate: function(){ - return this.o.startDate; - }, - - setStartDate: function(startDate){ - this._process_options({startDate: startDate}); - this.update(); - this.updateNavArrows(); - return this; - }, - - getEndDate: function(){ - return this.o.endDate; - }, - - setEndDate: function(endDate){ - this._process_options({endDate: endDate}); - this.update(); - this.updateNavArrows(); - return this; - }, - - setDaysOfWeekDisabled: function(daysOfWeekDisabled){ - this._process_options({daysOfWeekDisabled: daysOfWeekDisabled}); - this.update(); - this.updateNavArrows(); - return this; - }, - - setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){ - this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted}); - this.update(); - return this; - }, - - setDatesDisabled: function(datesDisabled){ - this._process_options({datesDisabled: datesDisabled}); - this.update(); - this.updateNavArrows(); - }, - - place: function(){ - if (this.isInline) - return this; - var calendarWidth = this.picker.outerWidth(), - calendarHeight = this.picker.outerHeight(), - visualPadding = 10, - container = $(this.o.container), - windowWidth = container.width(), - scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(), - appendOffset = container.offset(); - - var parentsZindex = []; - this.element.parents().each(function(){ - var itemZIndex = $(this).css('z-index'); - if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex)); - }); - var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset; - var offset = this.component ? this.component.parent().offset() : this.element.offset(); - var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false); - var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false); - var left = offset.left - appendOffset.left, - top = offset.top - appendOffset.top; - - if (this.o.container !== 'body') { - top += scrollTop; - } - - this.picker.removeClass( - 'datepicker-orient-top datepicker-orient-bottom '+ - 'datepicker-orient-right datepicker-orient-left' - ); - - if (this.o.orientation.x !== 'auto'){ - this.picker.addClass('datepicker-orient-' + this.o.orientation.x); - if (this.o.orientation.x === 'right') - left -= calendarWidth - width; - } - // auto x orientation is best-placement: if it crosses a window - // edge, fudge it sideways - else { - if (offset.left < 0) { - // component is outside the window on the left side. Move it into visible range - this.picker.addClass('datepicker-orient-left'); - left -= offset.left - visualPadding; - } else if (left + calendarWidth > windowWidth) { - // the calendar passes the widow right edge. Align it to component right side - this.picker.addClass('datepicker-orient-right'); - left += width - calendarWidth; - } else { - // Default to left - this.picker.addClass('datepicker-orient-left'); - } - } - - // auto y orientation is best-situation: top or bottom, no fudging, - // decision based on which shows more of the calendar - var yorient = this.o.orientation.y, - top_overflow; - if (yorient === 'auto'){ - top_overflow = -scrollTop + top - calendarHeight; - yorient = top_overflow < 0 ? 'bottom' : 'top'; - } - - this.picker.addClass('datepicker-orient-' + yorient); - if (yorient === 'top') - top -= calendarHeight + parseInt(this.picker.css('padding-top')); - else - top += height; - - if (this.o.rtl) { - var right = windowWidth - (left + width); - this.picker.css({ - top: top, - right: right, - zIndex: zIndex - }); - } else { - this.picker.css({ - top: top, - left: left, - zIndex: zIndex - }); - } - return this; - }, - - _allow_update: true, - update: function(){ - if (!this._allow_update) - return this; - - var oldDates = this.dates.copy(), - dates = [], - fromArgs = false; - if (arguments.length){ - $.each(arguments, $.proxy(function(i, date){ - if (date instanceof Date) - date = this._local_to_utc(date); - dates.push(date); - }, this)); - fromArgs = true; - } - else { - dates = this.isInput - ? this.element.val() - : this.element.data('date') || this.inputField.val(); - if (dates && this.o.multidate) - dates = dates.split(this.o.multidateSeparator); - else - dates = [dates]; - delete this.element.data().date; - } - - dates = $.map(dates, $.proxy(function(date){ - return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear); - }, this)); - dates = $.grep(dates, $.proxy(function(date){ - return ( - !this.dateWithinRange(date) || - !date - ); - }, this), true); - this.dates.replace(dates); - - if (this.dates.length) - this.viewDate = new Date(this.dates.get(-1)); - else if (this.viewDate < this.o.startDate) - this.viewDate = new Date(this.o.startDate); - else if (this.viewDate > this.o.endDate) - this.viewDate = new Date(this.o.endDate); - else - this.viewDate = this.o.defaultViewDate; - - if (fromArgs){ - // setting date by clicking - this.setValue(); - } - else if (dates.length){ - // setting date by typing - if (String(oldDates) !== String(this.dates)) - this._trigger('changeDate'); - } - if (!this.dates.length && oldDates.length) - this._trigger('clearDate'); - - this.fill(); - this.element.change(); - return this; - }, - - fillDow: function(){ - var dowCnt = this.o.weekStart, - html = ''; - if (this.o.calendarWeeks){ - this.picker.find('.datepicker-days .datepicker-switch') - .attr('colspan', function(i, val){ - return parseInt(val) + 1; - }); - html += ' '; - } - while (dowCnt < this.o.weekStart + 7){ - html += ''+dates[this.o.language].daysMin[(dowCnt++)%7]+''; - } - html += ''; - this.picker.find('.datepicker-days thead').append(html); - }, - - fillMonths: function(){ - var localDate = this._utc_to_local(this.viewDate); - var html = '', - i = 0; - while (i < 12){ - var focused = localDate && localDate.getMonth() === i ? ' focused' : ''; - html += '' + dates[this.o.language].monthsShort[i++]+''; - } - this.picker.find('.datepicker-months td').html(html); - }, - - setRange: function(range){ - if (!range || !range.length) - delete this.range; - else - this.range = $.map(range, function(d){ - return d.valueOf(); - }); - this.fill(); - }, - - getClassNames: function(date){ - var cls = [], - year = this.viewDate.getUTCFullYear(), - month = this.viewDate.getUTCMonth(), - today = new Date(); - if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){ - cls.push('old'); - } - else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){ - cls.push('new'); - } - if (this.focusDate && date.valueOf() === this.focusDate.valueOf()) - cls.push('focused'); - // Compare internal UTC date with local today, not UTC today - if (this.o.todayHighlight && - date.getUTCFullYear() === today.getFullYear() && - date.getUTCMonth() === today.getMonth() && - date.getUTCDate() === today.getDate()){ - cls.push('today'); - } - if (this.dates.contains(date) !== -1) - cls.push('active'); - if (!this.dateWithinRange(date)){ - cls.push('disabled'); - } - if (this.dateIsDisabled(date)){ - cls.push('disabled', 'disabled-date'); - } - if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){ - cls.push('highlighted'); - } - - if (this.range){ - if (date > this.range[0] && date < this.range[this.range.length-1]){ - cls.push('range'); - } - if ($.inArray(date.valueOf(), this.range) !== -1){ - cls.push('selected'); - } - if (date.valueOf() === this.range[0]){ - cls.push('range-start'); - } - if (date.valueOf() === this.range[this.range.length-1]){ - cls.push('range-end'); - } - } - return cls; - }, - - _fill_yearsView: function(selector, cssClass, factor, step, currentYear, startYear, endYear, callback){ - var html, view, year, steps, startStep, endStep, thisYear, i, classes, tooltip, before; - - html = ''; - view = this.picker.find(selector); - year = parseInt(currentYear / factor, 10) * factor; - startStep = parseInt(startYear / step, 10) * step; - endStep = parseInt(endYear / step, 10) * step; - steps = $.map(this.dates, function(d){ - return parseInt(d.getUTCFullYear() / step, 10) * step; - }); - - view.find('.datepicker-switch').text(year + '-' + (year + step * 9)); - - thisYear = year - step; - for (i = -1; i < 11; i += 1) { - classes = [cssClass]; - tooltip = null; - - if (i === -1) { - classes.push('old'); - } else if (i === 10) { - classes.push('new'); - } - if ($.inArray(thisYear, steps) !== -1) { - classes.push('active'); - } - if (thisYear < startStep || thisYear > endStep) { - classes.push('disabled'); - } - if (thisYear === this.viewDate.getFullYear()) { - classes.push('focused'); - } - - if (callback !== $.noop) { - before = callback(new Date(thisYear, 0, 1)); - if (before === undefined) { - before = {}; - } else if (typeof(before) === 'boolean') { - before = {enabled: before}; - } else if (typeof(before) === 'string') { - before = {classes: before}; - } - if (before.enabled === false) { - classes.push('disabled'); - } - if (before.classes) { - classes = classes.concat(before.classes.split(/\s+/)); - } - if (before.tooltip) { - tooltip = before.tooltip; - } - } - - html += '' + thisYear + ''; - thisYear += step; - } - view.find('td').html(html); - }, - - fill: function(){ - var d = new Date(this.viewDate), - year = d.getUTCFullYear(), - month = d.getUTCMonth(), - startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity, - startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity, - endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity, - endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity, - todaytxt = dates[this.o.language].today || dates['en'].today || '', - cleartxt = dates[this.o.language].clear || dates['en'].clear || '', - titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat, - tooltip, - before; - if (isNaN(year) || isNaN(month)) - return; - this.picker.find('.datepicker-days .datepicker-switch') - .text(DPGlobal.formatDate(d, titleFormat, this.o.language)); - this.picker.find('tfoot .today') - .text(todaytxt) - .toggle(this.o.todayBtn !== false); - this.picker.find('tfoot .clear') - .text(cleartxt) - .toggle(this.o.clearBtn !== false); - this.picker.find('thead .datepicker-title') - .text(this.o.title) - .toggle(this.o.title !== ''); - this.updateNavArrows(); - this.fillMonths(); - var prevMonth = UTCDate(year, month-1, 28), - day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); - prevMonth.setUTCDate(day); - prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7); - var nextMonth = new Date(prevMonth); - if (prevMonth.getUTCFullYear() < 100){ - nextMonth.setUTCFullYear(prevMonth.getUTCFullYear()); - } - nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); - nextMonth = nextMonth.valueOf(); - var html = []; - var clsName; - while (prevMonth.valueOf() < nextMonth){ - if (prevMonth.getUTCDay() === this.o.weekStart){ - html.push(''); - if (this.o.calendarWeeks){ - // ISO 8601: First week contains first thursday. - // ISO also states week starts on Monday, but we can be more abstract here. - var - // Start of current week: based on weekstart/current date - ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5), - // Thursday of this week - th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5), - // First Thursday of year, year from thursday - yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5), - // Calendar week: ms between thursdays, div ms per day, div 7 days - calWeek = (th - yth) / 864e5 / 7 + 1; - html.push(''+ calWeek +''); - } - } - clsName = this.getClassNames(prevMonth); - clsName.push('day'); - - if (this.o.beforeShowDay !== $.noop){ - before = this.o.beforeShowDay(this._utc_to_local(prevMonth)); - if (before === undefined) - before = {}; - else if (typeof(before) === 'boolean') - before = {enabled: before}; - else if (typeof(before) === 'string') - before = {classes: before}; - if (before.enabled === false) - clsName.push('disabled'); - if (before.classes) - clsName = clsName.concat(before.classes.split(/\s+/)); - if (before.tooltip) - tooltip = before.tooltip; - } - - clsName = $.unique(clsName); - html.push(''+prevMonth.getUTCDate() + ''); - tooltip = null; - if (prevMonth.getUTCDay() === this.o.weekEnd){ - html.push(''); - } - prevMonth.setUTCDate(prevMonth.getUTCDate()+1); - } - this.picker.find('.datepicker-days tbody').empty().append(html.join('')); - - var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months'; - var months = this.picker.find('.datepicker-months') - .find('.datepicker-switch') - .text(this.o.maxViewMode < 2 ? monthsTitle : year) - .end() - .find('span').removeClass('active'); - - $.each(this.dates, function(i, d){ - if (d.getUTCFullYear() === year) - months.eq(d.getUTCMonth()).addClass('active'); - }); - - if (year < startYear || year > endYear){ - months.addClass('disabled'); - } - if (year === startYear){ - months.slice(0, startMonth).addClass('disabled'); - } - if (year === endYear){ - months.slice(endMonth+1).addClass('disabled'); - } - - if (this.o.beforeShowMonth !== $.noop){ - var that = this; - $.each(months, function(i, month){ - var moDate = new Date(year, i, 1); - var before = that.o.beforeShowMonth(moDate); - if (before === undefined) - before = {}; - else if (typeof(before) === 'boolean') - before = {enabled: before}; - else if (typeof(before) === 'string') - before = {classes: before}; - if (before.enabled === false && !$(month).hasClass('disabled')) - $(month).addClass('disabled'); - if (before.classes) - $(month).addClass(before.classes); - if (before.tooltip) - $(month).prop('title', before.tooltip); - }); - } - - // Generating decade/years picker - this._fill_yearsView( - '.datepicker-years', - 'year', - 10, - 1, - year, - startYear, - endYear, - this.o.beforeShowYear - ); - - // Generating century/decades picker - this._fill_yearsView( - '.datepicker-decades', - 'decade', - 100, - 10, - year, - startYear, - endYear, - this.o.beforeShowDecade - ); - - // Generating millennium/centuries picker - this._fill_yearsView( - '.datepicker-centuries', - 'century', - 1000, - 100, - year, - startYear, - endYear, - this.o.beforeShowCentury - ); - }, - - updateNavArrows: function(){ - if (!this._allow_update) - return; - - var d = new Date(this.viewDate), - year = d.getUTCFullYear(), - month = d.getUTCMonth(); - switch (this.viewMode){ - case 0: - if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){ - this.picker.find('.prev').css({visibility: 'hidden'}); - } - else { - this.picker.find('.prev').css({visibility: 'visible'}); - } - if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){ - this.picker.find('.next').css({visibility: 'hidden'}); - } - else { - this.picker.find('.next').css({visibility: 'visible'}); - } - break; - case 1: - case 2: - case 3: - case 4: - if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){ - this.picker.find('.prev').css({visibility: 'hidden'}); - } - else { - this.picker.find('.prev').css({visibility: 'visible'}); - } - if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() || this.o.maxViewMode < 2){ - this.picker.find('.next').css({visibility: 'hidden'}); - } - else { - this.picker.find('.next').css({visibility: 'visible'}); - } - break; - } - }, - - click: function(e){ - e.preventDefault(); - e.stopPropagation(); - - var target, dir, day, year, month, monthChanged, yearChanged; - target = $(e.target); - - // Clicked on the switch - if (target.hasClass('datepicker-switch')){ - this.showMode(1); - } - - // Clicked on prev or next - var navArrow = target.closest('.prev, .next'); - if (navArrow.length > 0) { - dir = DPGlobal.modes[this.viewMode].navStep * (navArrow.hasClass('prev') ? -1 : 1); - if (this.viewMode === 0){ - this.viewDate = this.moveMonth(this.viewDate, dir); - this._trigger('changeMonth', this.viewDate); - } else { - this.viewDate = this.moveYear(this.viewDate, dir); - if (this.viewMode === 1){ - this._trigger('changeYear', this.viewDate); - } - } - this.fill(); - } - - // Clicked on today button - if (target.hasClass('today') && !target.hasClass('day')){ - this.showMode(-2); - this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view'); - } - - // Clicked on clear button - if (target.hasClass('clear')){ - this.clearDates(); - } - - if (!target.hasClass('disabled')){ - // Clicked on a day - if (target.hasClass('day')){ - day = parseInt(target.text(), 10) || 1; - year = this.viewDate.getUTCFullYear(); - month = this.viewDate.getUTCMonth(); - - // From last month - if (target.hasClass('old')){ - if (month === 0) { - month = 11; - year = year - 1; - monthChanged = true; - yearChanged = true; - } else { - month = month - 1; - monthChanged = true; - } - } - - // From next month - if (target.hasClass('new')) { - if (month === 11){ - month = 0; - year = year + 1; - monthChanged = true; - yearChanged = true; - } else { - month = month + 1; - monthChanged = true; - } - } - this._setDate(UTCDate(year, month, day)); - if (yearChanged) { - this._trigger('changeYear', this.viewDate); - } - if (monthChanged) { - this._trigger('changeMonth', this.viewDate); - } - } - - // Clicked on a month - if (target.hasClass('month')) { - this.viewDate.setUTCDate(1); - day = 1; - month = target.parent().find('span').index(target); - year = this.viewDate.getUTCFullYear(); - this.viewDate.setUTCMonth(month); - this._trigger('changeMonth', this.viewDate); - if (this.o.minViewMode === 1){ - this._setDate(UTCDate(year, month, day)); - this.showMode(); - } else { - this.showMode(-1); - } - this.fill(); - } - - // Clicked on a year - if (target.hasClass('year') - || target.hasClass('decade') - || target.hasClass('century')) { - this.viewDate.setUTCDate(1); - - day = 1; - month = 0; - year = parseInt(target.text(), 10)||0; - this.viewDate.setUTCFullYear(year); - - if (target.hasClass('year')){ - this._trigger('changeYear', this.viewDate); - if (this.o.minViewMode === 2){ - this._setDate(UTCDate(year, month, day)); - } - } - if (target.hasClass('decade')){ - this._trigger('changeDecade', this.viewDate); - if (this.o.minViewMode === 3){ - this._setDate(UTCDate(year, month, day)); - } - } - if (target.hasClass('century')){ - this._trigger('changeCentury', this.viewDate); - if (this.o.minViewMode === 4){ - this._setDate(UTCDate(year, month, day)); - } - } - - this.showMode(-1); - this.fill(); - } - } - - if (this.picker.is(':visible') && this._focused_from){ - $(this._focused_from).focus(); - } - delete this._focused_from; - }, - - _toggle_multidate: function(date){ - var ix = this.dates.contains(date); - if (!date){ - this.dates.clear(); - } - - if (ix !== -1){ - if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){ - this.dates.remove(ix); - } - } else if (this.o.multidate === false) { - this.dates.clear(); - this.dates.push(date); - } - else { - this.dates.push(date); - } - - if (typeof this.o.multidate === 'number') - while (this.dates.length > this.o.multidate) - this.dates.remove(0); - }, - - _setDate: function(date, which){ - if (!which || which === 'date') - this._toggle_multidate(date && new Date(date)); - if (!which || which === 'view') - this.viewDate = date && new Date(date); - - this.fill(); - this.setValue(); - if (!which || which !== 'view') { - this._trigger('changeDate'); - } - if (this.inputField){ - this.inputField.change(); - } - if (this.o.autoclose && (!which || which === 'date')){ - this.hide(); - } - }, - - moveDay: function(date, dir){ - var newDate = new Date(date); - newDate.setUTCDate(date.getUTCDate() + dir); - - return newDate; - }, - - moveWeek: function(date, dir){ - return this.moveDay(date, dir * 7); - }, - - moveMonth: function(date, dir){ - if (!isValidDate(date)) - return this.o.defaultViewDate; - if (!dir) - return date; - var new_date = new Date(date.valueOf()), - day = new_date.getUTCDate(), - month = new_date.getUTCMonth(), - mag = Math.abs(dir), - new_month, test; - dir = dir > 0 ? 1 : -1; - if (mag === 1){ - test = dir === -1 - // If going back one month, make sure month is not current month - // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) - ? function(){ - return new_date.getUTCMonth() === month; - } - // If going forward one month, make sure month is as expected - // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) - : function(){ - return new_date.getUTCMonth() !== new_month; - }; - new_month = month + dir; - new_date.setUTCMonth(new_month); - // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 - if (new_month < 0 || new_month > 11) - new_month = (new_month + 12) % 12; - } - else { - // For magnitudes >1, move one month at a time... - for (var i=0; i < mag; i++) - // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... - new_date = this.moveMonth(new_date, dir); - // ...then reset the day, keeping it in the new month - new_month = new_date.getUTCMonth(); - new_date.setUTCDate(day); - test = function(){ - return new_month !== new_date.getUTCMonth(); - }; - } - // Common date-resetting loop -- if date is beyond end of month, make it - // end of month - while (test()){ - new_date.setUTCDate(--day); - new_date.setUTCMonth(new_month); - } - return new_date; - }, - - moveYear: function(date, dir){ - return this.moveMonth(date, dir*12); - }, - - moveAvailableDate: function(date, dir, fn){ - do { - date = this[fn](date, dir); - - if (!this.dateWithinRange(date)) - return false; - - fn = 'moveDay'; - } - while (this.dateIsDisabled(date)); - - return date; - }, - - weekOfDateIsDisabled: function(date){ - return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1; - }, - - dateIsDisabled: function(date){ - return ( - this.weekOfDateIsDisabled(date) || - $.grep(this.o.datesDisabled, function(d){ - return isUTCEquals(date, d); - }).length > 0 - ); - }, - - dateWithinRange: function(date){ - return date >= this.o.startDate && date <= this.o.endDate; - }, - - keydown: function(e){ - if (!this.picker.is(':visible')){ - if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker - this.show(); - e.stopPropagation(); - } - return; - } - var dateChanged = false, - dir, newViewDate, - focusDate = this.focusDate || this.viewDate; - switch (e.keyCode){ - case 27: // escape - if (this.focusDate){ - this.focusDate = null; - this.viewDate = this.dates.get(-1) || this.viewDate; - this.fill(); - } - else - this.hide(); - e.preventDefault(); - e.stopPropagation(); - break; - case 37: // left - case 38: // up - case 39: // right - case 40: // down - if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7) - break; - dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1; - if (this.viewMode === 0) { - if (e.ctrlKey){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear'); - - if (newViewDate) - this._trigger('changeYear', this.viewDate); - } - else if (e.shiftKey){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth'); - - if (newViewDate) - this._trigger('changeMonth', this.viewDate); - } - else if (e.keyCode === 37 || e.keyCode === 39){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay'); - } - else if (!this.weekOfDateIsDisabled(focusDate)){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek'); - } - } else if (this.viewMode === 1) { - if (e.keyCode === 38 || e.keyCode === 40) { - dir = dir * 4; - } - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth'); - } else if (this.viewMode === 2) { - if (e.keyCode === 38 || e.keyCode === 40) { - dir = dir * 4; - } - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear'); - } - if (newViewDate){ - this.focusDate = this.viewDate = newViewDate; - this.setValue(); - this.fill(); - e.preventDefault(); - } - break; - case 13: // enter - if (!this.o.forceParse) - break; - focusDate = this.focusDate || this.dates.get(-1) || this.viewDate; - if (this.o.keyboardNavigation) { - this._toggle_multidate(focusDate); - dateChanged = true; - } - this.focusDate = null; - this.viewDate = this.dates.get(-1) || this.viewDate; - this.setValue(); - this.fill(); - if (this.picker.is(':visible')){ - e.preventDefault(); - e.stopPropagation(); - if (this.o.autoclose) - this.hide(); - } - break; - case 9: // tab - this.focusDate = null; - this.viewDate = this.dates.get(-1) || this.viewDate; - this.fill(); - this.hide(); - break; - } - if (dateChanged){ - if (this.dates.length) - this._trigger('changeDate'); - else - this._trigger('clearDate'); - if (this.inputField){ - this.inputField.change(); - } - } - }, - - showMode: function(dir){ - if (dir){ - this.viewMode = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, this.viewMode + dir)); - } - this.picker - .children('div') - .hide() - .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName) - .show(); - this.updateNavArrows(); - } - }; - - var DateRangePicker = function(element, options){ - $(element).data('datepicker', this); - this.element = $(element); - this.inputs = $.map(options.inputs, function(i){ - return i.jquery ? i[0] : i; - }); - delete options.inputs; - - datepickerPlugin.call($(this.inputs), options) - .on('changeDate', $.proxy(this.dateUpdated, this)); - - this.pickers = $.map(this.inputs, function(i){ - return $(i).data('datepicker'); - }); - this.updateDates(); - }; - DateRangePicker.prototype = { - updateDates: function(){ - this.dates = $.map(this.pickers, function(i){ - return i.getUTCDate(); - }); - this.updateRanges(); - }, - updateRanges: function(){ - var range = $.map(this.dates, function(d){ - return d.valueOf(); - }); - $.each(this.pickers, function(i, p){ - p.setRange(range); - }); - }, - dateUpdated: function(e){ - // `this.updating` is a workaround for preventing infinite recursion - // between `changeDate` triggering and `setUTCDate` calling. Until - // there is a better mechanism. - if (this.updating) - return; - this.updating = true; - - var dp = $(e.target).data('datepicker'); - - if (typeof(dp) === "undefined") { - return; - } - - var new_date = dp.getUTCDate(), - i = $.inArray(e.target, this.inputs), - j = i - 1, - k = i + 1, - l = this.inputs.length; - if (i === -1) - return; - - $.each(this.pickers, function(i, p){ - if (!p.getUTCDate()) - p.setUTCDate(new_date); - }); - - if (new_date < this.dates[j]){ - // Date being moved earlier/left - while (j >= 0 && new_date < this.dates[j]){ - this.pickers[j--].setUTCDate(new_date); - } - } - else if (new_date > this.dates[k]){ - // Date being moved later/right - while (k < l && new_date > this.dates[k]){ - this.pickers[k++].setUTCDate(new_date); - } - } - this.updateDates(); - - delete this.updating; - }, - remove: function(){ - $.map(this.pickers, function(p){ p.remove(); }); - delete this.element.data().datepicker; - } - }; - - function opts_from_el(el, prefix){ - // Derive options from element data-attrs - var data = $(el).data(), - out = {}, inkey, - replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])'); - prefix = new RegExp('^' + prefix.toLowerCase()); - function re_lower(_,a){ - return a.toLowerCase(); - } - for (var key in data) - if (prefix.test(key)){ - inkey = key.replace(replace, re_lower); - out[inkey] = data[key]; - } - return out; - } - - function opts_from_locale(lang){ - // Derive options from locale plugins - var out = {}; - // Check if "de-DE" style date is available, if not language should - // fallback to 2 letter code eg "de" - if (!dates[lang]){ - lang = lang.split('-')[0]; - if (!dates[lang]) - return; - } - var d = dates[lang]; - $.each(locale_opts, function(i,k){ - if (k in d) - out[k] = d[k]; - }); - return out; - } - - var old = $.fn.datepicker; - var datepickerPlugin = function(option){ - var args = Array.apply(null, arguments); - args.shift(); - var internal_return; - this.each(function(){ - var $this = $(this), - data = $this.data('datepicker'), - options = typeof option === 'object' && option; - if (!data){ - var elopts = opts_from_el(this, 'date'), - // Preliminary otions - xopts = $.extend({}, defaults, elopts, options), - locopts = opts_from_locale(xopts.language), - // Options priority: js args, data-attrs, locales, defaults - opts = $.extend({}, defaults, locopts, elopts, options); - if ($this.hasClass('input-daterange') || opts.inputs){ - $.extend(opts, { - inputs: opts.inputs || $this.find('input').toArray() - }); - data = new DateRangePicker(this, opts); - } - else { - data = new Datepicker(this, opts); - } - $this.data('datepicker', data); - } - if (typeof option === 'string' && typeof data[option] === 'function'){ - internal_return = data[option].apply(data, args); - } - }); - - if ( - internal_return === undefined || - internal_return instanceof Datepicker || - internal_return instanceof DateRangePicker - ) - return this; - - if (this.length > 1) - throw new Error('Using only allowed for the collection of a single element (' + option + ' function)'); - else - return internal_return; - }; - $.fn.datepicker = datepickerPlugin; - - var defaults = $.fn.datepicker.defaults = { - assumeNearbyYear: false, - autoclose: false, - beforeShowDay: $.noop, - beforeShowMonth: $.noop, - beforeShowYear: $.noop, - beforeShowDecade: $.noop, - beforeShowCentury: $.noop, - calendarWeeks: false, - clearBtn: false, - toggleActive: false, - daysOfWeekDisabled: [], - daysOfWeekHighlighted: [], - datesDisabled: [], - endDate: Infinity, - forceParse: true, - format: 'mm/dd/yyyy', - keyboardNavigation: true, - language: 'en', - minViewMode: 0, - maxViewMode: 4, - multidate: false, - multidateSeparator: ',', - orientation: "auto", - rtl: false, - startDate: -Infinity, - startView: 0, - todayBtn: false, - todayHighlight: false, - weekStart: 0, - disableTouchKeyboard: false, - enableOnReadonly: true, - showOnFocus: true, - zIndexOffset: 10, - container: 'body', - immediateUpdates: false, - title: '', - templates: { - leftArrow: '«', - rightArrow: '»' - } - }; - var locale_opts = $.fn.datepicker.locale_opts = [ - 'format', - 'rtl', - 'weekStart' - ]; - $.fn.datepicker.Constructor = Datepicker; - var dates = $.fn.datepicker.dates = { - en: { - days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], - months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], - today: "Today", - clear: "Clear", - titleFormat: "MM yyyy" - } - }; - - var DPGlobal = { - modes: [ - { - clsName: 'days', - navFnc: 'Month', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'FullYear', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'FullYear', - navStep: 10 - }, - { - clsName: 'decades', - navFnc: 'FullDecade', - navStep: 100 - }, - { - clsName: 'centuries', - navFnc: 'FullCentury', - navStep: 1000 - }], - isLeapYear: function(year){ - return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); - }, - getDaysInMonth: function(year, month){ - return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; - }, - validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, - nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g, - parseFormat: function(format){ - if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function') - return format; - // IE treats \0 as a string end in inputs (truncating the value), - // so it's a bad format delimiter, anyway - var separators = format.replace(this.validParts, '\0').split('\0'), - parts = format.match(this.validParts); - if (!separators || !separators.length || !parts || parts.length === 0){ - throw new Error("Invalid date format."); - } - return {separators: separators, parts: parts}; - }, - parseDate: function(date, format, language, assumeNearby){ - if (!date) - return undefined; - if (date instanceof Date) - return date; - if (typeof format === 'string') - format = DPGlobal.parseFormat(format); - if (format.toValue) - return format.toValue(date, format, language); - var part_re = /([\-+]\d+)([dmwy])/, - parts = date.match(/([\-+]\d+)([dmwy])/g), - fn_map = { - d: 'moveDay', - m: 'moveMonth', - w: 'moveWeek', - y: 'moveYear' - }, - dateAliases = { - yesterday: '-1d', - today: '+0d', - tomorrow: '+1d' - }, - part, dir, i, fn; - if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){ - date = new Date(); - for (i=0; i < parts.length; i++){ - part = part_re.exec(parts[i]); - dir = parseInt(part[1]); - fn = fn_map[part[2]]; - date = Datepicker.prototype[fn](date, dir); - } - return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()); - } - - if (typeof dateAliases[date] !== 'undefined') { - date = dateAliases[date]; - parts = date.match(/([\-+]\d+)([dmwy])/g); - - if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){ - date = new Date(); - for (i=0; i < parts.length; i++){ - part = part_re.exec(parts[i]); - dir = parseInt(part[1]); - fn = fn_map[part[2]]; - date = Datepicker.prototype[fn](date, dir); - } - - return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()); - } - } - - parts = date && date.match(this.nonpunctuation) || []; - date = new Date(); - - function applyNearbyYear(year, threshold){ - if (threshold === true) - threshold = 10; - - // if year is 2 digits or less, than the user most likely is trying to get a recent century - if (year < 100){ - year += 2000; - // if the new year is more than threshold years in advance, use last century - if (year > ((new Date()).getFullYear()+threshold)){ - year -= 100; - } - } - - return year; - } - - var parsed = {}, - setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], - setters_map = { - yyyy: function(d,v){ - return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v); - }, - yy: function(d,v){ - return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v); - }, - m: function(d,v){ - if (isNaN(d)) - return d; - v -= 1; - while (v < 0) v += 12; - v %= 12; - d.setUTCMonth(v); - while (d.getUTCMonth() !== v) - d.setUTCDate(d.getUTCDate()-1); - return d; - }, - d: function(d,v){ - return d.setUTCDate(v); - } - }, - val, filtered; - setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; - setters_map['dd'] = setters_map['d']; - date = UTCToday(); - var fparts = format.parts.slice(); - // Remove noop parts - if (parts.length !== fparts.length){ - fparts = $(fparts).filter(function(i,p){ - return $.inArray(p, setters_order) !== -1; - }).toArray(); - } - // Process remainder - function match_part(){ - var m = this.slice(0, parts[i].length), - p = parts[i].slice(0, m.length); - return m.toLowerCase() === p.toLowerCase(); - } - if (parts.length === fparts.length){ - var cnt; - for (i=0, cnt = fparts.length; i < cnt; i++){ - val = parseInt(parts[i], 10); - part = fparts[i]; - if (isNaN(val)){ - switch (part){ - case 'MM': - filtered = $(dates[language].months).filter(match_part); - val = $.inArray(filtered[0], dates[language].months) + 1; - break; - case 'M': - filtered = $(dates[language].monthsShort).filter(match_part); - val = $.inArray(filtered[0], dates[language].monthsShort) + 1; - break; - } - } - parsed[part] = val; - } - var _date, s; - for (i=0; i < setters_order.length; i++){ - s = setters_order[i]; - if (s in parsed && !isNaN(parsed[s])){ - _date = new Date(date); - setters_map[s](_date, parsed[s]); - if (!isNaN(_date)) - date = _date; - } - } - } - return date; - }, - formatDate: function(date, format, language){ - if (!date) - return ''; - if (typeof format === 'string') - format = DPGlobal.parseFormat(format); - if (format.toDisplay) - return format.toDisplay(date, format, language); - var val = { - d: date.getUTCDate(), - D: dates[language].daysShort[date.getUTCDay()], - DD: dates[language].days[date.getUTCDay()], - m: date.getUTCMonth() + 1, - M: dates[language].monthsShort[date.getUTCMonth()], - MM: dates[language].months[date.getUTCMonth()], - yy: date.getUTCFullYear().toString().substring(2), - yyyy: date.getUTCFullYear() - }; - val.dd = (val.d < 10 ? '0' : '') + val.d; - val.mm = (val.m < 10 ? '0' : '') + val.m; - date = []; - var seps = $.extend([], format.separators); - for (var i=0, cnt = format.parts.length; i <= cnt; i++){ - if (seps.length) - date.push(seps.shift()); - date.push(val[format.parts[i]]); - } - return date.join(''); - }, - headTemplate: ''+ - ''+ - ''+ - ''+ - ''+ - '«'+ - ''+ - '»'+ - ''+ - '', - contTemplate: '', - footTemplate: ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - '' - }; - DPGlobal.template = '
    '+ - '
    '+ - ''+ - DPGlobal.headTemplate+ - ''+ - DPGlobal.footTemplate+ - '
    '+ - '
    '+ - '
    '+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
    '+ - '
    '+ - '
    '+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
    '+ - '
    '+ - '
    '+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
    '+ - '
    '+ - '
    '+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
    '+ - '
    '+ - '
    '; - - $.fn.datepicker.DPGlobal = DPGlobal; - - - /* DATEPICKER NO CONFLICT - * =================== */ - - $.fn.datepicker.noConflict = function(){ - $.fn.datepicker = old; - return this; - }; - - /* DATEPICKER VERSION - * =================== */ - $.fn.datepicker.version = '1.6.1'; - - /* DATEPICKER DATA-API - * ================== */ - - $(document).on( - 'focus.datepicker.data-api click.datepicker.data-api', - '[data-provide="datepicker"]', - function(e){ - var $this = $(this); - if ($this.data('datepicker')) - return; - e.preventDefault(); - // component click requires us to explicitly show it - datepickerPlugin.call($this, 'show'); - } - ); - $(function(){ - datepickerPlugin.call($('[data-provide="datepicker-inline"]')); - }); - -})); diff --git a/vendor/assets/javascripts/bootstrap-tagsinput.js b/vendor/assets/javascripts/bootstrap-tagsinput.js deleted file mode 100644 index 823256b..0000000 --- a/vendor/assets/javascripts/bootstrap-tagsinput.js +++ /dev/null @@ -1,682 +0,0 @@ -/* - * bootstrap-tagsinput v0.8.0 - * - */ - -(function ($) { - "use strict"; - - var defaultOptions = { - tagClass: function(item) { - return 'label label-info'; - }, - focusClass: 'focus', - itemValue: function(item) { - return item ? item.toString() : item; - }, - itemText: function(item) { - return this.itemValue(item); - }, - itemTitle: function(item) { - return null; - }, - freeInput: true, - addOnBlur: true, - maxTags: undefined, - maxChars: undefined, - confirmKeys: [13, 44], - delimiter: ',', - delimiterRegex: null, - cancelConfirmKeysOnEmpty: false, - onTagExists: function(item, $tag) { - $tag.hide().fadeIn(); - }, - trimValue: false, - allowDuplicates: false, - triggerChange: true - }; - - /** - * Constructor function - */ - function TagsInput(element, options) { - this.isInit = true; - this.itemsArray = []; - - this.$element = $(element); - this.$element.hide(); - - this.isSelect = (element.tagName === 'SELECT'); - this.multiple = (this.isSelect && element.hasAttribute('multiple')); - this.objectItems = options && options.itemValue; - this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : ''; - this.inputSize = Math.max(1, this.placeholderText.length); - - this.$container = $('
    '); - this.$input = $('').appendTo(this.$container); - - this.$element.before(this.$container); - - this.build(options); - this.isInit = false; - } - - TagsInput.prototype = { - constructor: TagsInput, - - /** - * Adds the given item as a new tag. Pass true to dontPushVal to prevent - * updating the elements val() - */ - add: function(item, dontPushVal, options) { - var self = this; - - if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags) - return; - - // Ignore falsey values, except false - if (item !== false && !item) - return; - - // Trim value - if (typeof item === "string" && self.options.trimValue) { - item = $.trim(item); - } - - // Throw an error when trying to add an object while the itemValue option was not set - if (typeof item === "object" && !self.objectItems) - throw("Can't add objects when itemValue option is not set"); - - // Ignore strings only containg whitespace - if (item.toString().match(/^\s*$/)) - return; - - // If SELECT but not multiple, remove current tag - if (self.isSelect && !self.multiple && self.itemsArray.length > 0) - self.remove(self.itemsArray[0]); - - if (typeof item === "string" && this.$element[0].tagName === 'INPUT') { - var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter; - var items = item.split(delimiter); - if (items.length > 1) { - for (var i = 0; i < items.length; i++) { - this.add(items[i], true); - } - - if (!dontPushVal) - self.pushVal(self.options.triggerChange); - return; - } - } - - var itemValue = self.options.itemValue(item), - itemText = self.options.itemText(item), - tagClass = self.options.tagClass(item), - itemTitle = self.options.itemTitle(item); - - // Ignore items allready added - var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0]; - if (existing && !self.options.allowDuplicates) { - // Invoke onTagExists - if (self.options.onTagExists) { - var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; }); - self.options.onTagExists(item, $existingTag); - } - return; - } - - // if length greater than limit - if (self.items().toString().length + item.length + 1 > self.options.maxInputLength) - return; - - // raise beforeItemAdd arg - var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false, options: options}); - self.$element.trigger(beforeItemAddEvent); - if (beforeItemAddEvent.cancel) - return; - - // register item in internal array and map - self.itemsArray.push(item); - - // add a tag element - - var $tag = $('' + htmlEncode(itemText) + ''); - $tag.data('item', item); - self.findInputWrapper().before($tag); - $tag.after(' '); - - // Check to see if the tag exists in its raw or uri-encoded form - var optionExists = ( - $('option[value="' + encodeURIComponent(itemValue) + '"]', self.$element).length || - $('option[value="' + htmlEncode(itemValue) + '"]', self.$element).length - ); - - // add
    ' + this.default_text + '
      '); - } - this.form_field_jq.hide().after(this.container); - this.dropdown = this.container.find('div.chosen-drop').first(); - this.search_field = this.container.find('input').first(); - this.search_results = this.container.find('ul.chosen-results').first(); - this.search_field_scale(); - this.search_no_results = this.container.find('li.no-results').first(); - if (this.is_multiple) { - this.search_choices = this.container.find('ul.chosen-choices').first(); - this.search_container = this.container.find('li.search-field').first(); - } else { - this.search_container = this.container.find('div.chosen-search').first(); - this.selected_item = this.container.find('.chosen-single').first(); - } - this.results_build(); - this.set_tab_index(); - return this.set_label_behavior(); - }; - - Chosen.prototype.on_ready = function() { - return this.form_field_jq.trigger("chosen:ready", { - chosen: this - }); - }; - - Chosen.prototype.register_observers = function() { - var _this = this; - this.container.bind('touchstart.chosen', function(evt) { - _this.container_mousedown(evt); - return evt.preventDefault(); - }); - this.container.bind('touchend.chosen', function(evt) { - _this.container_mouseup(evt); - return evt.preventDefault(); - }); - this.container.bind('mousedown.chosen', function(evt) { - _this.container_mousedown(evt); - }); - this.container.bind('mouseup.chosen', function(evt) { - _this.container_mouseup(evt); - }); - this.container.bind('mouseenter.chosen', function(evt) { - _this.mouse_enter(evt); - }); - this.container.bind('mouseleave.chosen', function(evt) { - _this.mouse_leave(evt); - }); - this.search_results.bind('mouseup.chosen', function(evt) { - _this.search_results_mouseup(evt); - }); - this.search_results.bind('mouseover.chosen', function(evt) { - _this.search_results_mouseover(evt); - }); - this.search_results.bind('mouseout.chosen', function(evt) { - _this.search_results_mouseout(evt); - }); - this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) { - _this.search_results_mousewheel(evt); - }); - this.search_results.bind('touchstart.chosen', function(evt) { - _this.search_results_touchstart(evt); - }); - this.search_results.bind('touchmove.chosen', function(evt) { - _this.search_results_touchmove(evt); - }); - this.search_results.bind('touchend.chosen', function(evt) { - _this.search_results_touchend(evt); - }); - this.form_field_jq.bind("chosen:updated.chosen", function(evt) { - _this.results_update_field(evt); - }); - this.form_field_jq.bind("chosen:activate.chosen", function(evt) { - _this.activate_field(evt); - }); - this.form_field_jq.bind("chosen:open.chosen", function(evt) { - _this.container_mousedown(evt); - }); - this.form_field_jq.bind("chosen:close.chosen", function(evt) { - _this.input_blur(evt); - }); - this.search_field.bind('blur.chosen', function(evt) { - _this.input_blur(evt); - }); - this.search_field.bind('keyup.chosen', function(evt) { - _this.keyup_checker(evt); - }); - this.search_field.bind('keydown.chosen', function(evt) { - _this.keydown_checker(evt); - }); - this.search_field.bind('focus.chosen', function(evt) { - _this.input_focus(evt); - }); - this.search_field.bind('cut.chosen', function(evt) { - _this.clipboard_event_checker(evt); - }); - this.search_field.bind('paste.chosen', function(evt) { - _this.clipboard_event_checker(evt); - }); - if (this.is_multiple) { - return this.search_choices.bind('click.chosen', function(evt) { - _this.choices_click(evt); - }); - } else { - return this.container.bind('click.chosen', function(evt) { - evt.preventDefault(); - }); - } - }; - - Chosen.prototype.destroy = function() { - $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); - if (this.search_field[0].tabIndex) { - this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex; - } - this.container.remove(); - this.form_field_jq.removeData('chosen'); - return this.form_field_jq.show(); - }; - - Chosen.prototype.search_field_disabled = function() { - this.is_disabled = this.form_field_jq[0].disabled; - if (this.is_disabled) { - this.container.addClass('chosen-disabled'); - this.search_field[0].disabled = true; - if (!this.is_multiple) { - this.selected_item.unbind("focus.chosen", this.activate_action); - } - return this.close_field(); - } else { - this.container.removeClass('chosen-disabled'); - this.search_field[0].disabled = false; - if (!this.is_multiple) { - return this.selected_item.bind("focus.chosen", this.activate_action); - } - } - }; - - Chosen.prototype.container_mousedown = function(evt) { - if (!this.is_disabled) { - if (evt && evt.type === "mousedown" && !this.results_showing) { - evt.preventDefault(); - } - if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) { - if (!this.active_field) { - if (this.is_multiple) { - this.search_field.val(""); - } - $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action); - this.results_show(); - } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) { - evt.preventDefault(); - this.results_toggle(); - } - return this.activate_field(); - } - } - }; - - Chosen.prototype.container_mouseup = function(evt) { - if (evt.target.nodeName === "ABBR" && !this.is_disabled) { - return this.results_reset(evt); - } - }; - - Chosen.prototype.search_results_mousewheel = function(evt) { - var delta; - if (evt.originalEvent) { - delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail; - } - if (delta != null) { - evt.preventDefault(); - if (evt.type === 'DOMMouseScroll') { - delta = delta * 40; - } - return this.search_results.scrollTop(delta + this.search_results.scrollTop()); - } - }; - - Chosen.prototype.blur_test = function(evt) { - if (!this.active_field && this.container.hasClass("chosen-container-active")) { - return this.close_field(); - } - }; - - Chosen.prototype.close_field = function() { - $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); - this.active_field = false; - this.results_hide(); - this.container.removeClass("chosen-container-active"); - this.clear_backstroke(); - this.show_search_field_default(); - return this.search_field_scale(); - }; - - Chosen.prototype.activate_field = function() { - this.container.addClass("chosen-container-active"); - this.active_field = true; - this.search_field.val(this.search_field.val()); - return this.search_field.focus(); - }; - - Chosen.prototype.test_active_click = function(evt) { - var active_container; - active_container = $(evt.target).closest('.chosen-container'); - if (active_container.length && this.container[0] === active_container[0]) { - return this.active_field = true; - } else { - return this.close_field(); - } - }; - - Chosen.prototype.results_build = function() { - this.parsing = true; - this.selected_option_count = null; - this.results_data = SelectParser.select_to_array(this.form_field); - if (this.is_multiple) { - this.search_choices.find("li.search-choice").remove(); - } else if (!this.is_multiple) { - this.single_set_selected_text(); - if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { - this.search_field[0].readOnly = true; - this.container.addClass("chosen-container-single-nosearch"); - } else { - this.search_field[0].readOnly = false; - this.container.removeClass("chosen-container-single-nosearch"); - } - } - this.update_results_content(this.results_option_build({ - first: true - })); - this.search_field_disabled(); - this.show_search_field_default(); - this.search_field_scale(); - return this.parsing = false; - }; - - Chosen.prototype.result_do_highlight = function(el) { - var high_bottom, high_top, maxHeight, visible_bottom, visible_top; - if (el.length) { - this.result_clear_highlight(); - this.result_highlight = el; - this.result_highlight.addClass("highlighted"); - maxHeight = parseInt(this.search_results.css("maxHeight"), 10); - visible_top = this.search_results.scrollTop(); - visible_bottom = maxHeight + visible_top; - high_top = this.result_highlight.position().top + this.search_results.scrollTop(); - high_bottom = high_top + this.result_highlight.outerHeight(); - if (high_bottom >= visible_bottom) { - return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); - } else if (high_top < visible_top) { - return this.search_results.scrollTop(high_top); - } - } - }; - - Chosen.prototype.result_clear_highlight = function() { - if (this.result_highlight) { - this.result_highlight.removeClass("highlighted"); - } - return this.result_highlight = null; - }; - - Chosen.prototype.results_show = function() { - if (this.is_multiple && this.max_selected_options <= this.choices_count()) { - this.form_field_jq.trigger("chosen:maxselected", { - chosen: this - }); - return false; - } - this.container.addClass("chosen-with-drop"); - this.results_showing = true; - this.search_field.focus(); - this.search_field.val(this.search_field.val()); - this.winnow_results(); - return this.form_field_jq.trigger("chosen:showing_dropdown", { - chosen: this - }); - }; - - Chosen.prototype.update_results_content = function(content) { - return this.search_results.html(content); - }; - - Chosen.prototype.results_hide = function() { - if (this.results_showing) { - this.result_clear_highlight(); - this.container.removeClass("chosen-with-drop"); - this.form_field_jq.trigger("chosen:hiding_dropdown", { - chosen: this - }); - } - return this.results_showing = false; - }; - - Chosen.prototype.set_tab_index = function(el) { - var ti; - if (this.form_field.tabIndex) { - ti = this.form_field.tabIndex; - this.form_field.tabIndex = -1; - return this.search_field[0].tabIndex = ti; - } - }; - - Chosen.prototype.set_label_behavior = function() { - var _this = this; - this.form_field_label = this.form_field_jq.parents("label"); - if (!this.form_field_label.length && this.form_field.id.length) { - this.form_field_label = $("label[for='" + this.form_field.id + "']"); - } - if (this.form_field_label.length > 0) { - return this.form_field_label.bind('click.chosen', function(evt) { - if (_this.is_multiple) { - return _this.container_mousedown(evt); - } else { - return _this.activate_field(); - } - }); - } - }; - - Chosen.prototype.show_search_field_default = function() { - if (this.is_multiple && this.choices_count() < 1 && !this.active_field) { - this.search_field.val(this.default_text); - return this.search_field.addClass("default"); - } else { - this.search_field.val(""); - return this.search_field.removeClass("default"); - } - }; - - Chosen.prototype.search_results_mouseup = function(evt) { - var target; - target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); - if (target.length) { - this.result_highlight = target; - this.result_select(evt); - return this.search_field.focus(); - } - }; - - Chosen.prototype.search_results_mouseover = function(evt) { - var target; - target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); - if (target) { - return this.result_do_highlight(target); - } - }; - - Chosen.prototype.search_results_mouseout = function(evt) { - if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) { - return this.result_clear_highlight(); - } - }; - - Chosen.prototype.choice_build = function(item) { - var choice, close_link, - _this = this; - choice = $('
    • ', { - "class": "search-choice" - }).html("" + (this.choice_label(item)) + ""); - if (item.disabled) { - choice.addClass('search-choice-disabled'); - } else { - close_link = $('', { - "class": 'search-choice-close', - 'data-option-array-index': item.array_index - }); - close_link.bind('click.chosen', function(evt) { - return _this.choice_destroy_link_click(evt); - }); - choice.append(close_link); - } - return this.search_container.before(choice); - }; - - Chosen.prototype.choice_destroy_link_click = function(evt) { - evt.preventDefault(); - evt.stopPropagation(); - if (!this.is_disabled) { - return this.choice_destroy($(evt.target)); - } - }; - - Chosen.prototype.choice_destroy = function(link) { - if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) { - this.show_search_field_default(); - if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) { - this.results_hide(); - } - link.parents('li').first().remove(); - return this.search_field_scale(); - } - }; - - Chosen.prototype.results_reset = function() { - this.reset_single_select_options(); - this.form_field.options[0].selected = true; - this.single_set_selected_text(); - this.show_search_field_default(); - this.results_reset_cleanup(); - this.form_field_jq.trigger("change"); - if (this.active_field) { - return this.results_hide(); - } - }; - - Chosen.prototype.results_reset_cleanup = function() { - this.current_selectedIndex = this.form_field.selectedIndex; - return this.selected_item.find("abbr").remove(); - }; - - Chosen.prototype.result_select = function(evt) { - var high, item; - if (this.result_highlight) { - high = this.result_highlight; - this.result_clear_highlight(); - if (this.is_multiple && this.max_selected_options <= this.choices_count()) { - this.form_field_jq.trigger("chosen:maxselected", { - chosen: this - }); - return false; - } - if (this.is_multiple) { - high.removeClass("active-result"); - } else { - this.reset_single_select_options(); - } - high.addClass("result-selected"); - item = this.results_data[high[0].getAttribute("data-option-array-index")]; - item.selected = true; - this.form_field.options[item.options_index].selected = true; - this.selected_option_count = null; - if (this.is_multiple) { - this.choice_build(item); - } else { - this.single_set_selected_text(this.choice_label(item)); - } - if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) { - this.results_hide(); - } - this.search_field.val(""); - if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) { - this.form_field_jq.trigger("change", { - 'selected': this.form_field.options[item.options_index].value - }); - } - this.current_selectedIndex = this.form_field.selectedIndex; - evt.preventDefault(); - return this.search_field_scale(); - } - }; - - Chosen.prototype.single_set_selected_text = function(text) { - if (text == null) { - text = this.default_text; - } - if (text === this.default_text) { - this.selected_item.addClass("chosen-default"); - } else { - this.single_deselect_control_build(); - this.selected_item.removeClass("chosen-default"); - } - return this.selected_item.find("span").html(text); - }; - - Chosen.prototype.result_deselect = function(pos) { - var result_data; - result_data = this.results_data[pos]; - if (!this.form_field.options[result_data.options_index].disabled) { - result_data.selected = false; - this.form_field.options[result_data.options_index].selected = false; - this.selected_option_count = null; - this.result_clear_highlight(); - if (this.results_showing) { - this.winnow_results(); - } - this.form_field_jq.trigger("change", { - deselected: this.form_field.options[result_data.options_index].value - }); - this.search_field_scale(); - return true; - } else { - return false; - } - }; - - Chosen.prototype.single_deselect_control_build = function() { - if (!this.allow_single_deselect) { - return; - } - if (!this.selected_item.find("abbr").length) { - this.selected_item.find("span").first().after(""); - } - return this.selected_item.addClass("chosen-single-with-deselect"); - }; - - Chosen.prototype.get_search_text = function() { - return $('
      ').text($.trim(this.search_field.val())).html(); - }; - - Chosen.prototype.winnow_results_set_highlight = function() { - var do_high, selected_results; - selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; - do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); - if (do_high != null) { - return this.result_do_highlight(do_high); - } - }; - - Chosen.prototype.no_results = function(terms) { - var no_results_html; - no_results_html = $('
    • ' + this.results_none_found + ' ""
    • '); - no_results_html.find("span").first().html(terms); - this.search_results.append(no_results_html); - return this.form_field_jq.trigger("chosen:no_results", { - chosen: this - }); - }; - - Chosen.prototype.no_results_clear = function() { - return this.search_results.find(".no-results").remove(); - }; - - Chosen.prototype.keydown_arrow = function() { - var next_sib; - if (this.results_showing && this.result_highlight) { - next_sib = this.result_highlight.nextAll("li.active-result").first(); - if (next_sib) { - return this.result_do_highlight(next_sib); - } - } else { - return this.results_show(); - } - }; - - Chosen.prototype.keyup_arrow = function() { - var prev_sibs; - if (!this.results_showing && !this.is_multiple) { - return this.results_show(); - } else if (this.result_highlight) { - prev_sibs = this.result_highlight.prevAll("li.active-result"); - if (prev_sibs.length) { - return this.result_do_highlight(prev_sibs.first()); - } else { - if (this.choices_count() > 0) { - this.results_hide(); - } - return this.result_clear_highlight(); - } - } - }; - - Chosen.prototype.keydown_backstroke = function() { - var next_available_destroy; - if (this.pending_backstroke) { - this.choice_destroy(this.pending_backstroke.find("a").first()); - return this.clear_backstroke(); - } else { - next_available_destroy = this.search_container.siblings("li.search-choice").last(); - if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) { - this.pending_backstroke = next_available_destroy; - if (this.single_backstroke_delete) { - return this.keydown_backstroke(); - } else { - return this.pending_backstroke.addClass("search-choice-focus"); - } - } - } - }; - - Chosen.prototype.clear_backstroke = function() { - if (this.pending_backstroke) { - this.pending_backstroke.removeClass("search-choice-focus"); - } - return this.pending_backstroke = null; - }; - - Chosen.prototype.keydown_checker = function(evt) { - var stroke, _ref1; - stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode; - this.search_field_scale(); - if (stroke !== 8 && this.pending_backstroke) { - this.clear_backstroke(); - } - switch (stroke) { - case 8: - this.backstroke_length = this.search_field.val().length; - break; - case 9: - if (this.results_showing && !this.is_multiple) { - this.result_select(evt); - } - this.mouse_on_container = false; - break; - case 13: - if (this.results_showing) { - evt.preventDefault(); - } - break; - case 32: - if (this.disable_search) { - evt.preventDefault(); - } - break; - case 38: - evt.preventDefault(); - this.keyup_arrow(); - break; - case 40: - evt.preventDefault(); - this.keydown_arrow(); - break; - } - }; - - Chosen.prototype.search_field_scale = function() { - var div, f_width, h, style, style_block, styles, w, _i, _len; - if (this.is_multiple) { - h = 0; - w = 0; - style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"; - styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing']; - for (_i = 0, _len = styles.length; _i < _len; _i++) { - style = styles[_i]; - style_block += style + ":" + this.search_field.css(style) + ";"; - } - div = $('
      ', { - 'style': style_block - }); - div.text(this.search_field.val()); - $('body').append(div); - w = div.width() + 25; - div.remove(); - f_width = this.container.outerWidth(); - if (w > f_width - 10) { - w = f_width - 10; - } - return this.search_field.css({ - 'width': w + 'px' - }); - } - }; - - return Chosen; - - })(AbstractChosen); - -}).call(this); diff --git a/vendor/assets/javascripts/codemirror.js b/vendor/assets/javascripts/codemirror.js deleted file mode 100644 index 73e034e..0000000 --- a/vendor/assets/javascripts/codemirror.js +++ /dev/null @@ -1,9304 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// This is CodeMirror (http://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.CodeMirror = factory()); -}(this, (function () { 'use strict'; - -// Kludges for bugs and behavior differences that can't be feature -// detected are enabled based on userAgent etc sniffing. -var userAgent = navigator.userAgent -var platform = navigator.platform - -var gecko = /gecko\/\d/i.test(userAgent) -var ie_upto10 = /MSIE \d/.test(userAgent) -var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent) -var edge = /Edge\/(\d+)/.exec(userAgent) -var ie = ie_upto10 || ie_11up || edge -var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]) -var webkit = !edge && /WebKit\//.test(userAgent) -var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent) -var chrome = !edge && /Chrome\//.test(userAgent) -var presto = /Opera\//.test(userAgent) -var safari = /Apple Computer/.test(navigator.vendor) -var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent) -var phantom = /PhantomJS/.test(userAgent) - -var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent) -var android = /Android/.test(userAgent) -// This is woefully incomplete. Suggestions for alternative methods welcome. -var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent) -var mac = ios || /Mac/.test(platform) -var chromeOS = /\bCrOS\b/.test(userAgent) -var windows = /win/i.test(platform) - -var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/) -if (presto_version) { presto_version = Number(presto_version[1]) } -if (presto_version && presto_version >= 15) { presto = false; webkit = true } -// Some browsers use the wrong event properties to signal cmd/ctrl on OS X -var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)) -var captureRightClick = gecko || (ie && ie_version >= 9) - -function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } - -var rmClass = function(node, cls) { - var current = node.className - var match = classTest(cls).exec(current) - if (match) { - var after = current.slice(match.index + match[0].length) - node.className = current.slice(0, match.index) + (after ? match[1] + after : "") - } -} - -function removeChildren(e) { - for (var count = e.childNodes.length; count > 0; --count) - { e.removeChild(e.firstChild) } - return e -} - -function removeChildrenAndAdd(parent, e) { - return removeChildren(parent).appendChild(e) -} - -function elt(tag, content, className, style) { - var e = document.createElement(tag) - if (className) { e.className = className } - if (style) { e.style.cssText = style } - if (typeof content == "string") { e.appendChild(document.createTextNode(content)) } - else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]) } } - return e -} -// wrapper for elt, which removes the elt from the accessibility tree -function eltP(tag, content, className, style) { - var e = elt(tag, content, className, style) - e.setAttribute("role", "presentation") - return e -} - -var range -if (document.createRange) { range = function(node, start, end, endNode) { - var r = document.createRange() - r.setEnd(endNode || node, end) - r.setStart(node, start) - return r -} } -else { range = function(node, start, end) { - var r = document.body.createTextRange() - try { r.moveToElementText(node.parentNode) } - catch(e) { return r } - r.collapse(true) - r.moveEnd("character", end) - r.moveStart("character", start) - return r -} } - -function contains(parent, child) { - if (child.nodeType == 3) // Android browser always returns false when child is a textnode - { child = child.parentNode } - if (parent.contains) - { return parent.contains(child) } - do { - if (child.nodeType == 11) { child = child.host } - if (child == parent) { return true } - } while (child = child.parentNode) -} - -function activeElt() { - // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. - // IE < 10 will throw when accessed while the page is loading or in an iframe. - // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. - var activeElement - try { - activeElement = document.activeElement - } catch(e) { - activeElement = document.body || null - } - while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) - { activeElement = activeElement.shadowRoot.activeElement } - return activeElement -} - -function addClass(node, cls) { - var current = node.className - if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls } -} -function joinClasses(a, b) { - var as = a.split(" ") - for (var i = 0; i < as.length; i++) - { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i] } } - return b -} - -var selectInput = function(node) { node.select() } -if (ios) // Mobile Safari apparently has a bug where select() is broken. - { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length } } -else if (ie) // Suppress mysterious IE10 errors - { selectInput = function(node) { try { node.select() } catch(_e) {} } } - -function bind(f) { - var args = Array.prototype.slice.call(arguments, 1) - return function(){return f.apply(null, args)} -} - -function copyObj(obj, target, overwrite) { - if (!target) { target = {} } - for (var prop in obj) - { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) - { target[prop] = obj[prop] } } - return target -} - -// Counts the column offset in a string, taking tabs into account. -// Used mostly to find indentation. -function countColumn(string, end, tabSize, startIndex, startValue) { - if (end == null) { - end = string.search(/[^\s\u00a0]/) - if (end == -1) { end = string.length } - } - for (var i = startIndex || 0, n = startValue || 0;;) { - var nextTab = string.indexOf("\t", i) - if (nextTab < 0 || nextTab >= end) - { return n + (end - i) } - n += nextTab - i - n += tabSize - (n % tabSize) - i = nextTab + 1 - } -} - -var Delayed = function() {this.id = null}; -Delayed.prototype.set = function (ms, f) { - clearTimeout(this.id) - this.id = setTimeout(f, ms) -}; - -function indexOf(array, elt) { - for (var i = 0; i < array.length; ++i) - { if (array[i] == elt) { return i } } - return -1 -} - -// Number of pixels added to scroller and sizer to hide scrollbar -var scrollerGap = 30 - -// Returned or thrown by various protocols to signal 'I'm not -// handling this'. -var Pass = {toString: function(){return "CodeMirror.Pass"}} - -// Reused option objects for setSelection & friends -var sel_dontScroll = {scroll: false}; -var sel_mouse = {origin: "*mouse"}; -var sel_move = {origin: "+move"}; -// The inverse of countColumn -- find the offset that corresponds to -// a particular column. -function findColumn(string, goal, tabSize) { - for (var pos = 0, col = 0;;) { - var nextTab = string.indexOf("\t", pos) - if (nextTab == -1) { nextTab = string.length } - var skipped = nextTab - pos - if (nextTab == string.length || col + skipped >= goal) - { return pos + Math.min(skipped, goal - col) } - col += nextTab - pos - col += tabSize - (col % tabSize) - pos = nextTab + 1 - if (col >= goal) { return pos } - } -} - -var spaceStrs = [""] -function spaceStr(n) { - while (spaceStrs.length <= n) - { spaceStrs.push(lst(spaceStrs) + " ") } - return spaceStrs[n] -} - -function lst(arr) { return arr[arr.length-1] } - -function map(array, f) { - var out = [] - for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i) } - return out -} - -function insertSorted(array, value, score) { - var pos = 0, priority = score(value) - while (pos < array.length && score(array[pos]) <= priority) { pos++ } - array.splice(pos, 0, value) -} - -function nothing() {} - -function createObj(base, props) { - var inst - if (Object.create) { - inst = Object.create(base) - } else { - nothing.prototype = base - inst = new nothing() - } - if (props) { copyObj(props, inst) } - return inst -} - -var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/ -function isWordCharBasic(ch) { - return /\w/.test(ch) || ch > "\x80" && - (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) -} -function isWordChar(ch, helper) { - if (!helper) { return isWordCharBasic(ch) } - if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } - return helper.test(ch) -} - -function isEmpty(obj) { - for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } - return true -} - -// Extending unicode characters. A series of a non-extending char + -// any number of extending chars is treated as a single unit as far -// as editing and measuring is concerned. This is not fully correct, -// since some scripts/fonts/browsers also treat other configurations -// of code points as a group. -var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/ -function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } - -// Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. -function skipExtendingChars(str, pos, dir) { - while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir } - return pos -} - -// Returns the value from the range [`from`; `to`] that satisfies -// `pred` and is closest to `from`. Assumes that at least `to` satisfies `pred`. -function findFirst(pred, from, to) { - for (;;) { - if (Math.abs(from - to) <= 1) { return pred(from) ? from : to } - var mid = Math.floor((from + to) / 2) - if (pred(mid)) { to = mid } - else { from = mid } - } -} - -// The display handles the DOM integration, both for input reading -// and content drawing. It holds references to DOM nodes and -// display-related state. - -function Display(place, doc, input) { - var d = this - this.input = input - - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler") - d.scrollbarFiller.setAttribute("cm-not-content", "true") - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler") - d.gutterFiller.setAttribute("cm-not-content", "true") - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = eltP("div", null, "CodeMirror-code") - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1") - d.cursorDiv = elt("div", null, "CodeMirror-cursors") - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure") - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure") - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none") - var lines = eltP("div", [d.lineSpace], "CodeMirror-lines") - // Moved around its parent to cover visible view. - d.mover = elt("div", [lines], null, "position: relative") - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer") - d.sizerWidth = null - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;") - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters") - d.lineGutter = null - // Actual scrollable element. - d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll") - d.scroller.setAttribute("tabIndex", "-1") - // The element in which the editor lives. - d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror") - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0 } - if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true } - - if (place) { - if (place.appendChild) { place.appendChild(d.wrapper) } - else { place(d.wrapper) } - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first - d.reportedViewFrom = d.reportedViewTo = doc.first - // Information about the rendered lines. - d.view = [] - d.renderedView = null - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null - // Empty space (in pixels) above the view - d.viewOffset = 0 - d.lastWrapHeight = d.lastWrapWidth = 0 - d.updateLineNumbers = null - - d.nativeBarWidth = d.barHeight = d.barWidth = 0 - d.scrollbarsClipped = false - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null - d.maxLineLength = 0 - d.maxLineChanged = false - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null - - // True when shift is held down. - d.shift = false - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null - - d.activeTouch = null - - input.init(d) -} - -// Find the line object corresponding to the given line number. -function getLine(doc, n) { - n -= doc.first - if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } - var chunk = doc - while (!chunk.lines) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize() - if (n < sz) { chunk = child; break } - n -= sz - } - } - return chunk.lines[n] -} - -// Get the part of a document between two positions, as an array of -// strings. -function getBetween(doc, start, end) { - var out = [], n = start.line - doc.iter(start.line, end.line + 1, function (line) { - var text = line.text - if (n == end.line) { text = text.slice(0, end.ch) } - if (n == start.line) { text = text.slice(start.ch) } - out.push(text) - ++n - }) - return out -} -// Get the lines between from and to, as array of strings. -function getLines(doc, from, to) { - var out = [] - doc.iter(from, to, function (line) { out.push(line.text) }) // iter aborts when callback returns truthy value - return out -} - -// Update the height of a line, propagating the height change -// upwards to parent nodes. -function updateLineHeight(line, height) { - var diff = height - line.height - if (diff) { for (var n = line; n; n = n.parent) { n.height += diff } } -} - -// Given a line object, find its line number by walking up through -// its parent links. -function lineNo(line) { - if (line.parent == null) { return null } - var cur = line.parent, no = indexOf(cur.lines, line) - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0;; ++i) { - if (chunk.children[i] == cur) { break } - no += chunk.children[i].chunkSize() - } - } - return no + cur.first -} - -// Find the line at the given vertical position, using the height -// information in the document tree. -function lineAtHeight(chunk, h) { - var n = chunk.first - outer: do { - for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { - var child = chunk.children[i$1], ch = child.height - if (h < ch) { chunk = child; continue outer } - h -= ch - n += child.chunkSize() - } - return n - } while (!chunk.lines) - var i = 0 - for (; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height - if (h < lh) { break } - h -= lh - } - return n + i -} - -function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} - -function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)) -} - -// A Pos instance represents a position within the text. -function Pos(line, ch, sticky) { - if ( sticky === void 0 ) sticky = null; - - if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } - this.line = line - this.ch = ch - this.sticky = sticky -} - -// Compare two positions, return 0 if they are the same, a negative -// number when a is less, and a positive number otherwise. -function cmp(a, b) { return a.line - b.line || a.ch - b.ch } - -function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } - -function copyPos(x) {return Pos(x.line, x.ch)} -function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } -function minPos(a, b) { return cmp(a, b) < 0 ? a : b } - -// Most of the external API clips given positions to make sure they -// actually exist within the document. -function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} -function clipPos(doc, pos) { - if (pos.line < doc.first) { return Pos(doc.first, 0) } - var last = doc.first + doc.size - 1 - if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } - return clipToLen(pos, getLine(doc, pos.line).text.length) -} -function clipToLen(pos, linelen) { - var ch = pos.ch - if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } - else if (ch < 0) { return Pos(pos.line, 0) } - else { return pos } -} -function clipPosArray(doc, array) { - var out = [] - for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]) } - return out -} - -// Optimize some code when these features are not used. -var sawReadOnlySpans = false; -var sawCollapsedSpans = false; -function seeReadOnlySpans() { - sawReadOnlySpans = true -} - -function seeCollapsedSpans() { - sawCollapsedSpans = true -} - -// TEXTMARKER SPANS - -function MarkedSpan(marker, from, to) { - this.marker = marker - this.from = from; this.to = to -} - -// Search an array of spans for a span matching the given marker. -function getMarkedSpanFor(spans, marker) { - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i] - if (span.marker == marker) { return span } - } } -} -// Remove a span from an array, returning undefined if no spans are -// left (we don't store arrays for lines without spans). -function removeMarkedSpan(spans, span) { - var r - for (var i = 0; i < spans.length; ++i) - { if (spans[i] != span) { (r || (r = [])).push(spans[i]) } } - return r -} -// Add a span to a line. -function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span] - span.marker.attachLine(line) -} - -// Used for the algorithm that adjusts markers for a change in the -// document. These functions cut an array of spans at a given -// character position, returning an array of remaining chunks (or -// undefined if nothing remains). -function markedSpansBefore(old, startCh, isInsert) { - var nw - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh) - if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)) - } - } } - return nw -} -function markedSpansAfter(old, endCh, isInsert) { - var nw - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh) - if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)) - } - } } - return nw -} - -// Given a change object, compute the new set of marker spans that -// cover the line in which the change took place. Removes spans -// entirely within the change, reconnects spans belonging to the -// same marker that appear on both sides of the change, and cuts off -// spans partially within the change. Returns an array of span -// arrays with one element for each line in (after) the change. -function stretchSpansOverChange(doc, change) { - if (change.full) { return null } - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans - if (!oldFirst && !oldLast) { return null } - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0 - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert) - var last = markedSpansAfter(oldLast, endCh, isInsert) - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0) - if (first) { - // Fix up .to properties of first - for (var i = 0; i < first.length; ++i) { - var span = first[i] - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker) - if (!found) { span.to = startCh } - else if (sameLine) { span.to = found.to == null ? null : found.to + offset } - } - } - } - if (last) { - // Fix up .from in last (or move them into first in case of sameLine) - for (var i$1 = 0; i$1 < last.length; ++i$1) { - var span$1 = last[i$1] - if (span$1.to != null) { span$1.to += offset } - if (span$1.from == null) { - var found$1 = getMarkedSpanFor(first, span$1.marker) - if (!found$1) { - span$1.from = offset - if (sameLine) { (first || (first = [])).push(span$1) } - } - } else { - span$1.from += offset - if (sameLine) { (first || (first = [])).push(span$1) } - } - } - } - // Make sure we didn't create any zero-length spans - if (first) { first = clearEmptySpans(first) } - if (last && last != first) { last = clearEmptySpans(last) } - - var newMarkers = [first] - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers - if (gap > 0 && first) - { for (var i$2 = 0; i$2 < first.length; ++i$2) - { if (first[i$2].to == null) - { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)) } } } - for (var i$3 = 0; i$3 < gap; ++i$3) - { newMarkers.push(gapMarkers) } - newMarkers.push(last) - } - return newMarkers -} - -// Remove spans that are empty and don't have a clearWhenEmpty -// option of false. -function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i] - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - { spans.splice(i--, 1) } - } - if (!spans.length) { return null } - return spans -} - -// Used to 'clip' out readOnly ranges when making a change. -function removeReadOnlyRanges(doc, from, to) { - var markers = null - doc.iter(from.line, to.line + 1, function (line) { - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - { (markers || (markers = [])).push(mark) } - } } - }) - if (!markers) { return null } - var parts = [{from: from, to: to}] - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0) - for (var j = 0; j < parts.length; ++j) { - var p = parts[j] - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to) - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - { newParts.push({from: p.from, to: m.from}) } - if (dto > 0 || !mk.inclusiveRight && !dto) - { newParts.push({from: m.to, to: p.to}) } - parts.splice.apply(parts, newParts) - j += newParts.length - 3 - } - } - return parts -} - -// Connect or disconnect spans from a line. -function detachMarkedSpans(line) { - var spans = line.markedSpans - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.detachLine(line) } - line.markedSpans = null -} -function attachMarkedSpans(line, spans) { - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.attachLine(line) } - line.markedSpans = spans -} - -// Helpers used when computing which overlapping collapsed span -// counts as the larger one. -function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } -function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } - -// Returns a number indicating which of two overlapping collapsed -// spans is larger (and thus includes the other). Falls back to -// comparing ids when the spans cover exactly the same range. -function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length - if (lenDiff != 0) { return lenDiff } - var aPos = a.find(), bPos = b.find() - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b) - if (fromCmp) { return -fromCmp } - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b) - if (toCmp) { return toCmp } - return b.id - a.id -} - -// Find out whether a line ends or starts in a collapsed span. If -// so, return the marker for that span. -function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i] - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - { found = sp.marker } - } } - return found -} -function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } -function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } - -// Test whether there exists a collapsed span that partially -// overlaps (covers the start or end, but not both) of a new span. -// Such overlap is not allowed. -function conflictingCollapsedRange(doc, lineNo, from, to, marker) { - var line = getLine(doc, lineNo) - var sps = sawCollapsedSpans && line.markedSpans - if (sps) { for (var i = 0; i < sps.length; ++i) { - var sp = sps[i] - if (!sp.marker.collapsed) { continue } - var found = sp.marker.find(0) - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker) - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker) - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } - if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || - fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) - { return true } - } } -} - -// A visual line is a line as drawn on the screen. Folding, for -// example, can cause multiple logical lines to appear on the same -// visual line. This finds the start of the visual line that the -// given line is part of (usually that is the line itself). -function visualLine(line) { - var merged - while (merged = collapsedSpanAtStart(line)) - { line = merged.find(-1, true).line } - return line -} - -function visualLineEnd(line) { - var merged - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line } - return line -} - -// Returns an array of logical lines that continue the visual line -// started by the argument, or undefined if there are no such lines. -function visualLineContinued(line) { - var merged, lines - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line - ;(lines || (lines = [])).push(line) - } - return lines -} - -// Get the line number of the start of the visual line that the -// given line number is part of. -function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line) - if (line == vis) { return lineN } - return lineNo(vis) -} - -// Get the line number of the start of the next visual line after -// the given line. -function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) { return lineN } - var line = getLine(doc, lineN), merged - if (!lineIsHidden(doc, line)) { return lineN } - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line } - return lineNo(line) + 1 -} - -// Compute whether a line is hidden. Lines count as hidden when they -// are part of a visual line that starts with another line, or when -// they are entirely covered by collapsed, non-widget span. -function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i] - if (!sp.marker.collapsed) { continue } - if (sp.from == null) { return true } - if (sp.marker.widgetNode) { continue } - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - { return true } - } } -} -function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true) - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) - } - if (span.marker.inclusiveRight && span.to == line.text.length) - { return true } - for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i] - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) { return true } - } -} - -// Find the height above the given line. -function heightAtLine(lineObj) { - lineObj = visualLine(lineObj) - - var h = 0, chunk = lineObj.parent - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i] - if (line == lineObj) { break } - else { h += line.height } - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i$1 = 0; i$1 < p.children.length; ++i$1) { - var cur = p.children[i$1] - if (cur == chunk) { break } - else { h += cur.height } - } - } - return h -} - -// Compute the character length of a line, taking into account -// collapsed ranges (see markText) that might hide parts, and join -// other lines onto it. -function lineLength(line) { - if (line.height == 0) { return 0 } - var len = line.text.length, merged, cur = line - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true) - cur = found.from.line - len += found.from.ch - found.to.ch - } - cur = line - while (merged = collapsedSpanAtEnd(cur)) { - var found$1 = merged.find(0, true) - len -= cur.text.length - found$1.from.ch - cur = found$1.to.line - len += cur.text.length - found$1.to.ch - } - return len -} - -// Find the longest line in the document. -function findMaxLine(cm) { - var d = cm.display, doc = cm.doc - d.maxLine = getLine(doc, doc.first) - d.maxLineLength = lineLength(d.maxLine) - d.maxLineChanged = true - doc.iter(function (line) { - var len = lineLength(line) - if (len > d.maxLineLength) { - d.maxLineLength = len - d.maxLine = line - } - }) -} - -// BIDI HELPERS - -function iterateBidiSections(order, from, to, f) { - if (!order) { return f(from, to, "ltr") } - var found = false - for (var i = 0; i < order.length; ++i) { - var part = order[i] - if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr") - found = true - } - } - if (!found) { f(from, to, "ltr") } -} - -var bidiOther = null -function getBidiPartAt(order, ch, sticky) { - var found - bidiOther = null - for (var i = 0; i < order.length; ++i) { - var cur = order[i] - if (cur.from < ch && cur.to > ch) { return i } - if (cur.to == ch) { - if (cur.from != cur.to && sticky == "before") { found = i } - else { bidiOther = i } - } - if (cur.from == ch) { - if (cur.from != cur.to && sticky != "before") { found = i } - else { bidiOther = i } - } - } - return found != null ? found : bidiOther -} - -// Bidirectional ordering algorithm -// See http://unicode.org/reports/tr9/tr9-13.html for the algorithm -// that this (partially) implements. - -// One-char codes used for character types: -// L (L): Left-to-Right -// R (R): Right-to-Left -// r (AL): Right-to-Left Arabic -// 1 (EN): European Number -// + (ES): European Number Separator -// % (ET): European Number Terminator -// n (AN): Arabic Number -// , (CS): Common Number Separator -// m (NSM): Non-Spacing Mark -// b (BN): Boundary Neutral -// s (B): Paragraph Separator -// t (S): Segment Separator -// w (WS): Whitespace -// N (ON): Other Neutrals - -// Returns null if characters are ordered as they appear -// (left-to-right), or an array of sections ({from, to, level} -// objects) in the order in which they occur visually. -var bidiOrdering = (function() { - // Character types for codepoints 0 to 0xff - var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN" - // Character types for codepoints 0x600 to 0x6f9 - var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111" - function charType(code) { - if (code <= 0xf7) { return lowTypes.charAt(code) } - else if (0x590 <= code && code <= 0x5f4) { return "R" } - else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } - else if (0x6ee <= code && code <= 0x8ac) { return "r" } - else if (0x2000 <= code && code <= 0x200b) { return "w" } - else if (code == 0x200c) { return "b" } - else { return "L" } - } - - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/ - var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/ - - function BidiSpan(level, from, to) { - this.level = level - this.from = from; this.to = to - } - - return function(str, direction) { - var outerType = direction == "ltr" ? "L" : "R" - - if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } - var len = str.length, types = [] - for (var i = 0; i < len; ++i) - { types.push(charType(str.charCodeAt(i))) } - - // W1. Examine each non-spacing mark (NSM) in the level run, and - // change the type of the NSM to the type of the previous - // character. If the NSM is at the start of the level run, it will - // get the type of sor. - for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { - var type = types[i$1] - if (type == "m") { types[i$1] = prev } - else { prev = type } - } - - // W2. Search backwards from each instance of a European number - // until the first strong type (R, L, AL, or sor) is found. If an - // AL is found, change the type of the European number to Arabic - // number. - // W3. Change all ALs to R. - for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { - var type$1 = types[i$2] - if (type$1 == "1" && cur == "r") { types[i$2] = "n" } - else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R" } } - } - - // W4. A single European separator between two European numbers - // changes to a European number. A single common separator between - // two numbers of the same type changes to that type. - for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { - var type$2 = types[i$3] - if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1" } - else if (type$2 == "," && prev$1 == types[i$3+1] && - (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1 } - prev$1 = type$2 - } - - // W5. A sequence of European terminators adjacent to European - // numbers changes to all European numbers. - // W6. Otherwise, separators and terminators change to Other - // Neutral. - for (var i$4 = 0; i$4 < len; ++i$4) { - var type$3 = types[i$4] - if (type$3 == ",") { types[i$4] = "N" } - else if (type$3 == "%") { - var end = (void 0) - for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N" - for (var j = i$4; j < end; ++j) { types[j] = replace } - i$4 = end - 1 - } - } - - // W7. Search backwards from each instance of a European number - // until the first strong type (R, L, or sor) is found. If an L is - // found, then change the type of the European number to L. - for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { - var type$4 = types[i$5] - if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L" } - else if (isStrong.test(type$4)) { cur$1 = type$4 } - } - - // N1. A sequence of neutrals takes the direction of the - // surrounding strong text if the text on both sides has the same - // direction. European and Arabic numbers act as if they were R in - // terms of their influence on neutrals. Start-of-level-run (sor) - // and end-of-level-run (eor) are used at level run boundaries. - // N2. Any remaining neutrals take the embedding direction. - for (var i$6 = 0; i$6 < len; ++i$6) { - if (isNeutral.test(types[i$6])) { - var end$1 = (void 0) - for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} - var before = (i$6 ? types[i$6-1] : outerType) == "L" - var after = (end$1 < len ? types[end$1] : outerType) == "L" - var replace$1 = before == after ? (before ? "L" : "R") : outerType - for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 } - i$6 = end$1 - 1 - } - } - - // Here we depart from the documented algorithm, in order to avoid - // building up an actual levels array. Since there are only three - // levels (0, 1, 2) in an implementation that doesn't take - // explicit embedding into account, we can build up the order on - // the fly, without following the level-based algorithm. - var order = [], m - for (var i$7 = 0; i$7 < len;) { - if (countsAsLeft.test(types[i$7])) { - var start = i$7 - for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} - order.push(new BidiSpan(0, start, i$7)) - } else { - var pos = i$7, at = order.length - for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} - for (var j$2 = pos; j$2 < i$7;) { - if (countsAsNum.test(types[j$2])) { - if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)) } - var nstart = j$2 - for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} - order.splice(at, 0, new BidiSpan(2, nstart, j$2)) - pos = j$2 - } else { ++j$2 } - } - if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)) } - } - } - if (order[0].level == 1 && (m = str.match(/^\s+/))) { - order[0].from = m[0].length - order.unshift(new BidiSpan(0, 0, m[0].length)) - } - if (lst(order).level == 1 && (m = str.match(/\s+$/))) { - lst(order).to -= m[0].length - order.push(new BidiSpan(0, len - m[0].length, len)) - } - - return direction == "rtl" ? order.reverse() : order - } -})() - -// Get the bidi ordering for the given line (and cache it). Returns -// false for lines that are fully left-to-right, and an array of -// BidiSpan objects otherwise. -function getOrder(line, direction) { - var order = line.order - if (order == null) { order = line.order = bidiOrdering(line.text, direction) } - return order -} - -function moveCharLogically(line, ch, dir) { - var target = skipExtendingChars(line.text, ch + dir, dir) - return target < 0 || target > line.text.length ? null : target -} - -function moveLogically(line, start, dir) { - var ch = moveCharLogically(line, start.ch, dir) - return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") -} - -function endOfLine(visually, cm, lineObj, lineNo, dir) { - if (visually) { - var order = getOrder(lineObj, cm.doc.direction) - if (order) { - var part = dir < 0 ? lst(order) : order[0] - var moveInStorageOrder = (dir < 0) == (part.level == 1) - var sticky = moveInStorageOrder ? "after" : "before" - var ch - // With a wrapped rtl chunk (possibly spanning multiple bidi parts), - // it could be that the last bidi part is not on the last visual line, - // since visual lines contain content order-consecutive chunks. - // Thus, in rtl, we are looking for the first (content-order) character - // in the rtl chunk that is on the last line (that is, the same line - // as the last (content-order) character). - if (part.level > 0) { - var prep = prepareMeasureForLine(cm, lineObj) - ch = dir < 0 ? lineObj.text.length - 1 : 0 - var targetTop = measureCharPrepared(cm, prep, ch).top - ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch) - if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1, true) } - } else { ch = dir < 0 ? part.to : part.from } - return new Pos(lineNo, ch, sticky) - } - } - return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") -} - -function moveVisually(cm, line, start, dir) { - var bidi = getOrder(line, cm.doc.direction) - if (!bidi) { return moveLogically(line, start, dir) } - if (start.ch >= line.text.length) { - start.ch = line.text.length - start.sticky = "before" - } else if (start.ch <= 0) { - start.ch = 0 - start.sticky = "after" - } - var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos] - if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { - // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, - // nothing interesting happens. - return moveLogically(line, start, dir) - } - - var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); } - var prep - var getWrappedLineExtent = function (ch) { - if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } - prep = prep || prepareMeasureForLine(cm, line) - return wrappedLineExtentChar(cm, line, prep, ch) - } - var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch) - - if (cm.doc.direction == "rtl" || part.level == 1) { - var moveInStorageOrder = (part.level == 1) == (dir < 0) - var ch = mv(start, moveInStorageOrder ? 1 : -1) - if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { - // Case 2: We move within an rtl part or in an rtl editor on the same visual line - var sticky = moveInStorageOrder ? "before" : "after" - return new Pos(start.line, ch, sticky) - } - } - - // Case 3: Could not move within this bidi part in this visual line, so leave - // the current bidi part - - var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { - var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder - ? new Pos(start.line, mv(ch, 1), "before") - : new Pos(start.line, ch, "after"); } - - for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { - var part = bidi[partPos] - var moveInStorageOrder = (dir > 0) == (part.level != 1) - var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1) - if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } - ch = moveInStorageOrder ? part.from : mv(part.to, -1) - if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } - } - } - - // Case 3a: Look for other bidi parts on the same visual line - var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent) - if (res) { return res } - - // Case 3b: Look for other bidi parts on the next visual line - var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1) - if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { - res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)) - if (res) { return res } - } - - // Case 4: Nowhere to move - return null -} - -// EVENT HANDLING - -// Lightweight event framework. on/off also work on DOM nodes, -// registering native DOM handlers. - -var noHandlers = [] - -var on = function(emitter, type, f) { - if (emitter.addEventListener) { - emitter.addEventListener(type, f, false) - } else if (emitter.attachEvent) { - emitter.attachEvent("on" + type, f) - } else { - var map = emitter._handlers || (emitter._handlers = {}) - map[type] = (map[type] || noHandlers).concat(f) - } -} - -function getHandlers(emitter, type) { - return emitter._handlers && emitter._handlers[type] || noHandlers -} - -function off(emitter, type, f) { - if (emitter.removeEventListener) { - emitter.removeEventListener(type, f, false) - } else if (emitter.detachEvent) { - emitter.detachEvent("on" + type, f) - } else { - var map = emitter._handlers, arr = map && map[type] - if (arr) { - var index = indexOf(arr, f) - if (index > -1) - { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) } - } - } -} - -function signal(emitter, type /*, values...*/) { - var handlers = getHandlers(emitter, type) - if (!handlers.length) { return } - var args = Array.prototype.slice.call(arguments, 2) - for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args) } -} - -// The DOM events that CodeMirror handles can be overridden by -// registering a (non-DOM) handler on the editor for the event name, -// and preventDefault-ing the event in that handler. -function signalDOMEvent(cm, e, override) { - if (typeof e == "string") - { e = {type: e, preventDefault: function() { this.defaultPrevented = true }} } - signal(cm, override || e.type, cm, e) - return e_defaultPrevented(e) || e.codemirrorIgnore -} - -function signalCursorActivity(cm) { - var arr = cm._handlers && cm._handlers.cursorActivity - if (!arr) { return } - var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []) - for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) - { set.push(arr[i]) } } -} - -function hasHandler(emitter, type) { - return getHandlers(emitter, type).length > 0 -} - -// Add on and off methods to a constructor's prototype, to make -// registering events on such objects more convenient. -function eventMixin(ctor) { - ctor.prototype.on = function(type, f) {on(this, type, f)} - ctor.prototype.off = function(type, f) {off(this, type, f)} -} - -// Due to the fact that we still support jurassic IE versions, some -// compatibility wrappers are needed. - -function e_preventDefault(e) { - if (e.preventDefault) { e.preventDefault() } - else { e.returnValue = false } -} -function e_stopPropagation(e) { - if (e.stopPropagation) { e.stopPropagation() } - else { e.cancelBubble = true } -} -function e_defaultPrevented(e) { - return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false -} -function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)} - -function e_target(e) {return e.target || e.srcElement} -function e_button(e) { - var b = e.which - if (b == null) { - if (e.button & 1) { b = 1 } - else if (e.button & 2) { b = 3 } - else if (e.button & 4) { b = 2 } - } - if (mac && e.ctrlKey && b == 1) { b = 3 } - return b -} - -// Detect drag-and-drop -var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie && ie_version < 9) { return false } - var div = elt('div') - return "draggable" in div || "dragDrop" in div -}() - -var zwspSupported -function zeroWidthElement(measure) { - if (zwspSupported == null) { - var test = elt("span", "\u200b") - removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])) - if (measure.firstChild.offsetHeight != 0) - { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8) } - } - var node = zwspSupported ? elt("span", "\u200b") : - elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px") - node.setAttribute("cm-text", "") - return node -} - -// Feature-detect IE's crummy client rect reporting for bidi text -var badBidiRects -function hasBadBidiRects(measure) { - if (badBidiRects != null) { return badBidiRects } - var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")) - var r0 = range(txt, 0, 1).getBoundingClientRect() - var r1 = range(txt, 1, 2).getBoundingClientRect() - removeChildren(measure) - if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) - return badBidiRects = (r1.right - r0.right < 3) -} - -// See if "".split is the broken IE version, if so, provide an -// alternative way to split lines. -var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { - var pos = 0, result = [], l = string.length - while (pos <= l) { - var nl = string.indexOf("\n", pos) - if (nl == -1) { nl = string.length } - var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl) - var rt = line.indexOf("\r") - if (rt != -1) { - result.push(line.slice(0, rt)) - pos += rt + 1 - } else { - result.push(line) - pos = nl + 1 - } - } - return result -} : function (string) { return string.split(/\r\n?|\n/); } - -var hasSelection = window.getSelection ? function (te) { - try { return te.selectionStart != te.selectionEnd } - catch(e) { return false } -} : function (te) { - var range - try {range = te.ownerDocument.selection.createRange()} - catch(e) {} - if (!range || range.parentElement() != te) { return false } - return range.compareEndPoints("StartToEnd", range) != 0 -} - -var hasCopyEvent = (function () { - var e = elt("div") - if ("oncopy" in e) { return true } - e.setAttribute("oncopy", "return;") - return typeof e.oncopy == "function" -})() - -var badZoomedRects = null -function hasBadZoomedRects(measure) { - if (badZoomedRects != null) { return badZoomedRects } - var node = removeChildrenAndAdd(measure, elt("span", "x")) - var normal = node.getBoundingClientRect() - var fromRange = range(node, 0, 1).getBoundingClientRect() - return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 -} - -var modes = {}; -var mimeModes = {}; -// Extra arguments are stored as the mode's dependencies, which is -// used by (legacy) mechanisms like loadmode.js to automatically -// load a mode. (Preferred mechanism is the require/define calls.) -function defineMode(name, mode) { - if (arguments.length > 2) - { mode.dependencies = Array.prototype.slice.call(arguments, 2) } - modes[name] = mode -} - -function defineMIME(mime, spec) { - mimeModes[mime] = spec -} - -// Given a MIME type, a {name, ...options} config object, or a name -// string, return a mode config object. -function resolveMode(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { - spec = mimeModes[spec] - } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { - var found = mimeModes[spec.name] - if (typeof found == "string") { found = {name: found} } - spec = createObj(found, spec) - spec.name = found.name - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { - return resolveMode("application/xml") - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { - return resolveMode("application/json") - } - if (typeof spec == "string") { return {name: spec} } - else { return spec || {name: "null"} } -} - -// Given a mode spec (anything that resolveMode accepts), find and -// initialize an actual mode object. -function getMode(options, spec) { - spec = resolveMode(spec) - var mfactory = modes[spec.name] - if (!mfactory) { return getMode(options, "text/plain") } - var modeObj = mfactory(options, spec) - if (modeExtensions.hasOwnProperty(spec.name)) { - var exts = modeExtensions[spec.name] - for (var prop in exts) { - if (!exts.hasOwnProperty(prop)) { continue } - if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop] } - modeObj[prop] = exts[prop] - } - } - modeObj.name = spec.name - if (spec.helperType) { modeObj.helperType = spec.helperType } - if (spec.modeProps) { for (var prop$1 in spec.modeProps) - { modeObj[prop$1] = spec.modeProps[prop$1] } } - - return modeObj -} - -// This can be used to attach properties to mode objects from -// outside the actual mode definition. -var modeExtensions = {} -function extendMode(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}) - copyObj(properties, exts) -} - -function copyState(mode, state) { - if (state === true) { return state } - if (mode.copyState) { return mode.copyState(state) } - var nstate = {} - for (var n in state) { - var val = state[n] - if (val instanceof Array) { val = val.concat([]) } - nstate[n] = val - } - return nstate -} - -// Given a mode and a state (for that mode), find the inner mode and -// state at the position that the state refers to. -function innerMode(mode, state) { - var info - while (mode.innerMode) { - info = mode.innerMode(state) - if (!info || info.mode == mode) { break } - state = info.state - mode = info.mode - } - return info || {mode: mode, state: state} -} - -function startState(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true -} - -// STRING STREAM - -// Fed to the mode parsers, provides helper functions to make -// parsers more succinct. - -var StringStream = function(string, tabSize) { - this.pos = this.start = 0 - this.string = string - this.tabSize = tabSize || 8 - this.lastColumnPos = this.lastColumnValue = 0 - this.lineStart = 0 -}; - -StringStream.prototype.eol = function () {return this.pos >= this.string.length}; -StringStream.prototype.sol = function () {return this.pos == this.lineStart}; -StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; -StringStream.prototype.next = function () { - if (this.pos < this.string.length) - { return this.string.charAt(this.pos++) } -}; -StringStream.prototype.eat = function (match) { - var ch = this.string.charAt(this.pos) - var ok - if (typeof match == "string") { ok = ch == match } - else { ok = ch && (match.test ? match.test(ch) : match(ch)) } - if (ok) {++this.pos; return ch} -}; -StringStream.prototype.eatWhile = function (match) { - var start = this.pos - while (this.eat(match)){} - return this.pos > start -}; -StringStream.prototype.eatSpace = function () { - var this$1 = this; - - var start = this.pos - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos } - return this.pos > start -}; -StringStream.prototype.skipToEnd = function () {this.pos = this.string.length}; -StringStream.prototype.skipTo = function (ch) { - var found = this.string.indexOf(ch, this.pos) - if (found > -1) {this.pos = found; return true} -}; -StringStream.prototype.backUp = function (n) {this.pos -= n}; -StringStream.prototype.column = function () { - if (this.lastColumnPos < this.start) { - this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue) - this.lastColumnPos = this.start - } - return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) -}; -StringStream.prototype.indentation = function () { - return countColumn(this.string, null, this.tabSize) - - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) -}; -StringStream.prototype.match = function (pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; } - var substr = this.string.substr(this.pos, pattern.length) - if (cased(substr) == cased(pattern)) { - if (consume !== false) { this.pos += pattern.length } - return true - } - } else { - var match = this.string.slice(this.pos).match(pattern) - if (match && match.index > 0) { return null } - if (match && consume !== false) { this.pos += match[0].length } - return match - } -}; -StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; -StringStream.prototype.hideFirstChars = function (n, inner) { - this.lineStart += n - try { return inner() } - finally { this.lineStart -= n } -}; - -// Compute a style array (an array starting with a mode generation -// -- for invalidation -- followed by pairs of end positions and -// style strings), which is used to highlight the tokens on the -// line. -function highlightLine(cm, line, state, forceToEnd) { - // A styles array always starts with a number identifying the - // mode/overlays that it is based on (for easy invalidation). - var st = [cm.state.modeGen], lineClasses = {} - // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function (end, style) { return st.push(end, style); }, - lineClasses, forceToEnd) - - // Run overlays, adjust style array. - var loop = function ( o ) { - var overlay = cm.state.overlays[o], i = 1, at = 0 - runMode(cm, line.text, overlay.mode, true, function (end, style) { - var start = i - // Ensure there's a token end at the current position, and that i points at it - while (at < end) { - var i_end = st[i] - if (i_end > end) - { st.splice(i, 1, end, st[i+1], i_end) } - i += 2 - at = Math.min(end, i_end) - } - if (!style) { return } - if (overlay.opaque) { - st.splice(start, i - start, end, "overlay " + style) - i = start + 2 - } else { - for (; start < i; start += 2) { - var cur = st[start+1] - st[start+1] = (cur ? cur + " " : "") + "overlay " + style - } - } - }, lineClasses) - }; - - for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); - - return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} -} - -function getLineStyles(cm, line, updateFrontier) { - if (!line.styles || line.styles[0] != cm.state.modeGen) { - var state = getStateBefore(cm, lineNo(line)) - var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state) - line.stateAfter = state - line.styles = result.styles - if (result.classes) { line.styleClasses = result.classes } - else if (line.styleClasses) { line.styleClasses = null } - if (updateFrontier === cm.doc.frontier) { cm.doc.frontier++ } - } - return line.styles -} - -function getStateBefore(cm, n, precise) { - var doc = cm.doc, display = cm.display - if (!doc.mode.startState) { return true } - var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter - if (!state) { state = startState(doc.mode) } - else { state = copyState(doc.mode, state) } - doc.iter(pos, n, function (line) { - processLine(cm, line.text, state) - var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo - line.stateAfter = save ? copyState(doc.mode, state) : null - ++pos - }) - if (precise) { doc.frontier = pos } - return state -} - -// Lightweight form of highlight -- proceed over this line and -// update state, but don't save a style array. Used for lines that -// aren't currently visible. -function processLine(cm, text, state, startAt) { - var mode = cm.doc.mode - var stream = new StringStream(text, cm.options.tabSize) - stream.start = stream.pos = startAt || 0 - if (text == "") { callBlankLine(mode, state) } - while (!stream.eol()) { - readToken(mode, stream, state) - stream.start = stream.pos - } -} - -function callBlankLine(mode, state) { - if (mode.blankLine) { return mode.blankLine(state) } - if (!mode.innerMode) { return } - var inner = innerMode(mode, state) - if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } -} - -function readToken(mode, stream, state, inner) { - for (var i = 0; i < 10; i++) { - if (inner) { inner[0] = innerMode(mode, state).mode } - var style = mode.token(stream, state) - if (stream.pos > stream.start) { return style } - } - throw new Error("Mode " + mode.name + " failed to advance stream.") -} - -// Utility for getTokenAt and getLineTokens -function takeToken(cm, pos, precise, asArray) { - var getObj = function (copy) { return ({ - start: stream.start, end: stream.pos, - string: stream.current(), - type: style || null, - state: copy ? copyState(doc.mode, state) : state - }); } - - var doc = cm.doc, mode = doc.mode, style - pos = clipPos(doc, pos) - var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise) - var stream = new StringStream(line.text, cm.options.tabSize), tokens - if (asArray) { tokens = [] } - while ((asArray || stream.pos < pos.ch) && !stream.eol()) { - stream.start = stream.pos - style = readToken(mode, stream, state) - if (asArray) { tokens.push(getObj(true)) } - } - return asArray ? tokens : getObj() -} - -function extractLineClasses(type, output) { - if (type) { for (;;) { - var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/) - if (!lineClass) { break } - type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length) - var prop = lineClass[1] ? "bgClass" : "textClass" - if (output[prop] == null) - { output[prop] = lineClass[2] } - else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) - { output[prop] += " " + lineClass[2] } - } } - return type -} - -// Run the given mode's parser over a line, calling f for each token. -function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { - var flattenSpans = mode.flattenSpans - if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans } - var curStart = 0, curStyle = null - var stream = new StringStream(text, cm.options.tabSize), style - var inner = cm.options.addModeClass && [null] - if (text == "") { extractLineClasses(callBlankLine(mode, state), lineClasses) } - while (!stream.eol()) { - if (stream.pos > cm.options.maxHighlightLength) { - flattenSpans = false - if (forceToEnd) { processLine(cm, text, state, stream.pos) } - stream.pos = text.length - style = null - } else { - style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses) - } - if (inner) { - var mName = inner[0].name - if (mName) { style = "m-" + (style ? mName + " " + style : mName) } - } - if (!flattenSpans || curStyle != style) { - while (curStart < stream.start) { - curStart = Math.min(stream.start, curStart + 5000) - f(curStart, curStyle) - } - curStyle = style - } - stream.start = stream.pos - } - while (curStart < stream.pos) { - // Webkit seems to refuse to render text nodes longer than 57444 - // characters, and returns inaccurate measurements in nodes - // starting around 5000 chars. - var pos = Math.min(stream.pos, curStart + 5000) - f(pos, curStyle) - curStart = pos - } -} - -// Finds the line to start with when starting a parse. Tries to -// find a line with a stateAfter, so that it can start with a -// valid state. If that fails, it returns the line with the -// smallest indentation, which tends to need the least context to -// parse correctly. -function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc - var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100) - for (var search = n; search > lim; --search) { - if (search <= doc.first) { return doc.first } - var line = getLine(doc, search - 1) - if (line.stateAfter && (!precise || search <= doc.frontier)) { return search } - var indented = countColumn(line.text, null, cm.options.tabSize) - if (minline == null || minindent > indented) { - minline = search - 1 - minindent = indented - } - } - return minline -} - -// LINE DATA STRUCTURE - -// Line objects. These hold state related to a line, including -// highlighting info (the styles array). -var Line = function(text, markedSpans, estimateHeight) { - this.text = text - attachMarkedSpans(this, markedSpans) - this.height = estimateHeight ? estimateHeight(this) : 1 -}; - -Line.prototype.lineNo = function () { return lineNo(this) }; -eventMixin(Line) - -// Change the content (text, markers) of a line. Automatically -// invalidates cached information and tries to re-estimate the -// line's height. -function updateLine(line, text, markedSpans, estimateHeight) { - line.text = text - if (line.stateAfter) { line.stateAfter = null } - if (line.styles) { line.styles = null } - if (line.order != null) { line.order = null } - detachMarkedSpans(line) - attachMarkedSpans(line, markedSpans) - var estHeight = estimateHeight ? estimateHeight(line) : 1 - if (estHeight != line.height) { updateLineHeight(line, estHeight) } -} - -// Detach a line from the document tree and its markers. -function cleanUpLine(line) { - line.parent = null - detachMarkedSpans(line) -} - -// Convert a style as returned by a mode (either null, or a string -// containing one or more styles) to a CSS style. This is cached, -// and also looks for line-wide styles. -var styleToClassCache = {}; -var styleToClassCacheWithMode = {}; -function interpretTokenStyle(style, options) { - if (!style || /^\s*$/.test(style)) { return null } - var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache - return cache[style] || - (cache[style] = style.replace(/\S+/g, "cm-$&")) -} - -// Render the DOM representation of the text of a line. Also builds -// up a 'line map', which points at the DOM nodes that represent -// specific stretches of text, and is used by the measuring code. -// The returned object contains the DOM node, this map, and -// information about line-wide styles that were set by the mode. -function buildLineContent(cm, lineView) { - // The padding-right forces the element to have a 'border', which - // is needed on Webkit to be able to get line-level bounding - // rectangles for it (in measureChar). - var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null) - var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, - col: 0, pos: 0, cm: cm, - trailingSpace: false, - splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")} - lineView.measure = {} - - // Iterate over the logical lines that make up this visual line. - for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { - var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0) - builder.pos = 0 - builder.addToken = buildToken - // Optionally wire in some hacks into the token-rendering - // algorithm, to deal with browser quirks. - if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) - { builder.addToken = buildTokenBadBidi(builder.addToken, order) } - builder.map = [] - var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line) - insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)) - if (line.styleClasses) { - if (line.styleClasses.bgClass) - { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "") } - if (line.styleClasses.textClass) - { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "") } - } - - // Ensure at least a single node is present, for measuring. - if (builder.map.length == 0) - { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))) } - - // Store the map and a cache object for the current logical line - if (i == 0) { - lineView.measure.map = builder.map - lineView.measure.cache = {} - } else { - ;(lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) - ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}) - } - } - - // See issue #2901 - if (webkit) { - var last = builder.content.lastChild - if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) - { builder.content.className = "cm-tab-wrap-hack" } - } - - signal(cm, "renderLine", cm, lineView.line, builder.pre) - if (builder.pre.className) - { builder.textClass = joinClasses(builder.pre.className, builder.textClass || "") } - - return builder -} - -function defaultSpecialCharPlaceholder(ch) { - var token = elt("span", "\u2022", "cm-invalidchar") - token.title = "\\u" + ch.charCodeAt(0).toString(16) - token.setAttribute("aria-label", token.title) - return token -} - -// Build up the DOM representation for a single token, and add it to -// the line map. Takes care to render special characters separately. -function buildToken(builder, text, style, startStyle, endStyle, title, css) { - if (!text) { return } - var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text - var special = builder.cm.state.specialChars, mustWrap = false - var content - if (!special.test(text)) { - builder.col += text.length - content = document.createTextNode(displayText) - builder.map.push(builder.pos, builder.pos + text.length, content) - if (ie && ie_version < 9) { mustWrap = true } - builder.pos += text.length - } else { - content = document.createDocumentFragment() - var pos = 0 - while (true) { - special.lastIndex = pos - var m = special.exec(text) - var skipped = m ? m.index - pos : text.length - pos - if (skipped) { - var txt = document.createTextNode(displayText.slice(pos, pos + skipped)) - if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])) } - else { content.appendChild(txt) } - builder.map.push(builder.pos, builder.pos + skipped, txt) - builder.col += skipped - builder.pos += skipped - } - if (!m) { break } - pos += skipped + 1 - var txt$1 = (void 0) - if (m[0] == "\t") { - var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize - txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")) - txt$1.setAttribute("role", "presentation") - txt$1.setAttribute("cm-text", "\t") - builder.col += tabWidth - } else if (m[0] == "\r" || m[0] == "\n") { - txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")) - txt$1.setAttribute("cm-text", m[0]) - builder.col += 1 - } else { - txt$1 = builder.cm.options.specialCharPlaceholder(m[0]) - txt$1.setAttribute("cm-text", m[0]) - if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])) } - else { content.appendChild(txt$1) } - builder.col += 1 - } - builder.map.push(builder.pos, builder.pos + 1, txt$1) - builder.pos++ - } - } - builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32 - if (style || startStyle || endStyle || mustWrap || css) { - var fullStyle = style || "" - if (startStyle) { fullStyle += startStyle } - if (endStyle) { fullStyle += endStyle } - var token = elt("span", [content], fullStyle, css) - if (title) { token.title = title } - return builder.content.appendChild(token) - } - builder.content.appendChild(content) -} - -function splitSpaces(text, trailingBefore) { - if (text.length > 1 && !/ /.test(text)) { return text } - var spaceBefore = trailingBefore, result = "" - for (var i = 0; i < text.length; i++) { - var ch = text.charAt(i) - if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) - { ch = "\u00a0" } - result += ch - spaceBefore = ch == " " - } - return result -} - -// Work around nonsense dimensions being reported for stretches of -// right-to-left text. -function buildTokenBadBidi(inner, order) { - return function (builder, text, style, startStyle, endStyle, title, css) { - style = style ? style + " cm-force-border" : "cm-force-border" - var start = builder.pos, end = start + text.length - for (;;) { - // Find the part that overlaps with the start of this text - var part = (void 0) - for (var i = 0; i < order.length; i++) { - part = order[i] - if (part.to > start && part.from <= start) { break } - } - if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) } - inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css) - startStyle = null - text = text.slice(part.to - start) - start = part.to - } - } -} - -function buildCollapsedSpan(builder, size, marker, ignoreWidget) { - var widget = !ignoreWidget && marker.widgetNode - if (widget) { builder.map.push(builder.pos, builder.pos + size, widget) } - if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { - if (!widget) - { widget = builder.content.appendChild(document.createElement("span")) } - widget.setAttribute("cm-marker", marker.id) - } - if (widget) { - builder.cm.display.input.setUneditable(widget) - builder.content.appendChild(widget) - } - builder.pos += size - builder.trailingSpace = false -} - -// Outputs a number of spans to make up a line, taking highlighting -// and marked text into account. -function insertLineContent(line, builder, styles) { - var spans = line.markedSpans, allText = line.text, at = 0 - if (!spans) { - for (var i$1 = 1; i$1 < styles.length; i$1+=2) - { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)) } - return - } - - var len = allText.length, pos = 0, i = 1, text = "", style, css - var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed - for (;;) { - if (nextChange == pos) { // Update current marker set - spanStyle = spanEndStyle = spanStartStyle = title = css = "" - collapsed = null; nextChange = Infinity - var foundBookmarks = [], endStyles = (void 0) - for (var j = 0; j < spans.length; ++j) { - var sp = spans[j], m = sp.marker - if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { - foundBookmarks.push(m) - } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { - if (sp.to != null && sp.to != pos && nextChange > sp.to) { - nextChange = sp.to - spanEndStyle = "" - } - if (m.className) { spanStyle += " " + m.className } - if (m.css) { css = (css ? css + ";" : "") + m.css } - if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle } - if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to) } - if (m.title && !title) { title = m.title } - if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) - { collapsed = sp } - } else if (sp.from > pos && nextChange > sp.from) { - nextChange = sp.from - } - } - if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) - { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1] } } } - - if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) - { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]) } } - if (collapsed && (collapsed.from || 0) == pos) { - buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, - collapsed.marker, collapsed.from == null) - if (collapsed.to == null) { return } - if (collapsed.to == pos) { collapsed = false } - } - } - if (pos >= len) { break } - - var upto = Math.min(len, nextChange) - while (true) { - if (text) { - var end = pos + text.length - if (!collapsed) { - var tokenText = end > upto ? text.slice(0, upto - pos) : text - builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css) - } - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} - pos = end - spanStartStyle = "" - } - text = allText.slice(at, at = styles[i++]) - style = interpretTokenStyle(styles[i++], builder.cm.options) - } - } -} - - -// These objects are used to represent the visible (currently drawn) -// part of the document. A LineView may correspond to multiple -// logical lines, if those are connected by collapsed ranges. -function LineView(doc, line, lineN) { - // The starting line - this.line = line - // Continuing lines, if any - this.rest = visualLineContinued(line) - // Number of logical lines in this visual line - this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1 - this.node = this.text = null - this.hidden = lineIsHidden(doc, line) -} - -// Create a range of LineView objects for the given lines. -function buildViewArray(cm, from, to) { - var array = [], nextPos - for (var pos = from; pos < to; pos = nextPos) { - var view = new LineView(cm.doc, getLine(cm.doc, pos), pos) - nextPos = pos + view.size - array.push(view) - } - return array -} - -var operationGroup = null - -function pushOperation(op) { - if (operationGroup) { - operationGroup.ops.push(op) - } else { - op.ownsGroup = operationGroup = { - ops: [op], - delayedCallbacks: [] - } - } -} - -function fireCallbacksForOps(group) { - // Calls delayed callbacks and cursorActivity handlers until no - // new ones appear - var callbacks = group.delayedCallbacks, i = 0 - do { - for (; i < callbacks.length; i++) - { callbacks[i].call(null) } - for (var j = 0; j < group.ops.length; j++) { - var op = group.ops[j] - if (op.cursorActivityHandlers) - { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) - { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) } } - } - } while (i < callbacks.length) -} - -function finishOperation(op, endCb) { - var group = op.ownsGroup - if (!group) { return } - - try { fireCallbacksForOps(group) } - finally { - operationGroup = null - endCb(group) - } -} - -var orphanDelayedCallbacks = null - -// Often, we want to signal events at a point where we are in the -// middle of some work, but don't want the handler to start calling -// other methods on the editor, which might be in an inconsistent -// state or simply not expect any other events to happen. -// signalLater looks whether there are any handlers, and schedules -// them to be executed when the last operation ends, or, if no -// operation is active, when a timeout fires. -function signalLater(emitter, type /*, values...*/) { - var arr = getHandlers(emitter, type) - if (!arr.length) { return } - var args = Array.prototype.slice.call(arguments, 2), list - if (operationGroup) { - list = operationGroup.delayedCallbacks - } else if (orphanDelayedCallbacks) { - list = orphanDelayedCallbacks - } else { - list = orphanDelayedCallbacks = [] - setTimeout(fireOrphanDelayed, 0) - } - var loop = function ( i ) { - list.push(function () { return arr[i].apply(null, args); }) - }; - - for (var i = 0; i < arr.length; ++i) - loop( i ); -} - -function fireOrphanDelayed() { - var delayed = orphanDelayedCallbacks - orphanDelayedCallbacks = null - for (var i = 0; i < delayed.length; ++i) { delayed[i]() } -} - -// When an aspect of a line changes, a string is added to -// lineView.changes. This updates the relevant part of the line's -// DOM structure. -function updateLineForChanges(cm, lineView, lineN, dims) { - for (var j = 0; j < lineView.changes.length; j++) { - var type = lineView.changes[j] - if (type == "text") { updateLineText(cm, lineView) } - else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims) } - else if (type == "class") { updateLineClasses(cm, lineView) } - else if (type == "widget") { updateLineWidgets(cm, lineView, dims) } - } - lineView.changes = null -} - -// Lines with gutter elements, widgets or a background class need to -// be wrapped, and have the extra elements added to the wrapper div -function ensureLineWrapped(lineView) { - if (lineView.node == lineView.text) { - lineView.node = elt("div", null, null, "position: relative") - if (lineView.text.parentNode) - { lineView.text.parentNode.replaceChild(lineView.node, lineView.text) } - lineView.node.appendChild(lineView.text) - if (ie && ie_version < 8) { lineView.node.style.zIndex = 2 } - } - return lineView.node -} - -function updateLineBackground(cm, lineView) { - var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass - if (cls) { cls += " CodeMirror-linebackground" } - if (lineView.background) { - if (cls) { lineView.background.className = cls } - else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null } - } else if (cls) { - var wrap = ensureLineWrapped(lineView) - lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild) - cm.display.input.setUneditable(lineView.background) - } -} - -// Wrapper around buildLineContent which will reuse the structure -// in display.externalMeasured when possible. -function getLineContent(cm, lineView) { - var ext = cm.display.externalMeasured - if (ext && ext.line == lineView.line) { - cm.display.externalMeasured = null - lineView.measure = ext.measure - return ext.built - } - return buildLineContent(cm, lineView) -} - -// Redraw the line's text. Interacts with the background and text -// classes because the mode may output tokens that influence these -// classes. -function updateLineText(cm, lineView) { - var cls = lineView.text.className - var built = getLineContent(cm, lineView) - if (lineView.text == lineView.node) { lineView.node = built.pre } - lineView.text.parentNode.replaceChild(built.pre, lineView.text) - lineView.text = built.pre - if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { - lineView.bgClass = built.bgClass - lineView.textClass = built.textClass - updateLineClasses(cm, lineView) - } else if (cls) { - lineView.text.className = cls - } -} - -function updateLineClasses(cm, lineView) { - updateLineBackground(cm, lineView) - if (lineView.line.wrapClass) - { ensureLineWrapped(lineView).className = lineView.line.wrapClass } - else if (lineView.node != lineView.text) - { lineView.node.className = "" } - var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass - lineView.text.className = textClass || "" -} - -function updateLineGutter(cm, lineView, lineN, dims) { - if (lineView.gutter) { - lineView.node.removeChild(lineView.gutter) - lineView.gutter = null - } - if (lineView.gutterBackground) { - lineView.node.removeChild(lineView.gutterBackground) - lineView.gutterBackground = null - } - if (lineView.line.gutterClass) { - var wrap = ensureLineWrapped(lineView) - lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, - ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")) - cm.display.input.setUneditable(lineView.gutterBackground) - wrap.insertBefore(lineView.gutterBackground, lineView.text) - } - var markers = lineView.line.gutterMarkers - if (cm.options.lineNumbers || markers) { - var wrap$1 = ensureLineWrapped(lineView) - var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")) - cm.display.input.setUneditable(gutterWrap) - wrap$1.insertBefore(gutterWrap, lineView.text) - if (lineView.line.gutterClass) - { gutterWrap.className += " " + lineView.line.gutterClass } - if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) - { lineView.lineNumber = gutterWrap.appendChild( - elt("div", lineNumberFor(cm.options, lineN), - "CodeMirror-linenumber CodeMirror-gutter-elt", - ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))) } - if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) { - var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id] - if (found) - { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", - ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))) } - } } - } -} - -function updateLineWidgets(cm, lineView, dims) { - if (lineView.alignable) { lineView.alignable = null } - for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { - next = node.nextSibling - if (node.className == "CodeMirror-linewidget") - { lineView.node.removeChild(node) } - } - insertLineWidgets(cm, lineView, dims) -} - -// Build a line's DOM representation from scratch -function buildLineElement(cm, lineView, lineN, dims) { - var built = getLineContent(cm, lineView) - lineView.text = lineView.node = built.pre - if (built.bgClass) { lineView.bgClass = built.bgClass } - if (built.textClass) { lineView.textClass = built.textClass } - - updateLineClasses(cm, lineView) - updateLineGutter(cm, lineView, lineN, dims) - insertLineWidgets(cm, lineView, dims) - return lineView.node -} - -// A lineView may contain multiple logical lines (when merged by -// collapsed spans). The widgets for all of them need to be drawn. -function insertLineWidgets(cm, lineView, dims) { - insertLineWidgetsFor(cm, lineView.line, lineView, dims, true) - if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) - { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false) } } -} - -function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { - if (!line.widgets) { return } - var wrap = ensureLineWrapped(lineView) - for (var i = 0, ws = line.widgets; i < ws.length; ++i) { - var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget") - if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true") } - positionLineWidget(widget, node, lineView, dims) - cm.display.input.setUneditable(node) - if (allowAbove && widget.above) - { wrap.insertBefore(node, lineView.gutter || lineView.text) } - else - { wrap.appendChild(node) } - signalLater(widget, "redraw") - } -} - -function positionLineWidget(widget, node, lineView, dims) { - if (widget.noHScroll) { - ;(lineView.alignable || (lineView.alignable = [])).push(node) - var width = dims.wrapperWidth - node.style.left = dims.fixedPos + "px" - if (!widget.coverGutter) { - width -= dims.gutterTotalWidth - node.style.paddingLeft = dims.gutterTotalWidth + "px" - } - node.style.width = width + "px" - } - if (widget.coverGutter) { - node.style.zIndex = 5 - node.style.position = "relative" - if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px" } - } -} - -function widgetHeight(widget) { - if (widget.height != null) { return widget.height } - var cm = widget.doc.cm - if (!cm) { return 0 } - if (!contains(document.body, widget.node)) { - var parentStyle = "position: relative;" - if (widget.coverGutter) - { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;" } - if (widget.noHScroll) - { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;" } - removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)) - } - return widget.height = widget.node.parentNode.offsetHeight -} - -// Return true when the given mouse event happened in a widget -function eventInWidget(display, e) { - for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { - if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || - (n.parentNode == display.sizer && n != display.mover)) - { return true } - } -} - -// POSITION MEASUREMENT - -function paddingTop(display) {return display.lineSpace.offsetTop} -function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} -function paddingH(display) { - if (display.cachedPaddingH) { return display.cachedPaddingH } - var e = removeChildrenAndAdd(display.measure, elt("pre", "x")) - var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle - var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)} - if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data } - return data -} - -function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } -function displayWidth(cm) { - return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth -} -function displayHeight(cm) { - return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight -} - -// Ensure the lineView.wrapping.heights array is populated. This is -// an array of bottom offsets for the lines that make up a drawn -// line. When lineWrapping is on, there might be more than one -// height. -function ensureLineHeights(cm, lineView, rect) { - var wrapping = cm.options.lineWrapping - var curWidth = wrapping && displayWidth(cm) - if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { - var heights = lineView.measure.heights = [] - if (wrapping) { - lineView.measure.width = curWidth - var rects = lineView.text.firstChild.getClientRects() - for (var i = 0; i < rects.length - 1; i++) { - var cur = rects[i], next = rects[i + 1] - if (Math.abs(cur.bottom - next.bottom) > 2) - { heights.push((cur.bottom + next.top) / 2 - rect.top) } - } - } - heights.push(rect.bottom - rect.top) - } -} - -// Find a line map (mapping character offsets to text nodes) and a -// measurement cache for the given line number. (A line view might -// contain multiple lines when collapsed ranges are present.) -function mapFromLineView(lineView, line, lineN) { - if (lineView.line == line) - { return {map: lineView.measure.map, cache: lineView.measure.cache} } - for (var i = 0; i < lineView.rest.length; i++) - { if (lineView.rest[i] == line) - { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } - for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) - { if (lineNo(lineView.rest[i$1]) > lineN) - { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } -} - -// Render a line into the hidden node display.externalMeasured. Used -// when measurement is needed for a line that's not in the viewport. -function updateExternalMeasurement(cm, line) { - line = visualLine(line) - var lineN = lineNo(line) - var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN) - view.lineN = lineN - var built = view.built = buildLineContent(cm, view) - view.text = built.pre - removeChildrenAndAdd(cm.display.lineMeasure, built.pre) - return view -} - -// Get a {top, bottom, left, right} box (in line-local coordinates) -// for a given character. -function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) -} - -// Find a line view that corresponds to the given line number. -function findViewForLine(cm, lineN) { - if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) - { return cm.display.view[findViewIndex(cm, lineN)] } - var ext = cm.display.externalMeasured - if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) - { return ext } -} - -// Measurement can be split in two steps, the set-up work that -// applies to the whole line, and the measurement of the actual -// character. Functions like coordsChar, that need to do a lot of -// measurements in a row, can thus ensure that the set-up work is -// only done once. -function prepareMeasureForLine(cm, line) { - var lineN = lineNo(line) - var view = findViewForLine(cm, lineN) - if (view && !view.text) { - view = null - } else if (view && view.changes) { - updateLineForChanges(cm, view, lineN, getDimensions(cm)) - cm.curOp.forceUpdate = true - } - if (!view) - { view = updateExternalMeasurement(cm, line) } - - var info = mapFromLineView(view, line, lineN) - return { - line: line, view: view, rect: null, - map: info.map, cache: info.cache, before: info.before, - hasHeights: false - } -} - -// Given a prepared measurement object, measures the position of an -// actual character (or fetches it from the cache). -function measureCharPrepared(cm, prepared, ch, bias, varHeight) { - if (prepared.before) { ch = -1 } - var key = ch + (bias || ""), found - if (prepared.cache.hasOwnProperty(key)) { - found = prepared.cache[key] - } else { - if (!prepared.rect) - { prepared.rect = prepared.view.text.getBoundingClientRect() } - if (!prepared.hasHeights) { - ensureLineHeights(cm, prepared.view, prepared.rect) - prepared.hasHeights = true - } - found = measureCharInner(cm, prepared, ch, bias) - if (!found.bogus) { prepared.cache[key] = found } - } - return {left: found.left, right: found.right, - top: varHeight ? found.rtop : found.top, - bottom: varHeight ? found.rbottom : found.bottom} -} - -var nullRect = {left: 0, right: 0, top: 0, bottom: 0} - -function nodeAndOffsetInLineMap(map, ch, bias) { - var node, start, end, collapse, mStart, mEnd - // First, search the line map for the text node corresponding to, - // or closest to, the target character. - for (var i = 0; i < map.length; i += 3) { - mStart = map[i] - mEnd = map[i + 1] - if (ch < mStart) { - start = 0; end = 1 - collapse = "left" - } else if (ch < mEnd) { - start = ch - mStart - end = start + 1 - } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { - end = mEnd - mStart - start = end - 1 - if (ch >= mEnd) { collapse = "right" } - } - if (start != null) { - node = map[i + 2] - if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) - { collapse = bias } - if (bias == "left" && start == 0) - { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { - node = map[(i -= 3) + 2] - collapse = "left" - } } - if (bias == "right" && start == mEnd - mStart) - { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { - node = map[(i += 3) + 2] - collapse = "right" - } } - break - } - } - return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} -} - -function getUsefulRect(rects, bias) { - var rect = nullRect - if (bias == "left") { for (var i = 0; i < rects.length; i++) { - if ((rect = rects[i]).left != rect.right) { break } - } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { - if ((rect = rects[i$1]).left != rect.right) { break } - } } - return rect -} - -function measureCharInner(cm, prepared, ch, bias) { - var place = nodeAndOffsetInLineMap(prepared.map, ch, bias) - var node = place.node, start = place.start, end = place.end, collapse = place.collapse - - var rect - if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. - for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned - while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start } - while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end } - if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) - { rect = node.parentNode.getBoundingClientRect() } - else - { rect = getUsefulRect(range(node, start, end).getClientRects(), bias) } - if (rect.left || rect.right || start == 0) { break } - end = start - start = start - 1 - collapse = "right" - } - if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect) } - } else { // If it is a widget, simply get the box for the whole widget. - if (start > 0) { collapse = bias = "right" } - var rects - if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) - { rect = rects[bias == "right" ? rects.length - 1 : 0] } - else - { rect = node.getBoundingClientRect() } - } - if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { - var rSpan = node.parentNode.getClientRects()[0] - if (rSpan) - { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom} } - else - { rect = nullRect } - } - - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top - var mid = (rtop + rbot) / 2 - var heights = prepared.view.measure.heights - var i = 0 - for (; i < heights.length - 1; i++) - { if (mid < heights[i]) { break } } - var top = i ? heights[i - 1] : 0, bot = heights[i] - var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, - right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, - top: top, bottom: bot} - if (!rect.left && !rect.right) { result.bogus = true } - if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot } - - return result -} - -// Work around problem with bounding client rects on ranges being -// returned incorrectly when zoomed on IE10 and below. -function maybeUpdateRectForZooming(measure, rect) { - if (!window.screen || screen.logicalXDPI == null || - screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) - { return rect } - var scaleX = screen.logicalXDPI / screen.deviceXDPI - var scaleY = screen.logicalYDPI / screen.deviceYDPI - return {left: rect.left * scaleX, right: rect.right * scaleX, - top: rect.top * scaleY, bottom: rect.bottom * scaleY} -} - -function clearLineMeasurementCacheFor(lineView) { - if (lineView.measure) { - lineView.measure.cache = {} - lineView.measure.heights = null - if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) - { lineView.measure.caches[i] = {} } } - } -} - -function clearLineMeasurementCache(cm) { - cm.display.externalMeasure = null - removeChildren(cm.display.lineMeasure) - for (var i = 0; i < cm.display.view.length; i++) - { clearLineMeasurementCacheFor(cm.display.view[i]) } -} - -function clearCaches(cm) { - clearLineMeasurementCache(cm) - cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null - if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true } - cm.display.lineNumChars = null -} - -function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft } -function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop } - -// Converts a {top, bottom, left, right} box from line-local -// coordinates into another coordinate system. Context may be one of -// "line", "div" (display.lineDiv), "local"./null (editor), "window", -// or "page". -function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { - if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]) - rect.top += size; rect.bottom += size - } } } - if (context == "line") { return rect } - if (!context) { context = "local" } - var yOff = heightAtLine(lineObj) - if (context == "local") { yOff += paddingTop(cm.display) } - else { yOff -= cm.display.viewOffset } - if (context == "page" || context == "window") { - var lOff = cm.display.lineSpace.getBoundingClientRect() - yOff += lOff.top + (context == "window" ? 0 : pageScrollY()) - var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()) - rect.left += xOff; rect.right += xOff - } - rect.top += yOff; rect.bottom += yOff - return rect -} - -// Coverts a box from "div" coords to another coordinate system. -// Context may be "window", "page", "div", or "local"./null. -function fromCoordSystem(cm, coords, context) { - if (context == "div") { return coords } - var left = coords.left, top = coords.top - // First move into "page" coordinate system - if (context == "page") { - left -= pageScrollX() - top -= pageScrollY() - } else if (context == "local" || !context) { - var localBox = cm.display.sizer.getBoundingClientRect() - left += localBox.left - top += localBox.top - } - - var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect() - return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} -} - -function charCoords(cm, pos, context, lineObj, bias) { - if (!lineObj) { lineObj = getLine(cm.doc, pos.line) } - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) -} - -// Returns a box for a given cursor position, which may have an -// 'other' property containing the position of the secondary cursor -// on a bidi boundary. -// A cursor Pos(line, char, "before") is on the same visual line as `char - 1` -// and after `char - 1` in writing order of `char - 1` -// A cursor Pos(line, char, "after") is on the same visual line as `char` -// and before `char` in writing order of `char` -// Examples (upper-case letters are RTL, lower-case are LTR): -// Pos(0, 1, ...) -// before after -// ab a|b a|b -// aB a|B aB| -// Ab |Ab A|b -// AB B|A B|A -// Every position after the last character on a line is considered to stick -// to the last character on the line. -function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { - lineObj = lineObj || getLine(cm.doc, pos.line) - if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) } - function get(ch, right) { - var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight) - if (right) { m.left = m.right; } else { m.right = m.left } - return intoCoordSystem(cm, lineObj, m, context) - } - var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky - if (ch >= lineObj.text.length) { - ch = lineObj.text.length - sticky = "before" - } else if (ch <= 0) { - ch = 0 - sticky = "after" - } - if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } - - function getBidi(ch, partPos, invert) { - var part = order[partPos], right = (part.level % 2) != 0 - return get(invert ? ch - 1 : ch, right != invert) - } - var partPos = getBidiPartAt(order, ch, sticky) - var other = bidiOther - var val = getBidi(ch, partPos, sticky == "before") - if (other != null) { val.other = getBidi(ch, other, sticky != "before") } - return val -} - -// Used to cheaply estimate the coordinates for a position. Used for -// intermediate scroll updates. -function estimateCoords(cm, pos) { - var left = 0 - pos = clipPos(cm.doc, pos) - if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch } - var lineObj = getLine(cm.doc, pos.line) - var top = heightAtLine(lineObj) + paddingTop(cm.display) - return {left: left, right: left, top: top, bottom: top + lineObj.height} -} - -// Positions returned by coordsChar contain some extra information. -// xRel is the relative x position of the input coordinates compared -// to the found position (so xRel > 0 means the coordinates are to -// the right of the character position, for example). When outside -// is true, that means the coordinates lie outside the line's -// vertical range. -function PosWithInfo(line, ch, sticky, outside, xRel) { - var pos = Pos(line, ch, sticky) - pos.xRel = xRel - if (outside) { pos.outside = true } - return pos -} - -// Compute the character position closest to the given coordinates. -// Input must be lineSpace-local ("div" coordinate system). -function coordsChar(cm, x, y) { - var doc = cm.doc - y += cm.display.viewOffset - if (y < 0) { return PosWithInfo(doc.first, 0, null, true, -1) } - var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1 - if (lineN > last) - { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, true, 1) } - if (x < 0) { x = 0 } - - var lineObj = getLine(doc, lineN) - for (;;) { - var found = coordsCharInner(cm, lineObj, lineN, x, y) - var merged = collapsedSpanAtEnd(lineObj) - var mergedPos = merged && merged.find(0, true) - if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) - { lineN = lineNo(lineObj = mergedPos.to.line) } - else - { return found } - } -} - -function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { - var measure = function (ch) { return intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line"); } - var end = lineObj.text.length - var begin = findFirst(function (ch) { return measure(ch - 1).bottom <= y; }, end, 0) - end = findFirst(function (ch) { return measure(ch).top > y; }, begin, end) - return {begin: begin, end: end} -} - -function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { - var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top - return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) -} - -function coordsCharInner(cm, lineObj, lineNo, x, y) { - y -= heightAtLine(lineObj) - var begin = 0, end = lineObj.text.length - var preparedMeasure = prepareMeasureForLine(cm, lineObj) - var pos - var order = getOrder(lineObj, cm.doc.direction) - if (order) { - if (cm.options.lineWrapping) { - ;var assign; - ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end, assign)) - } - pos = new Pos(lineNo, begin) - var beginLeft = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - var dir = beginLeft < x ? 1 : -1 - var prevDiff, diff = beginLeft - x, prevPos - do { - prevDiff = diff - prevPos = pos - pos = moveVisually(cm, lineObj, pos, dir) - if (pos == null || pos.ch < begin || end <= (pos.sticky == "before" ? pos.ch - 1 : pos.ch)) { - pos = prevPos - break - } - diff = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - x - } while ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff))) - if (Math.abs(diff) > Math.abs(prevDiff)) { - if ((diff < 0) == (prevDiff < 0)) { throw new Error("Broke out of infinite loop in coordsCharInner") } - pos = prevPos - } - } else { - var ch = findFirst(function (ch) { - var box = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line") - if (box.top > y) { - // For the cursor stickiness - end = Math.min(ch, end) - return true - } - else if (box.bottom <= y) { return false } - else if (box.left > x) { return true } - else if (box.right < x) { return false } - else { return (x - box.left < box.right - x) } - }, begin, end) - ch = skipExtendingChars(lineObj.text, ch, 1) - pos = new Pos(lineNo, ch, ch == end ? "before" : "after") - } - var coords = cursorCoords(cm, pos, "line", lineObj, preparedMeasure) - if (y < coords.top || coords.bottom < y) { pos.outside = true } - pos.xRel = x < coords.left ? -1 : (x > coords.right ? 1 : 0) - return pos -} - -var measureText -// Compute the default text height. -function textHeight(display) { - if (display.cachedTextHeight != null) { return display.cachedTextHeight } - if (measureText == null) { - measureText = elt("pre") - // Measure a bunch of lines, for browsers that compute - // fractional heights. - for (var i = 0; i < 49; ++i) { - measureText.appendChild(document.createTextNode("x")) - measureText.appendChild(elt("br")) - } - measureText.appendChild(document.createTextNode("x")) - } - removeChildrenAndAdd(display.measure, measureText) - var height = measureText.offsetHeight / 50 - if (height > 3) { display.cachedTextHeight = height } - removeChildren(display.measure) - return height || 1 -} - -// Compute the default character width. -function charWidth(display) { - if (display.cachedCharWidth != null) { return display.cachedCharWidth } - var anchor = elt("span", "xxxxxxxxxx") - var pre = elt("pre", [anchor]) - removeChildrenAndAdd(display.measure, pre) - var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10 - if (width > 2) { display.cachedCharWidth = width } - return width || 10 -} - -// Do a bulk-read of the DOM positions and sizes needed to draw the -// view, so that we don't interleave reading and writing to the DOM. -function getDimensions(cm) { - var d = cm.display, left = {}, width = {} - var gutterLeft = d.gutters.clientLeft - for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft - width[cm.options.gutters[i]] = n.clientWidth - } - return {fixedPos: compensateForHScroll(d), - gutterTotalWidth: d.gutters.offsetWidth, - gutterLeft: left, - gutterWidth: width, - wrapperWidth: d.wrapper.clientWidth} -} - -// Computes display.scroller.scrollLeft + display.gutters.offsetWidth, -// but using getBoundingClientRect to get a sub-pixel-accurate -// result. -function compensateForHScroll(display) { - return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left -} - -// Returns a function that estimates the height of a line, to use as -// first approximation until the line becomes visible (and is thus -// properly measurable). -function estimateHeight(cm) { - var th = textHeight(cm.display), wrapping = cm.options.lineWrapping - var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3) - return function (line) { - if (lineIsHidden(cm.doc, line)) { return 0 } - - var widgetsHeight = 0 - if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { - if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height } - } } - - if (wrapping) - { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } - else - { return widgetsHeight + th } - } -} - -function estimateLineHeights(cm) { - var doc = cm.doc, est = estimateHeight(cm) - doc.iter(function (line) { - var estHeight = est(line) - if (estHeight != line.height) { updateLineHeight(line, estHeight) } - }) -} - -// Given a mouse event, find the corresponding position. If liberal -// is false, it checks whether a gutter or scrollbar was clicked, -// and returns null if it was. forRect is used by rectangular -// selections, and tries to estimate a character position even for -// coordinates beyond the right of the text. -function posFromMouse(cm, e, liberal, forRect) { - var display = cm.display - if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } - - var x, y, space = display.lineSpace.getBoundingClientRect() - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX - space.left; y = e.clientY - space.top } - catch (e) { return null } - var coords = coordsChar(cm, x, y), line - if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { - var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length - coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)) - } - return coords -} - -// Find the view element corresponding to a given line. Return null -// when the line isn't visible. -function findViewIndex(cm, n) { - if (n >= cm.display.viewTo) { return null } - n -= cm.display.viewFrom - if (n < 0) { return null } - var view = cm.display.view - for (var i = 0; i < view.length; i++) { - n -= view[i].size - if (n < 0) { return i } - } -} - -function updateSelection(cm) { - cm.display.input.showSelection(cm.display.input.prepareSelection()) -} - -function prepareSelection(cm, primary) { - var doc = cm.doc, result = {} - var curFragment = result.cursors = document.createDocumentFragment() - var selFragment = result.selection = document.createDocumentFragment() - - for (var i = 0; i < doc.sel.ranges.length; i++) { - if (primary === false && i == doc.sel.primIndex) { continue } - var range = doc.sel.ranges[i] - if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } - var collapsed = range.empty() - if (collapsed || cm.options.showCursorWhenSelecting) - { drawSelectionCursor(cm, range.head, curFragment) } - if (!collapsed) - { drawSelectionRange(cm, range, selFragment) } - } - return result -} - -// Draws a cursor for the given range -function drawSelectionCursor(cm, head, output) { - var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine) - - var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")) - cursor.style.left = pos.left + "px" - cursor.style.top = pos.top + "px" - cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px" - - if (pos.other) { - // Secondary cursor, shown when on a 'jump' in bi-directional text - var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")) - otherCursor.style.display = "" - otherCursor.style.left = pos.other.left + "px" - otherCursor.style.top = pos.other.top + "px" - otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px" - } -} - -// Draws the given range as a highlighted selection -function drawSelectionRange(cm, range, output) { - var display = cm.display, doc = cm.doc - var fragment = document.createDocumentFragment() - var padding = paddingH(cm.display), leftSide = padding.left - var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right - - function add(left, top, width, bottom) { - if (top < 0) { top = 0 } - top = Math.round(top) - bottom = Math.round(bottom) - fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))) - } - - function drawForLine(line, fromArg, toArg) { - var lineObj = getLine(doc, line) - var lineLen = lineObj.text.length - var start, end - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias) - } - - iterateBidiSections(getOrder(lineObj, doc.direction), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right - if (from == to) { - rightPos = leftPos - left = right = leftPos.left - } else { - rightPos = coords(to - 1, "right") - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp } - left = leftPos.left - right = rightPos.right - } - if (fromArg == null && from == 0) { left = leftSide } - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom) - left = leftSide - if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) } - } - if (toArg == null && to == lineLen) { right = rightSide } - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - { start = leftPos } - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - { end = rightPos } - if (left < leftSide + 1) { left = leftSide } - add(left, rightPos.top, right - left, rightPos.bottom) - }) - return {start: start, end: end} - } - - var sFrom = range.from(), sTo = range.to() - if (sFrom.line == sTo.line) { - drawForLine(sFrom.line, sFrom.ch, sTo.ch) - } else { - var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line) - var singleVLine = visualLine(fromLine) == visualLine(toLine) - var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end - var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start - if (singleVLine) { - if (leftEnd.top < rightStart.top - 2) { - add(leftEnd.right, leftEnd.top, null, leftEnd.bottom) - add(leftSide, rightStart.top, rightStart.left, rightStart.bottom) - } else { - add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom) - } - } - if (leftEnd.bottom < rightStart.top) - { add(leftSide, leftEnd.bottom, null, rightStart.top) } - } - - output.appendChild(fragment) -} - -// Cursor-blinking -function restartBlink(cm) { - if (!cm.state.focused) { return } - var display = cm.display - clearInterval(display.blinker) - var on = true - display.cursorDiv.style.visibility = "" - if (cm.options.cursorBlinkRate > 0) - { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; }, - cm.options.cursorBlinkRate) } - else if (cm.options.cursorBlinkRate < 0) - { display.cursorDiv.style.visibility = "hidden" } -} - -function ensureFocus(cm) { - if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm) } -} - -function delayBlurEvent(cm) { - cm.state.delayingBlurEvent = true - setTimeout(function () { if (cm.state.delayingBlurEvent) { - cm.state.delayingBlurEvent = false - onBlur(cm) - } }, 100) -} - -function onFocus(cm, e) { - if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false } - - if (cm.options.readOnly == "nocursor") { return } - if (!cm.state.focused) { - signal(cm, "focus", cm, e) - cm.state.focused = true - addClass(cm.display.wrapper, "CodeMirror-focused") - // This test prevents this from firing when a context - // menu is closed (since the input reset would kill the - // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { - cm.display.input.reset() - if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20) } // Issue #1730 - } - cm.display.input.receivedFocus() - } - restartBlink(cm) -} -function onBlur(cm, e) { - if (cm.state.delayingBlurEvent) { return } - - if (cm.state.focused) { - signal(cm, "blur", cm, e) - cm.state.focused = false - rmClass(cm.display.wrapper, "CodeMirror-focused") - } - clearInterval(cm.display.blinker) - setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false } }, 150) -} - -// Re-align line numbers and gutter marks to compensate for -// horizontal scrolling. -function alignHorizontally(cm) { - var display = cm.display, view = display.view - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft - var gutterW = display.gutters.offsetWidth, left = comp + "px" - for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { - if (cm.options.fixedGutter) { - if (view[i].gutter) - { view[i].gutter.style.left = left } - if (view[i].gutterBackground) - { view[i].gutterBackground.style.left = left } - } - var align = view[i].alignable - if (align) { for (var j = 0; j < align.length; j++) - { align[j].style.left = left } } - } } - if (cm.options.fixedGutter) - { display.gutters.style.left = (comp + gutterW) + "px" } -} - -// Used to ensure that the line number gutter is still the right -// size for the current document size. Returns true when an update -// is needed. -function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) { return false } - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")) - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW - display.lineGutter.style.width = "" - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1 - display.lineNumWidth = display.lineNumInnerWidth + padding - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1 - display.lineGutter.style.width = display.lineNumWidth + "px" - updateGutterSpace(cm) - return true - } - return false -} - -// Read the actual heights of the rendered lines, and update their -// stored heights to match. -function updateHeightsInViewport(cm) { - var display = cm.display - var prevBottom = display.lineDiv.offsetTop - for (var i = 0; i < display.view.length; i++) { - var cur = display.view[i], height = (void 0) - if (cur.hidden) { continue } - if (ie && ie_version < 8) { - var bot = cur.node.offsetTop + cur.node.offsetHeight - height = bot - prevBottom - prevBottom = bot - } else { - var box = cur.node.getBoundingClientRect() - height = box.bottom - box.top - } - var diff = cur.line.height - height - if (height < 2) { height = textHeight(display) } - if (diff > .001 || diff < -.001) { - updateLineHeight(cur.line, height) - updateWidgetHeight(cur.line) - if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) - { updateWidgetHeight(cur.rest[j]) } } - } - } -} - -// Read and store the height of line widgets associated with the -// given line. -function updateWidgetHeight(line) { - if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) - { line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight } } -} - -// Compute the lines that are visible in a given viewport (defaults -// the the current scroll position). viewport may contain top, -// height, and ensure (see op.scrollToPos) properties. -function visibleLines(display, doc, viewport) { - var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop - top = Math.floor(top - paddingTop(display)) - var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight - - var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom) - // Ensure is a {from: {line, ch}, to: {line, ch}} object, and - // forces those lines into the viewport (if possible). - if (viewport && viewport.ensure) { - var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line - if (ensureFrom < from) { - from = ensureFrom - to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight) - } else if (Math.min(ensureTo, doc.lastLine()) >= to) { - from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight) - to = ensureTo - } - } - return {from: from, to: Math.max(to, from + 1)} -} - -// Sync the scrollable area and scrollbars, ensure the viewport -// covers the visible area. -function setScrollTop(cm, val) { - if (Math.abs(cm.doc.scrollTop - val) < 2) { return } - cm.doc.scrollTop = val - if (!gecko) { updateDisplaySimple(cm, {top: val}) } - if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val } - cm.display.scrollbars.setScrollTop(val) - if (gecko) { updateDisplaySimple(cm) } - startWorker(cm, 100) -} -// Sync scroller and scrollbar, ensure the gutter elements are -// aligned. -function setScrollLeft(cm, val, isScroller) { - if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) { return } - val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth) - cm.doc.scrollLeft = val - alignHorizontally(cm) - if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val } - cm.display.scrollbars.setScrollLeft(val) -} - -// Since the delta values reported on mouse wheel events are -// unstandardized between browsers and even browser versions, and -// generally horribly unpredictable, this code starts by measuring -// the scroll effect that the first few mouse wheel events have, -// and, from that, detects the way it can convert deltas to pixel -// offsets afterwards. -// -// The reason we want to know the amount a wheel event will scroll -// is that it gives us a chance to update the display before the -// actual scrolling happens, reducing flickering. - -var wheelSamples = 0; -var wheelPixelsPerUnit = null; -// Fill in a browser-detected starting value on browsers where we -// know one. These don't have to be accurate -- the result of them -// being wrong would just be a slight flicker on the first wheel -// scroll (if it is large enough). -if (ie) { wheelPixelsPerUnit = -.53 } -else if (gecko) { wheelPixelsPerUnit = 15 } -else if (chrome) { wheelPixelsPerUnit = -.7 } -else if (safari) { wheelPixelsPerUnit = -1/3 } - -function wheelEventDelta(e) { - var dx = e.wheelDeltaX, dy = e.wheelDeltaY - if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail } - if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail } - else if (dy == null) { dy = e.wheelDelta } - return {x: dx, y: dy} -} -function wheelEventPixels(e) { - var delta = wheelEventDelta(e) - delta.x *= wheelPixelsPerUnit - delta.y *= wheelPixelsPerUnit - return delta -} - -function onScrollWheel(cm, e) { - var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y - - var display = cm.display, scroll = display.scroller - // Quit if there's nothing to scroll here - var canScrollX = scroll.scrollWidth > scroll.clientWidth - var canScrollY = scroll.scrollHeight > scroll.clientHeight - if (!(dx && canScrollX || dy && canScrollY)) { return } - - // Webkit browsers on OS X abort momentum scrolls when the target - // of the scroll event is removed from the scrollable element. - // This hack (see related code in patchDisplay) makes sure the - // element is kept around. - if (dy && mac && webkit) { - outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { - for (var i = 0; i < view.length; i++) { - if (view[i].node == cur) { - cm.display.currentWheelTarget = cur - break outer - } - } - } - } - - // On some browsers, horizontal scrolling will cause redraws to - // happen before the gutter has been realigned, causing it to - // wriggle around in a most unseemly way. When we have an - // estimated pixels/delta value, we just handle horizontal - // scrolling entirely here. It'll be slightly off from native, but - // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { - if (dy && canScrollY) - { setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))) } - setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))) - // Only prevent default scrolling if vertical scrolling is - // actually possible. Otherwise, it causes vertical scroll - // jitter on OSX trackpads when deltaX is small and deltaY - // is large (issue #3579) - if (!dy || (dy && canScrollY)) - { e_preventDefault(e) } - display.wheelStartX = null // Abort measurement, if in progress - return - } - - // 'Project' the visible viewport to cover the area that is being - // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit - var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight - if (pixels < 0) { top = Math.max(0, top + pixels - 50) } - else { bot = Math.min(cm.doc.height, bot + pixels + 50) } - updateDisplaySimple(cm, {top: top, bottom: bot}) - } - - if (wheelSamples < 20) { - if (display.wheelStartX == null) { - display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop - display.wheelDX = dx; display.wheelDY = dy - setTimeout(function () { - if (display.wheelStartX == null) { return } - var movedX = scroll.scrollLeft - display.wheelStartX - var movedY = scroll.scrollTop - display.wheelStartY - var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || - (movedX && display.wheelDX && movedX / display.wheelDX) - display.wheelStartX = display.wheelStartY = null - if (!sample) { return } - wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1) - ++wheelSamples - }, 200) - } else { - display.wheelDX += dx; display.wheelDY += dy - } - } -} - -// SCROLLBARS - -// Prepare DOM reads needed to update the scrollbars. Done in one -// shot to minimize update/measure roundtrips. -function measureForScrollbars(cm) { - var d = cm.display, gutterW = d.gutters.offsetWidth - var docH = Math.round(cm.doc.height + paddingVert(cm.display)) - return { - clientHeight: d.scroller.clientHeight, - viewHeight: d.wrapper.clientHeight, - scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, - viewWidth: d.wrapper.clientWidth, - barLeft: cm.options.fixedGutter ? gutterW : 0, - docHeight: docH, - scrollHeight: docH + scrollGap(cm) + d.barHeight, - nativeBarWidth: d.nativeBarWidth, - gutterWidth: gutterW - } -} - -var NativeScrollbars = function(place, scroll, cm) { - this.cm = cm - var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar") - var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar") - place(vert); place(horiz) - - on(vert, "scroll", function () { - if (vert.clientHeight) { scroll(vert.scrollTop, "vertical") } - }) - on(horiz, "scroll", function () { - if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal") } - }) - - this.checkedZeroWidth = false - // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). - if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px" } -}; - -NativeScrollbars.prototype.update = function (measure) { - var needsH = measure.scrollWidth > measure.clientWidth + 1 - var needsV = measure.scrollHeight > measure.clientHeight + 1 - var sWidth = measure.nativeBarWidth - - if (needsV) { - this.vert.style.display = "block" - this.vert.style.bottom = needsH ? sWidth + "px" : "0" - var totalHeight = measure.viewHeight - (needsH ? sWidth : 0) - // A bug in IE8 can cause this value to be negative, so guard it. - this.vert.firstChild.style.height = - Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px" - } else { - this.vert.style.display = "" - this.vert.firstChild.style.height = "0" - } - - if (needsH) { - this.horiz.style.display = "block" - this.horiz.style.right = needsV ? sWidth + "px" : "0" - this.horiz.style.left = measure.barLeft + "px" - var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0) - this.horiz.firstChild.style.width = - Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px" - } else { - this.horiz.style.display = "" - this.horiz.firstChild.style.width = "0" - } - - if (!this.checkedZeroWidth && measure.clientHeight > 0) { - if (sWidth == 0) { this.zeroWidthHack() } - this.checkedZeroWidth = true - } - - return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} -}; - -NativeScrollbars.prototype.setScrollLeft = function (pos) { - if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos } - if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz) } -}; - -NativeScrollbars.prototype.setScrollTop = function (pos) { - if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos } - if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert) } -}; - -NativeScrollbars.prototype.zeroWidthHack = function () { - var w = mac && !mac_geMountainLion ? "12px" : "18px" - this.horiz.style.height = this.vert.style.width = w - this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none" - this.disableHoriz = new Delayed - this.disableVert = new Delayed -}; - -NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay) { - bar.style.pointerEvents = "auto" - function maybeDisable() { - // To find out whether the scrollbar is still visible, we - // check whether the element under the pixel in the bottom - // left corner of the scrollbar box is the scrollbar box - // itself (when the bar is still visible) or its filler child - // (when the bar is hidden). If it is still visible, we keep - // it enabled, if it's hidden, we disable pointer events. - var box = bar.getBoundingClientRect() - var elt = document.elementFromPoint(box.left + 1, box.bottom - 1) - if (elt != bar) { bar.style.pointerEvents = "none" } - else { delay.set(1000, maybeDisable) } - } - delay.set(1000, maybeDisable) -}; - -NativeScrollbars.prototype.clear = function () { - var parent = this.horiz.parentNode - parent.removeChild(this.horiz) - parent.removeChild(this.vert) -}; - -var NullScrollbars = function () {}; - -NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; -NullScrollbars.prototype.setScrollLeft = function () {}; -NullScrollbars.prototype.setScrollTop = function () {}; -NullScrollbars.prototype.clear = function () {}; - -function updateScrollbars(cm, measure) { - if (!measure) { measure = measureForScrollbars(cm) } - var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight - updateScrollbarsInner(cm, measure) - for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { - if (startWidth != cm.display.barWidth && cm.options.lineWrapping) - { updateHeightsInViewport(cm) } - updateScrollbarsInner(cm, measureForScrollbars(cm)) - startWidth = cm.display.barWidth; startHeight = cm.display.barHeight - } -} - -// Re-synchronize the fake scrollbars with the actual size of the -// content. -function updateScrollbarsInner(cm, measure) { - var d = cm.display - var sizes = d.scrollbars.update(measure) - - d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px" - d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px" - d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent" - - if (sizes.right && sizes.bottom) { - d.scrollbarFiller.style.display = "block" - d.scrollbarFiller.style.height = sizes.bottom + "px" - d.scrollbarFiller.style.width = sizes.right + "px" - } else { d.scrollbarFiller.style.display = "" } - if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { - d.gutterFiller.style.display = "block" - d.gutterFiller.style.height = sizes.bottom + "px" - d.gutterFiller.style.width = measure.gutterWidth + "px" - } else { d.gutterFiller.style.display = "" } -} - -var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars} - -function initScrollbars(cm) { - if (cm.display.scrollbars) { - cm.display.scrollbars.clear() - if (cm.display.scrollbars.addClass) - { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass) } - } - - cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { - cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller) - // Prevent clicks in the scrollbars from killing focus - on(node, "mousedown", function () { - if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0) } - }) - node.setAttribute("cm-not-content", "true") - }, function (pos, axis) { - if (axis == "horizontal") { setScrollLeft(cm, pos) } - else { setScrollTop(cm, pos) } - }, cm) - if (cm.display.scrollbars.addClass) - { addClass(cm.display.wrapper, cm.display.scrollbars.addClass) } -} - -// SCROLLING THINGS INTO VIEW - -// If an editor sits on the top or bottom of the window, partially -// scrolled out of view, this ensures that the cursor is visible. -function maybeScrollWindow(cm, rect) { - if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } - - var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null - if (rect.top + box.top < 0) { doScroll = true } - else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false } - if (doScroll != null && !phantom) { - var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")) - cm.display.lineSpace.appendChild(scrollNode) - scrollNode.scrollIntoView(doScroll) - cm.display.lineSpace.removeChild(scrollNode) - } -} - -// Scroll a given position into view (immediately), verifying that -// it actually became visible (as line heights are accurately -// measured, the position of something may 'drift' during drawing). -function scrollPosIntoView(cm, pos, end, margin) { - if (margin == null) { margin = 0 } - var rect - for (var limit = 0; limit < 5; limit++) { - var changed = false - var coords = cursorCoords(cm, pos) - var endCoords = !end || end == pos ? coords : cursorCoords(cm, end) - rect = {left: Math.min(coords.left, endCoords.left), - top: Math.min(coords.top, endCoords.top) - margin, - right: Math.max(coords.left, endCoords.left), - bottom: Math.max(coords.bottom, endCoords.bottom) + margin} - var scrollPos = calculateScrollPos(cm, rect) - var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft - if (scrollPos.scrollTop != null) { - setScrollTop(cm, scrollPos.scrollTop) - if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true } - } - if (scrollPos.scrollLeft != null) { - setScrollLeft(cm, scrollPos.scrollLeft) - if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true } - } - if (!changed) { break } - } - return rect -} - -// Scroll a given set of coordinates into view (immediately). -function scrollIntoView(cm, rect) { - var scrollPos = calculateScrollPos(cm, rect) - if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop) } - if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft) } -} - -// Calculate a new scroll position needed to scroll the given -// rectangle into view. Returns an object with scrollTop and -// scrollLeft properties. When these are undefined, the -// vertical/horizontal position does not need to be adjusted. -function calculateScrollPos(cm, rect) { - var display = cm.display, snapMargin = textHeight(cm.display) - if (rect.top < 0) { rect.top = 0 } - var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop - var screen = displayHeight(cm), result = {} - if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen } - var docBottom = cm.doc.height + paddingVert(display) - var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin - if (rect.top < screentop) { - result.scrollTop = atTop ? 0 : rect.top - } else if (rect.bottom > screentop + screen) { - var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen) - if (newTop != screentop) { result.scrollTop = newTop } - } - - var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0) - var tooWide = rect.right - rect.left > screenw - if (tooWide) { rect.right = rect.left + screenw } - if (rect.left < 10) - { result.scrollLeft = 0 } - else if (rect.left < screenleft) - { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)) } - else if (rect.right > screenw + screenleft - 3) - { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw } - return result -} - -// Store a relative adjustment to the scroll position in the current -// operation (to be applied when the operation finishes). -function addToScrollPos(cm, left, top) { - if (left != null || top != null) { resolveScrollToPos(cm) } - if (left != null) - { cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left } - if (top != null) - { cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top } -} - -// Make sure that at the end of the operation the current cursor is -// shown. -function ensureCursorVisible(cm) { - resolveScrollToPos(cm) - var cur = cm.getCursor(), from = cur, to = cur - if (!cm.options.lineWrapping) { - from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur - to = Pos(cur.line, cur.ch + 1) - } - cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin} -} - -// When an operation has its scrollToPos property set, and another -// scroll action is applied before the end of the operation, this -// 'simulates' scrolling that position into view in a cheap way, so -// that the effect of intermediate scroll commands is not ignored. -function resolveScrollToPos(cm) { - var range = cm.curOp.scrollToPos - if (range) { - cm.curOp.scrollToPos = null - var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to) - var sPos = calculateScrollPos(cm, { - left: Math.min(from.left, to.left), - top: Math.min(from.top, to.top) - range.margin, - right: Math.max(from.right, to.right), - bottom: Math.max(from.bottom, to.bottom) + range.margin - }) - cm.scrollTo(sPos.scrollLeft, sPos.scrollTop) - } -} - -// Operations are used to wrap a series of changes to the editor -// state in such a way that each change won't have to update the -// cursor and display (which would be awkward, slow, and -// error-prone). Instead, display updates are batched and then all -// combined and executed at once. - -var nextOpId = 0 -// Start a new operation. -function startOperation(cm) { - cm.curOp = { - cm: cm, - viewChanged: false, // Flag that indicates that lines might need to be redrawn - startHeight: cm.doc.height, // Used to detect need to update scrollbar - forceUpdate: false, // Used to force a redraw - updateInput: null, // Whether to reset the input textarea - typing: false, // Whether this reset should be careful to leave existing text (for compositing) - changeObjs: null, // Accumulated changes, for firing change events - cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on - cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already - selectionChanged: false, // Whether the selection needs to be redrawn - updateMaxLine: false, // Set when the widest line needs to be determined anew - scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet - scrollToPos: null, // Used to scroll to a specific position - focus: false, - id: ++nextOpId // Unique ID - } - pushOperation(cm.curOp) -} - -// Finish an operation, updating the display and signalling delayed events -function endOperation(cm) { - var op = cm.curOp - finishOperation(op, function (group) { - for (var i = 0; i < group.ops.length; i++) - { group.ops[i].cm.curOp = null } - endOperations(group) - }) -} - -// The DOM updates done when an operation finishes are batched so -// that the minimum number of relayouts are required. -function endOperations(group) { - var ops = group.ops - for (var i = 0; i < ops.length; i++) // Read DOM - { endOperation_R1(ops[i]) } - for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) - { endOperation_W1(ops[i$1]) } - for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM - { endOperation_R2(ops[i$2]) } - for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) - { endOperation_W2(ops[i$3]) } - for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM - { endOperation_finish(ops[i$4]) } -} - -function endOperation_R1(op) { - var cm = op.cm, display = cm.display - maybeClipScrollbars(cm) - if (op.updateMaxLine) { findMaxLine(cm) } - - op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping - op.update = op.mustUpdate && - new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate) -} - -function endOperation_W1(op) { - op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update) -} - -function endOperation_R2(op) { - var cm = op.cm, display = cm.display - if (op.updatedDisplay) { updateHeightsInViewport(cm) } - - op.barMeasure = measureForScrollbars(cm) - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - // updateDisplay_W2 will use these properties to do the actual resizing - if (display.maxLineChanged && !cm.options.lineWrapping) { - op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3 - cm.display.sizerWidth = op.adjustWidthTo - op.barMeasure.scrollWidth = - Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth) - op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)) - } - - if (op.updatedDisplay || op.selectionChanged) - { op.preparedSelection = display.input.prepareSelection(op.focus) } -} - -function endOperation_W2(op) { - var cm = op.cm - - if (op.adjustWidthTo != null) { - cm.display.sizer.style.minWidth = op.adjustWidthTo + "px" - if (op.maxScrollLeft < cm.doc.scrollLeft) - { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) } - cm.display.maxLineChanged = false - } - - var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()) - if (op.preparedSelection) - { cm.display.input.showSelection(op.preparedSelection, takeFocus) } - if (op.updatedDisplay || op.startHeight != cm.doc.height) - { updateScrollbars(cm, op.barMeasure) } - if (op.updatedDisplay) - { setDocumentHeight(cm, op.barMeasure) } - - if (op.selectionChanged) { restartBlink(cm) } - - if (cm.state.focused && op.updateInput) - { cm.display.input.reset(op.typing) } - if (takeFocus) { ensureFocus(op.cm) } -} - -function endOperation_finish(op) { - var cm = op.cm, display = cm.display, doc = cm.doc - - if (op.updatedDisplay) { postUpdateDisplay(cm, op.update) } - - // Abort mouse wheel delta measurement, when scrolling explicitly - if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) - { display.wheelStartX = display.wheelStartY = null } - - // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { - doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)) - display.scrollbars.setScrollTop(doc.scrollTop) - display.scroller.scrollTop = doc.scrollTop - } - if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { - doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft)) - display.scrollbars.setScrollLeft(doc.scrollLeft) - display.scroller.scrollLeft = doc.scrollLeft - alignHorizontally(cm) - } - // If we need to scroll a specific position into view, do so. - if (op.scrollToPos) { - var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), - clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin) - maybeScrollWindow(cm, rect) - } - - // Fire events for markers that are hidden/unidden by editing or - // undoing - var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers - if (hidden) { for (var i = 0; i < hidden.length; ++i) - { if (!hidden[i].lines.length) { signal(hidden[i], "hide") } } } - if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) - { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide") } } } - - if (display.wrapper.offsetHeight) - { doc.scrollTop = cm.display.scroller.scrollTop } - - // Fire change events, and delayed event handlers - if (op.changeObjs) - { signal(cm, "changes", cm, op.changeObjs) } - if (op.update) - { op.update.finish() } -} - -// Run the given function in an operation -function runInOp(cm, f) { - if (cm.curOp) { return f() } - startOperation(cm) - try { return f() } - finally { endOperation(cm) } -} -// Wraps a function in an operation. Returns the wrapped function. -function operation(cm, f) { - return function() { - if (cm.curOp) { return f.apply(cm, arguments) } - startOperation(cm) - try { return f.apply(cm, arguments) } - finally { endOperation(cm) } - } -} -// Used to add methods to editor and doc instances, wrapping them in -// operations. -function methodOp(f) { - return function() { - if (this.curOp) { return f.apply(this, arguments) } - startOperation(this) - try { return f.apply(this, arguments) } - finally { endOperation(this) } - } -} -function docMethodOp(f) { - return function() { - var cm = this.cm - if (!cm || cm.curOp) { return f.apply(this, arguments) } - startOperation(cm) - try { return f.apply(this, arguments) } - finally { endOperation(cm) } - } -} - -// Updates the display.view data structure for a given change to the -// document. From and to are in pre-change coordinates. Lendiff is -// the amount of lines added or subtracted by the change. This is -// used for changes that span multiple lines, or change the way -// lines are divided into visual lines. regLineChange (below) -// registers single-line changes. -function regChange(cm, from, to, lendiff) { - if (from == null) { from = cm.doc.first } - if (to == null) { to = cm.doc.first + cm.doc.size } - if (!lendiff) { lendiff = 0 } - - var display = cm.display - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - { display.updateLineNumbers = from } - - cm.curOp.viewChanged = true - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - { resetView(cm) } - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm) - } else { - display.viewFrom += lendiff - display.viewTo += lendiff - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm) - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1) - if (cut) { - display.view = display.view.slice(cut.index) - display.viewFrom = cut.lineN - display.viewTo += lendiff - } else { - resetView(cm) - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut$1 = viewCuttingPoint(cm, from, from, -1) - if (cut$1) { - display.view = display.view.slice(0, cut$1.index) - display.viewTo = cut$1.lineN - } else { - resetView(cm) - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1) - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1) - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)) - display.viewTo += lendiff - } else { - resetView(cm) - } - } - - var ext = display.externalMeasured - if (ext) { - if (to < ext.lineN) - { ext.lineN += lendiff } - else if (from < ext.lineN + ext.size) - { display.externalMeasured = null } - } -} - -// Register a change to a single line. Type must be one of "text", -// "gutter", "class", "widget" -function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true - var display = cm.display, ext = cm.display.externalMeasured - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - { display.externalMeasured = null } - - if (line < display.viewFrom || line >= display.viewTo) { return } - var lineView = display.view[findViewIndex(cm, line)] - if (lineView.node == null) { return } - var arr = lineView.changes || (lineView.changes = []) - if (indexOf(arr, type) == -1) { arr.push(type) } -} - -// Clear the view. -function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first - cm.display.view = [] - cm.display.viewOffset = 0 -} - -function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - { return {index: index, lineN: newN} } - var n = cm.display.viewFrom - for (var i = 0; i < index; i++) - { n += view[i].size } - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) { return null } - diff = (n + view[index].size) - oldN - index++ - } else { - diff = n - oldN - } - oldN += diff; newN += diff - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) { return null } - newN += dir * view[index - (dir < 0 ? 1 : 0)].size - index += dir - } - return {index: index, lineN: newN} -} - -// Force the view to cover a given range, adding empty view element -// or clipping off existing ones as needed. -function adjustView(cm, from, to) { - var display = cm.display, view = display.view - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to) - display.viewFrom = from - } else { - if (display.viewFrom > from) - { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view) } - else if (display.viewFrom < from) - { display.view = display.view.slice(findViewIndex(cm, from)) } - display.viewFrom = from - if (display.viewTo < to) - { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)) } - else if (display.viewTo > to) - { display.view = display.view.slice(0, findViewIndex(cm, to)) } - } - display.viewTo = to -} - -// Count the number of lines in the view whose DOM representation is -// out of date (or nonexistent). -function countDirtyView(cm) { - var view = cm.display.view, dirty = 0 - for (var i = 0; i < view.length; i++) { - var lineView = view[i] - if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty } - } - return dirty -} - -// HIGHLIGHT WORKER - -function startWorker(cm, time) { - if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) - { cm.state.highlight.set(time, bind(highlightWorker, cm)) } -} - -function highlightWorker(cm) { - var doc = cm.doc - if (doc.frontier < doc.first) { doc.frontier = doc.first } - if (doc.frontier >= cm.display.viewTo) { return } - var end = +new Date + cm.options.workTime - var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)) - var changedLines = [] - - doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { - if (doc.frontier >= cm.display.viewFrom) { // Visible - var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength - var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true) - line.styles = highlighted.styles - var oldCls = line.styleClasses, newCls = highlighted.classes - if (newCls) { line.styleClasses = newCls } - else if (oldCls) { line.styleClasses = null } - var ischange = !oldStyles || oldStyles.length != line.styles.length || - oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass) - for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i] } - if (ischange) { changedLines.push(doc.frontier) } - line.stateAfter = tooLong ? state : copyState(doc.mode, state) - } else { - if (line.text.length <= cm.options.maxHighlightLength) - { processLine(cm, line.text, state) } - line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null - } - ++doc.frontier - if (+new Date > end) { - startWorker(cm, cm.options.workDelay) - return true - } - }) - if (changedLines.length) { runInOp(cm, function () { - for (var i = 0; i < changedLines.length; i++) - { regLineChange(cm, changedLines[i], "text") } - }) } -} - -// DISPLAY DRAWING - -var DisplayUpdate = function(cm, viewport, force) { - var display = cm.display - - this.viewport = viewport - // Store some values that we'll need later (but don't want to force a relayout for) - this.visible = visibleLines(display, cm.doc, viewport) - this.editorIsHidden = !display.wrapper.offsetWidth - this.wrapperHeight = display.wrapper.clientHeight - this.wrapperWidth = display.wrapper.clientWidth - this.oldDisplayWidth = displayWidth(cm) - this.force = force - this.dims = getDimensions(cm) - this.events = [] -}; - -DisplayUpdate.prototype.signal = function (emitter, type) { - if (hasHandler(emitter, type)) - { this.events.push(arguments) } -}; -DisplayUpdate.prototype.finish = function () { - var this$1 = this; - - for (var i = 0; i < this.events.length; i++) - { signal.apply(null, this$1.events[i]) } -}; - -function maybeClipScrollbars(cm) { - var display = cm.display - if (!display.scrollbarsClipped && display.scroller.offsetWidth) { - display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth - display.heightForcer.style.height = scrollGap(cm) + "px" - display.sizer.style.marginBottom = -display.nativeBarWidth + "px" - display.sizer.style.borderRightWidth = scrollGap(cm) + "px" - display.scrollbarsClipped = true - } -} - -// Does the actual updating of the line display. Bails out -// (returning false) when there is nothing to be done and forced is -// false. -function updateDisplayIfNeeded(cm, update) { - var display = cm.display, doc = cm.doc - - if (update.editorIsHidden) { - resetView(cm) - return false - } - - // Bail out if the visible area is already rendered and nothing changed. - if (!update.force && - update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && - display.renderedView == display.view && countDirtyView(cm) == 0) - { return false } - - if (maybeUpdateLineNumberWidth(cm)) { - resetView(cm) - update.dims = getDimensions(cm) - } - - // Compute a suitable new viewport (from & to) - var end = doc.first + doc.size - var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first) - var to = Math.min(end, update.visible.to + cm.options.viewportMargin) - if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom) } - if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo) } - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from) - to = visualLineEndNo(cm.doc, to) - } - - var different = from != display.viewFrom || to != display.viewTo || - display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth - adjustView(cm, from, to) - - display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)) - // Position the mover div to align with the current scroll position - cm.display.mover.style.top = display.viewOffset + "px" - - var toUpdate = countDirtyView(cm) - if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) - { return false } - - // For big changes, we hide the enclosing element during the - // update, since that speeds up the operations on most browsers. - var focused = activeElt() - if (toUpdate > 4) { display.lineDiv.style.display = "none" } - patchDisplay(cm, display.updateLineNumbers, update.dims) - if (toUpdate > 4) { display.lineDiv.style.display = "" } - display.renderedView = display.view - // There might have been a widget with a focused element that got - // hidden or updated, if so re-focus it. - if (focused && activeElt() != focused && focused.offsetHeight) { focused.focus() } - - // Prevent selection and cursors from interfering with the scroll - // width and height. - removeChildren(display.cursorDiv) - removeChildren(display.selectionDiv) - display.gutters.style.height = display.sizer.style.minHeight = 0 - - if (different) { - display.lastWrapHeight = update.wrapperHeight - display.lastWrapWidth = update.wrapperWidth - startWorker(cm, 400) - } - - display.updateLineNumbers = null - - return true -} - -function postUpdateDisplay(cm, update) { - var viewport = update.viewport - - for (var first = true;; first = false) { - if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { - // Clip forced viewport to actual scrollable area. - if (viewport && viewport.top != null) - { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} } - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - update.visible = visibleLines(cm.display, cm.doc, viewport) - if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) - { break } - } - if (!updateDisplayIfNeeded(cm, update)) { break } - updateHeightsInViewport(cm) - var barMeasure = measureForScrollbars(cm) - updateSelection(cm) - updateScrollbars(cm, barMeasure) - setDocumentHeight(cm, barMeasure) - } - - update.signal(cm, "update", cm) - if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { - update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo) - cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo - } -} - -function updateDisplaySimple(cm, viewport) { - var update = new DisplayUpdate(cm, viewport) - if (updateDisplayIfNeeded(cm, update)) { - updateHeightsInViewport(cm) - postUpdateDisplay(cm, update) - var barMeasure = measureForScrollbars(cm) - updateSelection(cm) - updateScrollbars(cm, barMeasure) - setDocumentHeight(cm, barMeasure) - update.finish() - } -} - -// Sync the actual display DOM structure with display.view, removing -// nodes for lines that are no longer in view, and creating the ones -// that are not there yet, and updating the ones that are out of -// date. -function patchDisplay(cm, updateNumbersFrom, dims) { - var display = cm.display, lineNumbers = cm.options.lineNumbers - var container = display.lineDiv, cur = container.firstChild - - function rm(node) { - var next = node.nextSibling - // Works around a throw-scroll bug in OS X Webkit - if (webkit && mac && cm.display.currentWheelTarget == node) - { node.style.display = "none" } - else - { node.parentNode.removeChild(node) } - return next - } - - var view = display.view, lineN = display.viewFrom - // Loop over the elements in the view, syncing cur (the DOM nodes - // in display.lineDiv) with the view as we go. - for (var i = 0; i < view.length; i++) { - var lineView = view[i] - if (lineView.hidden) { - } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet - var node = buildLineElement(cm, lineView, lineN, dims) - container.insertBefore(node, cur) - } else { // Already drawn - while (cur != lineView.node) { cur = rm(cur) } - var updateNumber = lineNumbers && updateNumbersFrom != null && - updateNumbersFrom <= lineN && lineView.lineNumber - if (lineView.changes) { - if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false } - updateLineForChanges(cm, lineView, lineN, dims) - } - if (updateNumber) { - removeChildren(lineView.lineNumber) - lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))) - } - cur = lineView.node.nextSibling - } - lineN += lineView.size - } - while (cur) { cur = rm(cur) } -} - -function updateGutterSpace(cm) { - var width = cm.display.gutters.offsetWidth - cm.display.sizer.style.marginLeft = width + "px" -} - -function setDocumentHeight(cm, measure) { - cm.display.sizer.style.minHeight = measure.docHeight + "px" - cm.display.heightForcer.style.top = measure.docHeight + "px" - cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px" -} - -// Rebuild the gutter elements, ensure the margin to the left of the -// code matches their width. -function updateGutters(cm) { - var gutters = cm.display.gutters, specs = cm.options.gutters - removeChildren(gutters) - var i = 0 - for (; i < specs.length; ++i) { - var gutterClass = specs[i] - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)) - if (gutterClass == "CodeMirror-linenumbers") { - cm.display.lineGutter = gElt - gElt.style.width = (cm.display.lineNumWidth || 1) + "px" - } - } - gutters.style.display = i ? "" : "none" - updateGutterSpace(cm) -} - -// Make sure the gutters options contains the element -// "CodeMirror-linenumbers" when the lineNumbers option is true. -function setGuttersForLineNumbers(options) { - var found = indexOf(options.gutters, "CodeMirror-linenumbers") - if (found == -1 && options.lineNumbers) { - options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]) - } else if (found > -1 && !options.lineNumbers) { - options.gutters = options.gutters.slice(0) - options.gutters.splice(found, 1) - } -} - -// Selection objects are immutable. A new one is created every time -// the selection changes. A selection is one or more non-overlapping -// (and non-touching) ranges, sorted, and an integer that indicates -// which one is the primary selection (the one that's scrolled into -// view, that getCursor returns, etc). -var Selection = function(ranges, primIndex) { - this.ranges = ranges - this.primIndex = primIndex -}; - -Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; - -Selection.prototype.equals = function (other) { - var this$1 = this; - - if (other == this) { return true } - if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } - for (var i = 0; i < this.ranges.length; i++) { - var here = this$1.ranges[i], there = other.ranges[i] - if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } - } - return true -}; - -Selection.prototype.deepCopy = function () { - var this$1 = this; - - var out = [] - for (var i = 0; i < this.ranges.length; i++) - { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)) } - return new Selection(out, this.primIndex) -}; - -Selection.prototype.somethingSelected = function () { - var this$1 = this; - - for (var i = 0; i < this.ranges.length; i++) - { if (!this$1.ranges[i].empty()) { return true } } - return false -}; - -Selection.prototype.contains = function (pos, end) { - var this$1 = this; - - if (!end) { end = pos } - for (var i = 0; i < this.ranges.length; i++) { - var range = this$1.ranges[i] - if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) - { return i } - } - return -1 -}; - -var Range = function(anchor, head) { - this.anchor = anchor; this.head = head -}; - -Range.prototype.from = function () { return minPos(this.anchor, this.head) }; -Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; -Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; - -// Take an unsorted, potentially overlapping set of ranges, and -// build a selection out of it. 'Consumes' ranges array (modifying -// it). -function normalizeSelection(ranges, primIndex) { - var prim = ranges[primIndex] - ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }) - primIndex = indexOf(ranges, prim) - for (var i = 1; i < ranges.length; i++) { - var cur = ranges[i], prev = ranges[i - 1] - if (cmp(prev.to(), cur.from()) >= 0) { - var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()) - var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head - if (i <= primIndex) { --primIndex } - ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)) - } - } - return new Selection(ranges, primIndex) -} - -function simpleSelection(anchor, head) { - return new Selection([new Range(anchor, head || anchor)], 0) -} - -// Compute the position of the end of a change (its 'to' property -// refers to the pre-change end). -function changeEnd(change) { - if (!change.text) { return change.to } - return Pos(change.from.line + change.text.length - 1, - lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) -} - -// Adjust a position to refer to the post-change position of the -// same text, or the end of the change if the change covers it. -function adjustForChange(pos, change) { - if (cmp(pos, change.from) < 0) { return pos } - if (cmp(pos, change.to) <= 0) { return changeEnd(change) } - - var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch - if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch } - return Pos(line, ch) -} - -function computeSelAfterChange(doc, change) { - var out = [] - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i] - out.push(new Range(adjustForChange(range.anchor, change), - adjustForChange(range.head, change))) - } - return normalizeSelection(out, doc.sel.primIndex) -} - -function offsetPos(pos, old, nw) { - if (pos.line == old.line) - { return Pos(nw.line, pos.ch - old.ch + nw.ch) } - else - { return Pos(nw.line + (pos.line - old.line), pos.ch) } -} - -// Used by replaceSelections to allow moving the selection to the -// start or around the replaced test. Hint may be "start" or "around". -function computeReplacedSel(doc, changes, hint) { - var out = [] - var oldPrev = Pos(doc.first, 0), newPrev = oldPrev - for (var i = 0; i < changes.length; i++) { - var change = changes[i] - var from = offsetPos(change.from, oldPrev, newPrev) - var to = offsetPos(changeEnd(change), oldPrev, newPrev) - oldPrev = change.to - newPrev = to - if (hint == "around") { - var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0 - out[i] = new Range(inv ? to : from, inv ? from : to) - } else { - out[i] = new Range(from, from) - } - } - return new Selection(out, doc.sel.primIndex) -} - -// Used to get the editor into a consistent state again when options change. - -function loadMode(cm) { - cm.doc.mode = getMode(cm.options, cm.doc.modeOption) - resetModeState(cm) -} - -function resetModeState(cm) { - cm.doc.iter(function (line) { - if (line.stateAfter) { line.stateAfter = null } - if (line.styles) { line.styles = null } - }) - cm.doc.frontier = cm.doc.first - startWorker(cm, 100) - cm.state.modeGen++ - if (cm.curOp) { regChange(cm) } -} - -// DOCUMENT DATA STRUCTURE - -// By default, updates that start and end at the beginning of a line -// are treated specially, in order to make the association of line -// widgets and marker elements with the text behave more intuitive. -function isWholeLineUpdate(doc, change) { - return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && - (!doc.cm || doc.cm.options.wholeLineUpdateBefore) -} - -// Perform a change on the document data structure. -function updateDoc(doc, change, markedSpans, estimateHeight) { - function spansFor(n) {return markedSpans ? markedSpans[n] : null} - function update(line, text, spans) { - updateLine(line, text, spans, estimateHeight) - signalLater(line, "change", line, change) - } - function linesFor(start, end) { - var result = [] - for (var i = start; i < end; ++i) - { result.push(new Line(text[i], spansFor(i), estimateHeight)) } - return result - } - - var from = change.from, to = change.to, text = change.text - var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line) - var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line - - // Adjust the line structure - if (change.full) { - doc.insert(0, linesFor(0, text.length)) - doc.remove(text.length, doc.size - text.length) - } else if (isWholeLineUpdate(doc, change)) { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = linesFor(0, text.length - 1) - update(lastLine, lastLine.text, lastSpans) - if (nlines) { doc.remove(from.line, nlines) } - if (added.length) { doc.insert(from.line, added) } - } else if (firstLine == lastLine) { - if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans) - } else { - var added$1 = linesFor(1, text.length - 1) - added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)) - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) - doc.insert(from.line + 1, added$1) - } - } else if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)) - doc.remove(from.line + 1, nlines) - } else { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) - update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans) - var added$2 = linesFor(1, text.length - 1) - if (nlines > 1) { doc.remove(from.line + 1, nlines - 1) } - doc.insert(from.line + 1, added$2) - } - - signalLater(doc, "change", doc, change) -} - -// Call f for all linked documents. -function linkedDocs(doc, f, sharedHistOnly) { - function propagate(doc, skip, sharedHist) { - if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { - var rel = doc.linked[i] - if (rel.doc == skip) { continue } - var shared = sharedHist && rel.sharedHist - if (sharedHistOnly && !shared) { continue } - f(rel.doc, shared) - propagate(rel.doc, doc, shared) - } } - } - propagate(doc, null, true) -} - -// Attach a document to an editor. -function attachDoc(cm, doc) { - if (doc.cm) { throw new Error("This document is already in use.") } - cm.doc = doc - doc.cm = cm - estimateLineHeights(cm) - loadMode(cm) - setDirectionClass(cm) - if (!cm.options.lineWrapping) { findMaxLine(cm) } - cm.options.mode = doc.modeOption - regChange(cm) -} - -function setDirectionClass(cm) { - ;(cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl") -} - -function directionChanged(cm) { - runInOp(cm, function () { - setDirectionClass(cm) - regChange(cm) - }) -} - -function History(startGen) { - // Arrays of change events and selections. Doing something adds an - // event to done and clears undo. Undoing moves events from done - // to undone, redoing moves them in the other direction. - this.done = []; this.undone = [] - this.undoDepth = Infinity - // Used to track when changes can be merged into a single undo - // event - this.lastModTime = this.lastSelTime = 0 - this.lastOp = this.lastSelOp = null - this.lastOrigin = this.lastSelOrigin = null - // Used by the isClean() method - this.generation = this.maxGeneration = startGen || 1 -} - -// Create a history change event from an updateDoc-style change -// object. -function historyChangeFromChange(doc, change) { - var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)} - attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1) - linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true) - return histChange -} - -// Pop all selection events off the end of a history array. Stop at -// a change event. -function clearSelectionEvents(array) { - while (array.length) { - var last = lst(array) - if (last.ranges) { array.pop() } - else { break } - } -} - -// Find the top change event in the history. Pop off selection -// events that are in the way. -function lastChangeEvent(hist, force) { - if (force) { - clearSelectionEvents(hist.done) - return lst(hist.done) - } else if (hist.done.length && !lst(hist.done).ranges) { - return lst(hist.done) - } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { - hist.done.pop() - return lst(hist.done) - } -} - -// Register a change in the history. Merges changes that are within -// a single operation, or are close together with an origin that -// allows merging (starting with "+") into a single event. -function addChangeToHistory(doc, change, selAfter, opId) { - var hist = doc.history - hist.undone.length = 0 - var time = +new Date, cur - var last - - if ((hist.lastOp == opId || - hist.lastOrigin == change.origin && change.origin && - ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || - change.origin.charAt(0) == "*")) && - (cur = lastChangeEvent(hist, hist.lastOp == opId))) { - // Merge this change into the last event - last = lst(cur.changes) - if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { - // Optimized case for simple insertion -- don't want to add - // new changesets for every character typed - last.to = changeEnd(change) - } else { - // Add new sub-event - cur.changes.push(historyChangeFromChange(doc, change)) - } - } else { - // Can not be merged, start a new event. - var before = lst(hist.done) - if (!before || !before.ranges) - { pushSelectionToHistory(doc.sel, hist.done) } - cur = {changes: [historyChangeFromChange(doc, change)], - generation: hist.generation} - hist.done.push(cur) - while (hist.done.length > hist.undoDepth) { - hist.done.shift() - if (!hist.done[0].ranges) { hist.done.shift() } - } - } - hist.done.push(selAfter) - hist.generation = ++hist.maxGeneration - hist.lastModTime = hist.lastSelTime = time - hist.lastOp = hist.lastSelOp = opId - hist.lastOrigin = hist.lastSelOrigin = change.origin - - if (!last) { signal(doc, "historyAdded") } -} - -function selectionEventCanBeMerged(doc, origin, prev, sel) { - var ch = origin.charAt(0) - return ch == "*" || - ch == "+" && - prev.ranges.length == sel.ranges.length && - prev.somethingSelected() == sel.somethingSelected() && - new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) -} - -// Called whenever the selection changes, sets the new selection as -// the pending selection in the history, and pushes the old pending -// selection into the 'done' array when it was significantly -// different (in number of selected ranges, emptiness, or time). -function addSelectionToHistory(doc, sel, opId, options) { - var hist = doc.history, origin = options && options.origin - - // A new event is started when the previous origin does not match - // the current, or the origins don't allow matching. Origins - // starting with * are always merged, those starting with + are - // merged when similar and close together in time. - if (opId == hist.lastSelOp || - (origin && hist.lastSelOrigin == origin && - (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || - selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) - { hist.done[hist.done.length - 1] = sel } - else - { pushSelectionToHistory(sel, hist.done) } - - hist.lastSelTime = +new Date - hist.lastSelOrigin = origin - hist.lastSelOp = opId - if (options && options.clearRedo !== false) - { clearSelectionEvents(hist.undone) } -} - -function pushSelectionToHistory(sel, dest) { - var top = lst(dest) - if (!(top && top.ranges && top.equals(sel))) - { dest.push(sel) } -} - -// Used to store marked span information in the history. -function attachLocalSpans(doc, change, from, to) { - var existing = change["spans_" + doc.id], n = 0 - doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { - if (line.markedSpans) - { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans } - ++n - }) -} - -// When un/re-doing restores text containing marked spans, those -// that have been explicitly cleared should not be restored. -function removeClearedSpans(spans) { - if (!spans) { return null } - var out - for (var i = 0; i < spans.length; ++i) { - if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i) } } - else if (out) { out.push(spans[i]) } - } - return !out ? spans : out.length ? out : null -} - -// Retrieve and filter the old marked spans stored in a change event. -function getOldSpans(doc, change) { - var found = change["spans_" + doc.id] - if (!found) { return null } - var nw = [] - for (var i = 0; i < change.text.length; ++i) - { nw.push(removeClearedSpans(found[i])) } - return nw -} - -// Used for un/re-doing changes from the history. Combines the -// result of computing the existing spans with the set of spans that -// existed in the history (so that deleting around a span and then -// undoing brings back the span). -function mergeOldSpans(doc, change) { - var old = getOldSpans(doc, change) - var stretched = stretchSpansOverChange(doc, change) - if (!old) { return stretched } - if (!stretched) { return old } - - for (var i = 0; i < old.length; ++i) { - var oldCur = old[i], stretchCur = stretched[i] - if (oldCur && stretchCur) { - spans: for (var j = 0; j < stretchCur.length; ++j) { - var span = stretchCur[j] - for (var k = 0; k < oldCur.length; ++k) - { if (oldCur[k].marker == span.marker) { continue spans } } - oldCur.push(span) - } - } else if (stretchCur) { - old[i] = stretchCur - } - } - return old -} - -// Used both to provide a JSON-safe object in .getHistory, and, when -// detaching a document, to split the history in two -function copyHistoryArray(events, newGroup, instantiateSel) { - var copy = [] - for (var i = 0; i < events.length; ++i) { - var event = events[i] - if (event.ranges) { - copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event) - continue - } - var changes = event.changes, newChanges = [] - copy.push({changes: newChanges}) - for (var j = 0; j < changes.length; ++j) { - var change = changes[j], m = (void 0) - newChanges.push({from: change.from, to: change.to, text: change.text}) - if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { - if (indexOf(newGroup, Number(m[1])) > -1) { - lst(newChanges)[prop] = change[prop] - delete change[prop] - } - } } } - } - } - return copy -} - -// The 'scroll' parameter given to many of these indicated whether -// the new cursor position should be scrolled into view after -// modifying the selection. - -// If shift is held or the extend flag is set, extends a range to -// include a given position (and optionally a second position). -// Otherwise, simply returns the range between the given positions. -// Used for cursor motion and such. -function extendRange(doc, range, head, other) { - if (doc.cm && doc.cm.display.shift || doc.extend) { - var anchor = range.anchor - if (other) { - var posBefore = cmp(head, anchor) < 0 - if (posBefore != (cmp(other, anchor) < 0)) { - anchor = head - head = other - } else if (posBefore != (cmp(head, other) < 0)) { - head = other - } - } - return new Range(anchor, head) - } else { - return new Range(other || head, head) - } -} - -// Extend the primary selection range, discard the rest. -function extendSelection(doc, head, other, options) { - setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options) -} - -// Extend all selections (pos is an array of selections with length -// equal the number of selections) -function extendSelections(doc, heads, options) { - var out = [] - for (var i = 0; i < doc.sel.ranges.length; i++) - { out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null) } - var newSel = normalizeSelection(out, doc.sel.primIndex) - setSelection(doc, newSel, options) -} - -// Updates a single range in the selection. -function replaceOneSelection(doc, i, range, options) { - var ranges = doc.sel.ranges.slice(0) - ranges[i] = range - setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options) -} - -// Reset the selection to a single range. -function setSimpleSelection(doc, anchor, head, options) { - setSelection(doc, simpleSelection(anchor, head), options) -} - -// Give beforeSelectionChange handlers a change to influence a -// selection update. -function filterSelectionChange(doc, sel, options) { - var obj = { - ranges: sel.ranges, - update: function(ranges) { - var this$1 = this; - - this.ranges = [] - for (var i = 0; i < ranges.length; i++) - { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), - clipPos(doc, ranges[i].head)) } - }, - origin: options && options.origin - } - signal(doc, "beforeSelectionChange", doc, obj) - if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj) } - if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) } - else { return sel } -} - -function setSelectionReplaceHistory(doc, sel, options) { - var done = doc.history.done, last = lst(done) - if (last && last.ranges) { - done[done.length - 1] = sel - setSelectionNoUndo(doc, sel, options) - } else { - setSelection(doc, sel, options) - } -} - -// Set a new selection. -function setSelection(doc, sel, options) { - setSelectionNoUndo(doc, sel, options) - addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options) -} - -function setSelectionNoUndo(doc, sel, options) { - if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - { sel = filterSelectionChange(doc, sel, options) } - - var bias = options && options.bias || - (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1) - setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)) - - if (!(options && options.scroll === false) && doc.cm) - { ensureCursorVisible(doc.cm) } -} - -function setSelectionInner(doc, sel) { - if (sel.equals(doc.sel)) { return } - - doc.sel = sel - - if (doc.cm) { - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true - signalCursorActivity(doc.cm) - } - signalLater(doc, "cursorActivity", doc) -} - -// Verify that the selection does not partially select any atomic -// marked ranges. -function reCheckSelection(doc) { - setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll) -} - -// Return a selection that does not partially select any atomic -// ranges. -function skipAtomicInSelection(doc, sel, bias, mayClear) { - var out - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i] - var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i] - var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear) - var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear) - if (out || newAnchor != range.anchor || newHead != range.head) { - if (!out) { out = sel.ranges.slice(0, i) } - out[i] = new Range(newAnchor, newHead) - } - } - return out ? normalizeSelection(out, sel.primIndex) : sel -} - -function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { - var line = getLine(doc, pos.line) - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var sp = line.markedSpans[i], m = sp.marker - if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { - if (mayClear) { - signal(m, "beforeCursorEnter") - if (m.explicitlyCleared) { - if (!line.markedSpans) { break } - else {--i; continue} - } - } - if (!m.atomic) { continue } - - if (oldPos) { - var near = m.find(dir < 0 ? 1 : -1), diff = (void 0) - if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) - { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) } - if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) - { return skipAtomicInner(doc, near, pos, dir, mayClear) } - } - - var far = m.find(dir < 0 ? -1 : 1) - if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) - { far = movePos(doc, far, dir, far.line == pos.line ? line : null) } - return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null - } - } } - return pos -} - -// Ensure a given position is not inside an atomic range. -function skipAtomic(doc, pos, oldPos, bias, mayClear) { - var dir = bias || 1 - var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || - (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || - skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || - (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)) - if (!found) { - doc.cantEdit = true - return Pos(doc.first, 0) - } - return found -} - -function movePos(doc, pos, dir, line) { - if (dir < 0 && pos.ch == 0) { - if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } - else { return null } - } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { - if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } - else { return null } - } else { - return new Pos(pos.line, pos.ch + dir) - } -} - -function selectAll(cm) { - cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll) -} - -// UPDATING - -// Allow "beforeChange" event handlers to influence a change -function filterChange(doc, change, update) { - var obj = { - canceled: false, - from: change.from, - to: change.to, - text: change.text, - origin: change.origin, - cancel: function () { return obj.canceled = true; } - } - if (update) { obj.update = function (from, to, text, origin) { - if (from) { obj.from = clipPos(doc, from) } - if (to) { obj.to = clipPos(doc, to) } - if (text) { obj.text = text } - if (origin !== undefined) { obj.origin = origin } - } } - signal(doc, "beforeChange", doc, obj) - if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj) } - - if (obj.canceled) { return null } - return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} -} - -// Apply a change to a document, and add it to the document's -// history, and propagating it to all linked documents. -function makeChange(doc, change, ignoreReadOnly) { - if (doc.cm) { - if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } - if (doc.cm.state.suppressEdits) { return } - } - - if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { - change = filterChange(doc, change, true) - if (!change) { return } - } - - // Possibly split or suppress the update based on the presence - // of read-only spans in its range. - var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to) - if (split) { - for (var i = split.length - 1; i >= 0; --i) - { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}) } - } else { - makeChangeInner(doc, change) - } -} - -function makeChangeInner(doc, change) { - if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } - var selAfter = computeSelAfterChange(doc, change) - addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN) - - makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)) - var rebased = [] - - linkedDocs(doc, function (doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change) - rebased.push(doc.history) - } - makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)) - }) -} - -// Revert a change stored in a document's history. -function makeChangeFromHistory(doc, type, allowSelectionOnly) { - if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return } - - var hist = doc.history, event, selAfter = doc.sel - var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done - - // Verify that there is a useable event (so that ctrl-z won't - // needlessly clear selection events) - var i = 0 - for (; i < source.length; i++) { - event = source[i] - if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) - { break } - } - if (i == source.length) { return } - hist.lastOrigin = hist.lastSelOrigin = null - - for (;;) { - event = source.pop() - if (event.ranges) { - pushSelectionToHistory(event, dest) - if (allowSelectionOnly && !event.equals(doc.sel)) { - setSelection(doc, event, {clearRedo: false}) - return - } - selAfter = event - } - else { break } - } - - // Build up a reverse change object to add to the opposite history - // stack (redo when undoing, and vice versa). - var antiChanges = [] - pushSelectionToHistory(selAfter, dest) - dest.push({changes: antiChanges, generation: hist.generation}) - hist.generation = event.generation || ++hist.maxGeneration - - var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange") - - var loop = function ( i ) { - var change = event.changes[i] - change.origin = type - if (filter && !filterChange(doc, change, false)) { - source.length = 0 - return {} - } - - antiChanges.push(historyChangeFromChange(doc, change)) - - var after = i ? computeSelAfterChange(doc, change) : lst(source) - makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)) - if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}) } - var rebased = [] - - // Propagate to the linked documents - linkedDocs(doc, function (doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change) - rebased.push(doc.history) - } - makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)) - }) - }; - - for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { - var returned = loop( i$1 ); - - if ( returned ) return returned.v; - } -} - -// Sub-views need their line numbers shifted when text is added -// above or below them in the parent document. -function shiftDoc(doc, distance) { - if (distance == 0) { return } - doc.first += distance - doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( - Pos(range.anchor.line + distance, range.anchor.ch), - Pos(range.head.line + distance, range.head.ch) - ); }), doc.sel.primIndex) - if (doc.cm) { - regChange(doc.cm, doc.first, doc.first - distance, distance) - for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) - { regLineChange(doc.cm, l, "gutter") } - } -} - -// More lower-level change function, handling only a single document -// (not linked ones). -function makeChangeSingleDoc(doc, change, selAfter, spans) { - if (doc.cm && !doc.cm.curOp) - { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } - - if (change.to.line < doc.first) { - shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)) - return - } - if (change.from.line > doc.lastLine()) { return } - - // Clip the change to the size of this doc - if (change.from.line < doc.first) { - var shift = change.text.length - 1 - (doc.first - change.from.line) - shiftDoc(doc, shift) - change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), - text: [lst(change.text)], origin: change.origin} - } - var last = doc.lastLine() - if (change.to.line > last) { - change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), - text: [change.text[0]], origin: change.origin} - } - - change.removed = getBetween(doc, change.from, change.to) - - if (!selAfter) { selAfter = computeSelAfterChange(doc, change) } - if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans) } - else { updateDoc(doc, change, spans) } - setSelectionNoUndo(doc, selAfter, sel_dontScroll) -} - -// Handle the interaction of a change to a document with the editor -// that this document is part of. -function makeChangeSingleDocInEditor(cm, change, spans) { - var doc = cm.doc, display = cm.display, from = change.from, to = change.to - - var recomputeMaxLength = false, checkWidthStart = from.line - if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(getLine(doc, from.line))) - doc.iter(checkWidthStart, to.line + 1, function (line) { - if (line == display.maxLine) { - recomputeMaxLength = true - return true - } - }) - } - - if (doc.sel.contains(change.from, change.to) > -1) - { signalCursorActivity(cm) } - - updateDoc(doc, change, spans, estimateHeight(cm)) - - if (!cm.options.lineWrapping) { - doc.iter(checkWidthStart, from.line + change.text.length, function (line) { - var len = lineLength(line) - if (len > display.maxLineLength) { - display.maxLine = line - display.maxLineLength = len - display.maxLineChanged = true - recomputeMaxLength = false - } - }) - if (recomputeMaxLength) { cm.curOp.updateMaxLine = true } - } - - // Adjust frontier, schedule worker - doc.frontier = Math.min(doc.frontier, from.line) - startWorker(cm, 400) - - var lendiff = change.text.length - (to.line - from.line) - 1 - // Remember that these lines changed, for updating the display - if (change.full) - { regChange(cm) } - else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) - { regLineChange(cm, from.line, "text") } - else - { regChange(cm, from.line, to.line + 1, lendiff) } - - var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change") - if (changeHandler || changesHandler) { - var obj = { - from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin - } - if (changeHandler) { signalLater(cm, "change", cm, obj) } - if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) } - } - cm.display.selForContextMenu = null -} - -function replaceRange(doc, code, from, to, origin) { - if (!to) { to = from } - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp } - if (typeof code == "string") { code = doc.splitLines(code) } - makeChange(doc, {from: from, to: to, text: code, origin: origin}) -} - -// Rebasing/resetting history to deal with externally-sourced changes - -function rebaseHistSelSingle(pos, from, to, diff) { - if (to < pos.line) { - pos.line += diff - } else if (from < pos.line) { - pos.line = from - pos.ch = 0 - } -} - -// Tries to rebase an array of history events given a change in the -// document. If the change touches the same lines as the event, the -// event, and everything 'behind' it, is discarded. If the change is -// before the event, the event's positions are updated. Uses a -// copy-on-write scheme for the positions, to avoid having to -// reallocate them all on every rebase, but also avoid problems with -// shared position objects being unsafely updated. -function rebaseHistArray(array, from, to, diff) { - for (var i = 0; i < array.length; ++i) { - var sub = array[i], ok = true - if (sub.ranges) { - if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true } - for (var j = 0; j < sub.ranges.length; j++) { - rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff) - rebaseHistSelSingle(sub.ranges[j].head, from, to, diff) - } - continue - } - for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { - var cur = sub.changes[j$1] - if (to < cur.from.line) { - cur.from = Pos(cur.from.line + diff, cur.from.ch) - cur.to = Pos(cur.to.line + diff, cur.to.ch) - } else if (from <= cur.to.line) { - ok = false - break - } - } - if (!ok) { - array.splice(0, i + 1) - i = 0 - } - } -} - -function rebaseHist(hist, change) { - var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1 - rebaseHistArray(hist.done, from, to, diff) - rebaseHistArray(hist.undone, from, to, diff) -} - -// Utility for applying a change to a line by handle or number, -// returning the number and optionally registering the line as -// changed. -function changeLine(doc, handle, changeType, op) { - var no = handle, line = handle - if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)) } - else { no = lineNo(handle) } - if (no == null) { return null } - if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType) } - return line -} - -// The document is represented as a BTree consisting of leaves, with -// chunk of lines in them, and branches, with up to ten leaves or -// other branch nodes below them. The top node is always a branch -// node, and is the document object itself (meaning it has -// additional methods and properties). -// -// All nodes have parent links. The tree is used both to go from -// line numbers to line objects, and to go from objects to numbers. -// It also indexes by height, and is used to convert between height -// and line object, and to find the total height of the document. -// -// See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html - -var LeafChunk = function(lines) { - var this$1 = this; - - this.lines = lines - this.parent = null - var height = 0 - for (var i = 0; i < lines.length; ++i) { - lines[i].parent = this$1 - height += lines[i].height - } - this.height = height -}; - -LeafChunk.prototype.chunkSize = function () { return this.lines.length }; - -// Remove the n lines at offset 'at'. -LeafChunk.prototype.removeInner = function (at, n) { - var this$1 = this; - - for (var i = at, e = at + n; i < e; ++i) { - var line = this$1.lines[i] - this$1.height -= line.height - cleanUpLine(line) - signalLater(line, "delete") - } - this.lines.splice(at, n) -}; - -// Helper used to collapse a small branch into a single leaf. -LeafChunk.prototype.collapse = function (lines) { - lines.push.apply(lines, this.lines) -}; - -// Insert the given array of lines at offset 'at', count them as -// having the given height. -LeafChunk.prototype.insertInner = function (at, lines, height) { - var this$1 = this; - - this.height += height - this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)) - for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1 } -}; - -// Used to iterate over a part of the tree. -LeafChunk.prototype.iterN = function (at, n, op) { - var this$1 = this; - - for (var e = at + n; at < e; ++at) - { if (op(this$1.lines[at])) { return true } } -}; - -var BranchChunk = function(children) { - var this$1 = this; - - this.children = children - var size = 0, height = 0 - for (var i = 0; i < children.length; ++i) { - var ch = children[i] - size += ch.chunkSize(); height += ch.height - ch.parent = this$1 - } - this.size = size - this.height = height - this.parent = null -}; - -BranchChunk.prototype.chunkSize = function () { return this.size }; - -BranchChunk.prototype.removeInner = function (at, n) { - var this$1 = this; - - this.size -= n - for (var i = 0; i < this.children.length; ++i) { - var child = this$1.children[i], sz = child.chunkSize() - if (at < sz) { - var rm = Math.min(n, sz - at), oldHeight = child.height - child.removeInner(at, rm) - this$1.height -= oldHeight - child.height - if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null } - if ((n -= rm) == 0) { break } - at = 0 - } else { at -= sz } - } - // If the result is smaller than 25 lines, ensure that it is a - // single leaf node. - if (this.size - n < 25 && - (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { - var lines = [] - this.collapse(lines) - this.children = [new LeafChunk(lines)] - this.children[0].parent = this - } -}; - -BranchChunk.prototype.collapse = function (lines) { - var this$1 = this; - - for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines) } -}; - -BranchChunk.prototype.insertInner = function (at, lines, height) { - var this$1 = this; - - this.size += lines.length - this.height += height - for (var i = 0; i < this.children.length; ++i) { - var child = this$1.children[i], sz = child.chunkSize() - if (at <= sz) { - child.insertInner(at, lines, height) - if (child.lines && child.lines.length > 50) { - // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. - // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. - var remaining = child.lines.length % 25 + 25 - for (var pos = remaining; pos < child.lines.length;) { - var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)) - child.height -= leaf.height - this$1.children.splice(++i, 0, leaf) - leaf.parent = this$1 - } - child.lines = child.lines.slice(0, remaining) - this$1.maybeSpill() - } - break - } - at -= sz - } -}; - -// When a node has grown, check whether it should be split. -BranchChunk.prototype.maybeSpill = function () { - if (this.children.length <= 10) { return } - var me = this - do { - var spilled = me.children.splice(me.children.length - 5, 5) - var sibling = new BranchChunk(spilled) - if (!me.parent) { // Become the parent node - var copy = new BranchChunk(me.children) - copy.parent = me - me.children = [copy, sibling] - me = copy - } else { - me.size -= sibling.size - me.height -= sibling.height - var myIndex = indexOf(me.parent.children, me) - me.parent.children.splice(myIndex + 1, 0, sibling) - } - sibling.parent = me.parent - } while (me.children.length > 10) - me.parent.maybeSpill() -}; - -BranchChunk.prototype.iterN = function (at, n, op) { - var this$1 = this; - - for (var i = 0; i < this.children.length; ++i) { - var child = this$1.children[i], sz = child.chunkSize() - if (at < sz) { - var used = Math.min(n, sz - at) - if (child.iterN(at, used, op)) { return true } - if ((n -= used) == 0) { break } - at = 0 - } else { at -= sz } - } -}; - -// Line widgets are block elements displayed above or below a line. - -var LineWidget = function(doc, node, options) { - var this$1 = this; - - if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) - { this$1[opt] = options[opt] } } } - this.doc = doc - this.node = node -}; - -LineWidget.prototype.clear = function () { - var this$1 = this; - - var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line) - if (no == null || !ws) { return } - for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1) } } - if (!ws.length) { line.widgets = null } - var height = widgetHeight(this) - updateLineHeight(line, Math.max(0, line.height - height)) - if (cm) { - runInOp(cm, function () { - adjustScrollWhenAboveVisible(cm, line, -height) - regLineChange(cm, no, "widget") - }) - signalLater(cm, "lineWidgetCleared", cm, this, no) - } -}; - -LineWidget.prototype.changed = function () { - var this$1 = this; - - var oldH = this.height, cm = this.doc.cm, line = this.line - this.height = null - var diff = widgetHeight(this) - oldH - if (!diff) { return } - updateLineHeight(line, line.height + diff) - if (cm) { - runInOp(cm, function () { - cm.curOp.forceUpdate = true - adjustScrollWhenAboveVisible(cm, line, diff) - signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)) - }) - } -}; -eventMixin(LineWidget) - -function adjustScrollWhenAboveVisible(cm, line, diff) { - if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) - { addToScrollPos(cm, null, diff) } -} - -function addLineWidget(doc, handle, node, options) { - var widget = new LineWidget(doc, node, options) - var cm = doc.cm - if (cm && widget.noHScroll) { cm.display.alignWidgets = true } - changeLine(doc, handle, "widget", function (line) { - var widgets = line.widgets || (line.widgets = []) - if (widget.insertAt == null) { widgets.push(widget) } - else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget) } - widget.line = line - if (cm && !lineIsHidden(doc, line)) { - var aboveVisible = heightAtLine(line) < doc.scrollTop - updateLineHeight(line, line.height + widgetHeight(widget)) - if (aboveVisible) { addToScrollPos(cm, null, widget.height) } - cm.curOp.forceUpdate = true - } - return true - }) - signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)) - return widget -} - -// TEXTMARKERS - -// Created with markText and setBookmark methods. A TextMarker is a -// handle that can be used to clear or find a marked position in the -// document. Line objects hold arrays (markedSpans) containing -// {from, to, marker} object pointing to such marker objects, and -// indicating that such a marker is present on that line. Multiple -// lines may point to the same marker when it spans across lines. -// The spans will have null for their from/to properties when the -// marker continues beyond the start/end of the line. Markers have -// links back to the lines they currently touch. - -// Collapsed markers have unique ids, in order to be able to order -// them, which is needed for uniquely determining an outer marker -// when they overlap (they may nest, but not partially overlap). -var nextMarkerId = 0 - -var TextMarker = function(doc, type) { - this.lines = [] - this.type = type - this.doc = doc - this.id = ++nextMarkerId -}; - -// Clear the marker. -TextMarker.prototype.clear = function () { - var this$1 = this; - - if (this.explicitlyCleared) { return } - var cm = this.doc.cm, withOp = cm && !cm.curOp - if (withOp) { startOperation(cm) } - if (hasHandler(this, "clear")) { - var found = this.find() - if (found) { signalLater(this, "clear", found.from, found.to) } - } - var min = null, max = null - for (var i = 0; i < this.lines.length; ++i) { - var line = this$1.lines[i] - var span = getMarkedSpanFor(line.markedSpans, this$1) - if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text") } - else if (cm) { - if (span.to != null) { max = lineNo(line) } - if (span.from != null) { min = lineNo(line) } - } - line.markedSpans = removeMarkedSpan(line.markedSpans, span) - if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm) - { updateLineHeight(line, textHeight(cm.display)) } - } - if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { - var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual) - if (len > cm.display.maxLineLength) { - cm.display.maxLine = visual - cm.display.maxLineLength = len - cm.display.maxLineChanged = true - } - } } - - if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1) } - this.lines.length = 0 - this.explicitlyCleared = true - if (this.atomic && this.doc.cantEdit) { - this.doc.cantEdit = false - if (cm) { reCheckSelection(cm.doc) } - } - if (cm) { signalLater(cm, "markerCleared", cm, this, min, max) } - if (withOp) { endOperation(cm) } - if (this.parent) { this.parent.clear() } -}; - -// Find the position of the marker in the document. Returns a {from, -// to} object by default. Side can be passed to get a specific side -// -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the -// Pos objects returned contain a line object, rather than a line -// number (used to prevent looking up the same line twice). -TextMarker.prototype.find = function (side, lineObj) { - var this$1 = this; - - if (side == null && this.type == "bookmark") { side = 1 } - var from, to - for (var i = 0; i < this.lines.length; ++i) { - var line = this$1.lines[i] - var span = getMarkedSpanFor(line.markedSpans, this$1) - if (span.from != null) { - from = Pos(lineObj ? line : lineNo(line), span.from) - if (side == -1) { return from } - } - if (span.to != null) { - to = Pos(lineObj ? line : lineNo(line), span.to) - if (side == 1) { return to } - } - } - return from && {from: from, to: to} -}; - -// Signals that the marker's widget changed, and surrounding layout -// should be recomputed. -TextMarker.prototype.changed = function () { - var this$1 = this; - - var pos = this.find(-1, true), widget = this, cm = this.doc.cm - if (!pos || !cm) { return } - runInOp(cm, function () { - var line = pos.line, lineN = lineNo(pos.line) - var view = findViewForLine(cm, lineN) - if (view) { - clearLineMeasurementCacheFor(view) - cm.curOp.selectionChanged = cm.curOp.forceUpdate = true - } - cm.curOp.updateMaxLine = true - if (!lineIsHidden(widget.doc, line) && widget.height != null) { - var oldHeight = widget.height - widget.height = null - var dHeight = widgetHeight(widget) - oldHeight - if (dHeight) - { updateLineHeight(line, line.height + dHeight) } - } - signalLater(cm, "markerChanged", cm, this$1) - }) -}; - -TextMarker.prototype.attachLine = function (line) { - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp - if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) - { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this) } - } - this.lines.push(line) -}; - -TextMarker.prototype.detachLine = function (line) { - this.lines.splice(indexOf(this.lines, line), 1) - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp - ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this) - } -}; -eventMixin(TextMarker) - -// Create a marker, wire it up to the right lines, and -function markText(doc, from, to, options, type) { - // Shared markers (across linked documents) are handled separately - // (markTextShared will call out to this again, once per - // document). - if (options && options.shared) { return markTextShared(doc, from, to, options, type) } - // Ensure we are in an operation. - if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } - - var marker = new TextMarker(doc, type), diff = cmp(from, to) - if (options) { copyObj(options, marker, false) } - // Don't connect empty markers unless clearWhenEmpty is false - if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) - { return marker } - if (marker.replacedWith) { - // Showing up as a widget implies collapsed (widget replaces text) - marker.collapsed = true - marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget") - if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true") } - if (options.insertLeft) { marker.widgetNode.insertLeft = true } - } - if (marker.collapsed) { - if (conflictingCollapsedRange(doc, from.line, from, to, marker) || - from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) - { throw new Error("Inserting collapsed marker partially overlapping an existing one") } - seeCollapsedSpans() - } - - if (marker.addToHistory) - { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) } - - var curLine = from.line, cm = doc.cm, updateMaxLine - doc.iter(curLine, to.line + 1, function (line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) - { updateMaxLine = true } - if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0) } - addMarkedSpan(line, new MarkedSpan(marker, - curLine == from.line ? from.ch : null, - curLine == to.line ? to.ch : null)) - ++curLine - }) - // lineIsHidden depends on the presence of the spans, so needs a second pass - if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { - if (lineIsHidden(doc, line)) { updateLineHeight(line, 0) } - }) } - - if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }) } - - if (marker.readOnly) { - seeReadOnlySpans() - if (doc.history.done.length || doc.history.undone.length) - { doc.clearHistory() } - } - if (marker.collapsed) { - marker.id = ++nextMarkerId - marker.atomic = true - } - if (cm) { - // Sync editor state - if (updateMaxLine) { cm.curOp.updateMaxLine = true } - if (marker.collapsed) - { regChange(cm, from.line, to.line + 1) } - else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) - { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text") } } - if (marker.atomic) { reCheckSelection(cm.doc) } - signalLater(cm, "markerAdded", cm, marker) - } - return marker -} - -// SHARED TEXTMARKERS - -// A shared marker spans multiple linked documents. It is -// implemented as a meta-marker-object controlling multiple normal -// markers. -var SharedTextMarker = function(markers, primary) { - var this$1 = this; - - this.markers = markers - this.primary = primary - for (var i = 0; i < markers.length; ++i) - { markers[i].parent = this$1 } -}; - -SharedTextMarker.prototype.clear = function () { - var this$1 = this; - - if (this.explicitlyCleared) { return } - this.explicitlyCleared = true - for (var i = 0; i < this.markers.length; ++i) - { this$1.markers[i].clear() } - signalLater(this, "clear") -}; - -SharedTextMarker.prototype.find = function (side, lineObj) { - return this.primary.find(side, lineObj) -}; -eventMixin(SharedTextMarker) - -function markTextShared(doc, from, to, options, type) { - options = copyObj(options) - options.shared = false - var markers = [markText(doc, from, to, options, type)], primary = markers[0] - var widget = options.widgetNode - linkedDocs(doc, function (doc) { - if (widget) { options.widgetNode = widget.cloneNode(true) } - markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)) - for (var i = 0; i < doc.linked.length; ++i) - { if (doc.linked[i].isParent) { return } } - primary = lst(markers) - }) - return new SharedTextMarker(markers, primary) -} - -function findSharedMarkers(doc) { - return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) -} - -function copySharedMarkers(doc, markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], pos = marker.find() - var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to) - if (cmp(mFrom, mTo)) { - var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type) - marker.markers.push(subMark) - subMark.parent = marker - } - } -} - -function detachSharedMarkers(markers) { - var loop = function ( i ) { - var marker = markers[i], linked = [marker.primary.doc] - linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }) - for (var j = 0; j < marker.markers.length; j++) { - var subMarker = marker.markers[j] - if (indexOf(linked, subMarker.doc) == -1) { - subMarker.parent = null - marker.markers.splice(j--, 1) - } - } - }; - - for (var i = 0; i < markers.length; i++) loop( i ); -} - -var nextDocId = 0 -var Doc = function(text, mode, firstLine, lineSep, direction) { - if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } - if (firstLine == null) { firstLine = 0 } - - BranchChunk.call(this, [new LeafChunk([new Line("", null)])]) - this.first = firstLine - this.scrollTop = this.scrollLeft = 0 - this.cantEdit = false - this.cleanGeneration = 1 - this.frontier = firstLine - var start = Pos(firstLine, 0) - this.sel = simpleSelection(start) - this.history = new History(null) - this.id = ++nextDocId - this.modeOption = mode - this.lineSep = lineSep - this.direction = (direction == "rtl") ? "rtl" : "ltr" - this.extend = false - - if (typeof text == "string") { text = this.splitLines(text) } - updateDoc(this, {from: start, to: start, text: text}) - setSelection(this, simpleSelection(start), sel_dontScroll) -} - -Doc.prototype = createObj(BranchChunk.prototype, { - constructor: Doc, - // Iterate over the document. Supports two forms -- with only one - // argument, it calls that for each line in the document. With - // three, it iterates over the range given by the first two (with - // the second being non-inclusive). - iter: function(from, to, op) { - if (op) { this.iterN(from - this.first, to - from, op) } - else { this.iterN(this.first, this.first + this.size, from) } - }, - - // Non-public interface for adding and removing lines. - insert: function(at, lines) { - var height = 0 - for (var i = 0; i < lines.length; ++i) { height += lines[i].height } - this.insertInner(at - this.first, lines, height) - }, - remove: function(at, n) { this.removeInner(at - this.first, n) }, - - // From here, the methods are part of the public interface. Most - // are also available from CodeMirror (editor) instances. - - getValue: function(lineSep) { - var lines = getLines(this, this.first, this.first + this.size) - if (lineSep === false) { return lines } - return lines.join(lineSep || this.lineSeparator()) - }, - setValue: docMethodOp(function(code) { - var top = Pos(this.first, 0), last = this.first + this.size - 1 - makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), - text: this.splitLines(code), origin: "setValue", full: true}, true) - setSelection(this, simpleSelection(top)) - }), - replaceRange: function(code, from, to, origin) { - from = clipPos(this, from) - to = to ? clipPos(this, to) : from - replaceRange(this, code, from, to, origin) - }, - getRange: function(from, to, lineSep) { - var lines = getBetween(this, clipPos(this, from), clipPos(this, to)) - if (lineSep === false) { return lines } - return lines.join(lineSep || this.lineSeparator()) - }, - - getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, - - getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, - getLineNumber: function(line) {return lineNo(line)}, - - getLineHandleVisualStart: function(line) { - if (typeof line == "number") { line = getLine(this, line) } - return visualLine(line) - }, - - lineCount: function() {return this.size}, - firstLine: function() {return this.first}, - lastLine: function() {return this.first + this.size - 1}, - - clipPos: function(pos) {return clipPos(this, pos)}, - - getCursor: function(start) { - var range = this.sel.primary(), pos - if (start == null || start == "head") { pos = range.head } - else if (start == "anchor") { pos = range.anchor } - else if (start == "end" || start == "to" || start === false) { pos = range.to() } - else { pos = range.from() } - return pos - }, - listSelections: function() { return this.sel.ranges }, - somethingSelected: function() {return this.sel.somethingSelected()}, - - setCursor: docMethodOp(function(line, ch, options) { - setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options) - }), - setSelection: docMethodOp(function(anchor, head, options) { - setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options) - }), - extendSelection: docMethodOp(function(head, other, options) { - extendSelection(this, clipPos(this, head), other && clipPos(this, other), options) - }), - extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads), options) - }), - extendSelectionsBy: docMethodOp(function(f, options) { - var heads = map(this.sel.ranges, f) - extendSelections(this, clipPosArray(this, heads), options) - }), - setSelections: docMethodOp(function(ranges, primary, options) { - var this$1 = this; - - if (!ranges.length) { return } - var out = [] - for (var i = 0; i < ranges.length; i++) - { out[i] = new Range(clipPos(this$1, ranges[i].anchor), - clipPos(this$1, ranges[i].head)) } - if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex) } - setSelection(this, normalizeSelection(out, primary), options) - }), - addSelection: docMethodOp(function(anchor, head, options) { - var ranges = this.sel.ranges.slice(0) - ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))) - setSelection(this, normalizeSelection(ranges, ranges.length - 1), options) - }), - - getSelection: function(lineSep) { - var this$1 = this; - - var ranges = this.sel.ranges, lines - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()) - lines = lines ? lines.concat(sel) : sel - } - if (lineSep === false) { return lines } - else { return lines.join(lineSep || this.lineSeparator()) } - }, - getSelections: function(lineSep) { - var this$1 = this; - - var parts = [], ranges = this.sel.ranges - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()) - if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()) } - parts[i] = sel - } - return parts - }, - replaceSelection: function(code, collapse, origin) { - var dup = [] - for (var i = 0; i < this.sel.ranges.length; i++) - { dup[i] = code } - this.replaceSelections(dup, collapse, origin || "+input") - }, - replaceSelections: docMethodOp(function(code, collapse, origin) { - var this$1 = this; - - var changes = [], sel = this.sel - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i] - changes[i] = {from: range.from(), to: range.to(), text: this$1.splitLines(code[i]), origin: origin} - } - var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse) - for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) - { makeChange(this$1, changes[i$1]) } - if (newSel) { setSelectionReplaceHistory(this, newSel) } - else if (this.cm) { ensureCursorVisible(this.cm) } - }), - undo: docMethodOp(function() {makeChangeFromHistory(this, "undo")}), - redo: docMethodOp(function() {makeChangeFromHistory(this, "redo")}), - undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true)}), - redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true)}), - - setExtending: function(val) {this.extend = val}, - getExtending: function() {return this.extend}, - - historySize: function() { - var hist = this.history, done = 0, undone = 0 - for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done } } - for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone } } - return {undo: done, redo: undone} - }, - clearHistory: function() {this.history = new History(this.history.maxGeneration)}, - - markClean: function() { - this.cleanGeneration = this.changeGeneration(true) - }, - changeGeneration: function(forceSplit) { - if (forceSplit) - { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null } - return this.history.generation - }, - isClean: function (gen) { - return this.history.generation == (gen || this.cleanGeneration) - }, - - getHistory: function() { - return {done: copyHistoryArray(this.history.done), - undone: copyHistoryArray(this.history.undone)} - }, - setHistory: function(histData) { - var hist = this.history = new History(this.history.maxGeneration) - hist.done = copyHistoryArray(histData.done.slice(0), null, true) - hist.undone = copyHistoryArray(histData.undone.slice(0), null, true) - }, - - setGutterMarker: docMethodOp(function(line, gutterID, value) { - return changeLine(this, line, "gutter", function (line) { - var markers = line.gutterMarkers || (line.gutterMarkers = {}) - markers[gutterID] = value - if (!value && isEmpty(markers)) { line.gutterMarkers = null } - return true - }) - }), - - clearGutter: docMethodOp(function(gutterID) { - var this$1 = this; - - this.iter(function (line) { - if (line.gutterMarkers && line.gutterMarkers[gutterID]) { - changeLine(this$1, line, "gutter", function () { - line.gutterMarkers[gutterID] = null - if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null } - return true - }) - } - }) - }), - - lineInfo: function(line) { - var n - if (typeof line == "number") { - if (!isLine(this, line)) { return null } - n = line - line = getLine(this, line) - if (!line) { return null } - } else { - n = lineNo(line) - if (n == null) { return null } - } - return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, - textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, - widgets: line.widgets} - }, - - addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass" - if (!line[prop]) { line[prop] = cls } - else if (classTest(cls).test(line[prop])) { return false } - else { line[prop] += " " + cls } - return true - }) - }), - removeLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass" - var cur = line[prop] - if (!cur) { return false } - else if (cls == null) { line[prop] = null } - else { - var found = cur.match(classTest(cls)) - if (!found) { return false } - var end = found.index + found[0].length - line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null - } - return true - }) - }), - - addLineWidget: docMethodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options) - }), - removeLineWidget: function(widget) { widget.clear() }, - - markText: function(from, to, options) { - return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") - }, - setBookmark: function(pos, options) { - var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft, - clearWhenEmpty: false, shared: options && options.shared, - handleMouseEvents: options && options.handleMouseEvents} - pos = clipPos(this, pos) - return markText(this, pos, pos, realOpts, "bookmark") - }, - findMarksAt: function(pos) { - pos = clipPos(this, pos) - var markers = [], spans = getLine(this, pos.line).markedSpans - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i] - if ((span.from == null || span.from <= pos.ch) && - (span.to == null || span.to >= pos.ch)) - { markers.push(span.marker.parent || span.marker) } - } } - return markers - }, - findMarks: function(from, to, filter) { - from = clipPos(this, from); to = clipPos(this, to) - var found = [], lineNo = from.line - this.iter(from.line, to.line + 1, function (line) { - var spans = line.markedSpans - if (spans) { for (var i = 0; i < spans.length; i++) { - var span = spans[i] - if (!(span.to != null && lineNo == from.line && from.ch >= span.to || - span.from == null && lineNo != from.line || - span.from != null && lineNo == to.line && span.from >= to.ch) && - (!filter || filter(span.marker))) - { found.push(span.marker.parent || span.marker) } - } } - ++lineNo - }) - return found - }, - getAllMarks: function() { - var markers = [] - this.iter(function (line) { - var sps = line.markedSpans - if (sps) { for (var i = 0; i < sps.length; ++i) - { if (sps[i].from != null) { markers.push(sps[i].marker) } } } - }) - return markers - }, - - posFromIndex: function(off) { - var ch, lineNo = this.first, sepSize = this.lineSeparator().length - this.iter(function (line) { - var sz = line.text.length + sepSize - if (sz > off) { ch = off; return true } - off -= sz - ++lineNo - }) - return clipPos(this, Pos(lineNo, ch)) - }, - indexFromPos: function (coords) { - coords = clipPos(this, coords) - var index = coords.ch - if (coords.line < this.first || coords.ch < 0) { return 0 } - var sepSize = this.lineSeparator().length - this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value - index += line.text.length + sepSize - }) - return index - }, - - copy: function(copyHistory) { - var doc = new Doc(getLines(this, this.first, this.first + this.size), - this.modeOption, this.first, this.lineSep, this.direction) - doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft - doc.sel = this.sel - doc.extend = false - if (copyHistory) { - doc.history.undoDepth = this.history.undoDepth - doc.setHistory(this.getHistory()) - } - return doc - }, - - linkedDoc: function(options) { - if (!options) { options = {} } - var from = this.first, to = this.first + this.size - if (options.from != null && options.from > from) { from = options.from } - if (options.to != null && options.to < to) { to = options.to } - var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction) - if (options.sharedHist) { copy.history = this.history - ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}) - copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}] - copySharedMarkers(copy, findSharedMarkers(this)) - return copy - }, - unlinkDoc: function(other) { - var this$1 = this; - - if (other instanceof CodeMirror) { other = other.doc } - if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { - var link = this$1.linked[i] - if (link.doc != other) { continue } - this$1.linked.splice(i, 1) - other.unlinkDoc(this$1) - detachSharedMarkers(findSharedMarkers(this$1)) - break - } } - // If the histories were shared, split them again - if (other.history == this.history) { - var splitIds = [other.id] - linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true) - other.history = new History(null) - other.history.done = copyHistoryArray(this.history.done, splitIds) - other.history.undone = copyHistoryArray(this.history.undone, splitIds) - } - }, - iterLinkedDocs: function(f) {linkedDocs(this, f)}, - - getMode: function() {return this.mode}, - getEditor: function() {return this.cm}, - - splitLines: function(str) { - if (this.lineSep) { return str.split(this.lineSep) } - return splitLinesAuto(str) - }, - lineSeparator: function() { return this.lineSep || "\n" }, - - setDirection: docMethodOp(function (dir) { - if (dir != "rtl") { dir = "ltr" } - if (dir == this.direction) { return } - this.direction = dir - this.iter(function (line) { return line.order = null; }) - if (this.cm) { directionChanged(this.cm) } - }) -}) - -// Public alias. -Doc.prototype.eachLine = Doc.prototype.iter - -// Kludge to work around strange IE behavior where it'll sometimes -// re-fire a series of drag-related events right after the drop (#1551) -var lastDrop = 0 - -function onDrop(e) { - var cm = this - clearDragCursor(cm) - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) - { return } - e_preventDefault(e) - if (ie) { lastDrop = +new Date } - var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files - if (!pos || cm.isReadOnly()) { return } - // Might be a file drop, in which case we simply extract the text - // and insert it. - if (files && files.length && window.FileReader && window.File) { - var n = files.length, text = Array(n), read = 0 - var loadFile = function (file, i) { - if (cm.options.allowDropFileTypes && - indexOf(cm.options.allowDropFileTypes, file.type) == -1) - { return } - - var reader = new FileReader - reader.onload = operation(cm, function () { - var content = reader.result - if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = "" } - text[i] = content - if (++read == n) { - pos = clipPos(cm.doc, pos) - var change = {from: pos, to: pos, - text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), - origin: "paste"} - makeChange(cm.doc, change) - setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))) - } - }) - reader.readAsText(file) - } - for (var i = 0; i < n; ++i) { loadFile(files[i], i) } - } else { // Normal drop - // Don't do a replace if the drop happened inside of the selected text. - if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { - cm.state.draggingText(e) - // Ensure the editor is re-focused - setTimeout(function () { return cm.display.input.focus(); }, 20) - return - } - try { - var text$1 = e.dataTransfer.getData("Text") - if (text$1) { - var selected - if (cm.state.draggingText && !cm.state.draggingText.copy) - { selected = cm.listSelections() } - setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)) - if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) - { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag") } } - cm.replaceSelection(text$1, "around", "paste") - cm.display.input.focus() - } - } - catch(e){} - } -} - -function onDragStart(cm, e) { - if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } - - e.dataTransfer.setData("Text", cm.getSelection()) - e.dataTransfer.effectAllowed = "copyMove" - - // Use dummy image instead of default browsers image. - // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. - if (e.dataTransfer.setDragImage && !safari) { - var img = elt("img", null, null, "position: fixed; left: 0; top: 0;") - img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" - if (presto) { - img.width = img.height = 1 - cm.display.wrapper.appendChild(img) - // Force a relayout, or Opera won't use our image for some obscure reason - img._top = img.offsetTop - } - e.dataTransfer.setDragImage(img, 0, 0) - if (presto) { img.parentNode.removeChild(img) } - } -} - -function onDragOver(cm, e) { - var pos = posFromMouse(cm, e) - if (!pos) { return } - var frag = document.createDocumentFragment() - drawSelectionCursor(cm, pos, frag) - if (!cm.display.dragCursor) { - cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors") - cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv) - } - removeChildrenAndAdd(cm.display.dragCursor, frag) -} - -function clearDragCursor(cm) { - if (cm.display.dragCursor) { - cm.display.lineSpace.removeChild(cm.display.dragCursor) - cm.display.dragCursor = null - } -} - -// These must be handled carefully, because naively registering a -// handler for each editor will cause the editors to never be -// garbage collected. - -function forEachCodeMirror(f) { - if (!document.body.getElementsByClassName) { return } - var byClass = document.body.getElementsByClassName("CodeMirror") - for (var i = 0; i < byClass.length; i++) { - var cm = byClass[i].CodeMirror - if (cm) { f(cm) } - } -} - -var globalsRegistered = false -function ensureGlobalHandlers() { - if (globalsRegistered) { return } - registerGlobalHandlers() - globalsRegistered = true -} -function registerGlobalHandlers() { - // When the window resizes, we need to refresh active editors. - var resizeTimer - on(window, "resize", function () { - if (resizeTimer == null) { resizeTimer = setTimeout(function () { - resizeTimer = null - forEachCodeMirror(onResize) - }, 100) } - }) - // When the window loses focus, we want to show the editor as blurred - on(window, "blur", function () { return forEachCodeMirror(onBlur); }) -} -// Called when the window resizes -function onResize(cm) { - var d = cm.display - if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) - { return } - // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null - d.scrollbarsClipped = false - cm.setSize() -} - -var keyNames = { - 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", - 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", - 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", - 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", - 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", - 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" -} - -// Number keys -for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i) } -// Alphabetic keys -for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1) } -// Function keys -for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2 } - -var keyMap = {} - -keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", - "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", - "Esc": "singleSelection" -} -// Note that the save and find-related commands aren't defined by -// default. User code or addons can define them. Unknown commands -// are simply ignored. -keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", - "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", - "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", - "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", - fallthrough: "basic" -} -// Very basic readline/emacs-style bindings, which are standard on Mac. -keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", - "Ctrl-O": "openLine" -} -keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", - "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", - "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", - fallthrough: ["basic", "emacsy"] -} -keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault - -// KEYMAP DISPATCH - -function normalizeKeyName(name) { - var parts = name.split(/-(?!$)/) - name = parts[parts.length - 1] - var alt, ctrl, shift, cmd - for (var i = 0; i < parts.length - 1; i++) { - var mod = parts[i] - if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true } - else if (/^a(lt)?$/i.test(mod)) { alt = true } - else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true } - else if (/^s(hift)?$/i.test(mod)) { shift = true } - else { throw new Error("Unrecognized modifier name: " + mod) } - } - if (alt) { name = "Alt-" + name } - if (ctrl) { name = "Ctrl-" + name } - if (cmd) { name = "Cmd-" + name } - if (shift) { name = "Shift-" + name } - return name -} - -// This is a kludge to keep keymaps mostly working as raw objects -// (backwards compatibility) while at the same time support features -// like normalization and multi-stroke key bindings. It compiles a -// new normalized keymap, and then updates the old object to reflect -// this. -function normalizeKeyMap(keymap) { - var copy = {} - for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { - var value = keymap[keyname] - if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } - if (value == "...") { delete keymap[keyname]; continue } - - var keys = map(keyname.split(" "), normalizeKeyName) - for (var i = 0; i < keys.length; i++) { - var val = (void 0), name = (void 0) - if (i == keys.length - 1) { - name = keys.join(" ") - val = value - } else { - name = keys.slice(0, i + 1).join(" ") - val = "..." - } - var prev = copy[name] - if (!prev) { copy[name] = val } - else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } - } - delete keymap[keyname] - } } - for (var prop in copy) { keymap[prop] = copy[prop] } - return keymap -} - -function lookupKey(key, map, handle, context) { - map = getKeyMap(map) - var found = map.call ? map.call(key, context) : map[key] - if (found === false) { return "nothing" } - if (found === "...") { return "multi" } - if (found != null && handle(found)) { return "handled" } - - if (map.fallthrough) { - if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") - { return lookupKey(key, map.fallthrough, handle, context) } - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle, context) - if (result) { return result } - } - } -} - -// Modifier key presses don't count as 'real' key presses for the -// purpose of keymap fallthrough. -function isModifierKey(value) { - var name = typeof value == "string" ? value : keyNames[value.keyCode] - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" -} - -// Look up the name of a key as indicated by an event object. -function keyName(event, noShift) { - if (presto && event.keyCode == 34 && event["char"]) { return false } - var base = keyNames[event.keyCode], name = base - if (name == null || event.altGraphKey) { return false } - if (event.altKey && base != "Alt") { name = "Alt-" + name } - if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name } - if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name } - if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name } - return name -} - -function getKeyMap(val) { - return typeof val == "string" ? keyMap[val] : val -} - -// Helper for deleting text near the selection(s), used to implement -// backspace, delete, and similar functionality. -function deleteNearSelection(cm, compute) { - var ranges = cm.doc.sel.ranges, kill = [] - // Build up a set of ranges to kill first, merging overlapping - // ranges. - for (var i = 0; i < ranges.length; i++) { - var toKill = compute(ranges[i]) - while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { - var replaced = kill.pop() - if (cmp(replaced.from, toKill.from) < 0) { - toKill.from = replaced.from - break - } - } - kill.push(toKill) - } - // Next, remove those actual ranges. - runInOp(cm, function () { - for (var i = kill.length - 1; i >= 0; i--) - { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") } - ensureCursorVisible(cm) - }) -} - -// Commands are parameter-less actions that can be performed on an -// editor, mostly used for keybindings. -var commands = { - selectAll: selectAll, - singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, - killLine: function (cm) { return deleteNearSelection(cm, function (range) { - if (range.empty()) { - var len = getLine(cm.doc, range.head.line).text.length - if (range.head.ch == len && range.head.line < cm.lastLine()) - { return {from: range.head, to: Pos(range.head.line + 1, 0)} } - else - { return {from: range.head, to: Pos(range.head.line, len)} } - } else { - return {from: range.from(), to: range.to()} - } - }); }, - deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ - from: Pos(range.from().line, 0), - to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) - }); }); }, - delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ - from: Pos(range.from().line, 0), to: range.from() - }); }); }, - delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - var leftPos = cm.coordsChar({left: 0, top: top}, "div") - return {from: leftPos, to: range.from()} - }); }, - delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") - return {from: range.from(), to: rightPos } - }); }, - undo: function (cm) { return cm.undo(); }, - redo: function (cm) { return cm.redo(); }, - undoSelection: function (cm) { return cm.undoSelection(); }, - redoSelection: function (cm) { return cm.redoSelection(); }, - goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, - goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, - goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, - {origin: "+move", bias: 1} - ); }, - goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, - {origin: "+move", bias: 1} - ); }, - goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, - {origin: "+move", bias: -1} - ); }, - goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") - }, sel_move); }, - goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - return cm.coordsChar({left: 0, top: top}, "div") - }, sel_move); }, - goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - var pos = cm.coordsChar({left: 0, top: top}, "div") - if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } - return pos - }, sel_move); }, - goLineUp: function (cm) { return cm.moveV(-1, "line"); }, - goLineDown: function (cm) { return cm.moveV(1, "line"); }, - goPageUp: function (cm) { return cm.moveV(-1, "page"); }, - goPageDown: function (cm) { return cm.moveV(1, "page"); }, - goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, - goCharRight: function (cm) { return cm.moveH(1, "char"); }, - goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, - goColumnRight: function (cm) { return cm.moveH(1, "column"); }, - goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, - goGroupRight: function (cm) { return cm.moveH(1, "group"); }, - goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, - goWordRight: function (cm) { return cm.moveH(1, "word"); }, - delCharBefore: function (cm) { return cm.deleteH(-1, "char"); }, - delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, - delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, - delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, - delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, - delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, - indentAuto: function (cm) { return cm.indentSelection("smart"); }, - indentMore: function (cm) { return cm.indentSelection("add"); }, - indentLess: function (cm) { return cm.indentSelection("subtract"); }, - insertTab: function (cm) { return cm.replaceSelection("\t"); }, - insertSoftTab: function (cm) { - var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].from() - var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize) - spaces.push(spaceStr(tabSize - col % tabSize)) - } - cm.replaceSelections(spaces) - }, - defaultTab: function (cm) { - if (cm.somethingSelected()) { cm.indentSelection("add") } - else { cm.execCommand("insertTab") } - }, - // Swap the two chars left and right of each selection's head. - // Move cursor behind the two swapped characters afterwards. - // - // Doesn't consider line feeds a character. - // Doesn't scan more than one line above to find a character. - // Doesn't do anything on an empty line. - // Doesn't do anything with non-empty selections. - transposeChars: function (cm) { return runInOp(cm, function () { - var ranges = cm.listSelections(), newSel = [] - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) { continue } - var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text - if (line) { - if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1) } - if (cur.ch > 0) { - cur = new Pos(cur.line, cur.ch + 1) - cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), - Pos(cur.line, cur.ch - 2), cur, "+transpose") - } else if (cur.line > cm.doc.first) { - var prev = getLine(cm.doc, cur.line - 1).text - if (prev) { - cur = new Pos(cur.line, 1) - cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + - prev.charAt(prev.length - 1), - Pos(cur.line - 1, prev.length - 1), cur, "+transpose") - } - } - } - newSel.push(new Range(cur, cur)) - } - cm.setSelections(newSel) - }); }, - newlineAndIndent: function (cm) { return runInOp(cm, function () { - var sels = cm.listSelections() - for (var i = sels.length - 1; i >= 0; i--) - { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") } - sels = cm.listSelections() - for (var i$1 = 0; i$1 < sels.length; i$1++) - { cm.indentLine(sels[i$1].from().line, null, true) } - ensureCursorVisible(cm) - }); }, - openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, - toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } -} - - -function lineStart(cm, lineN) { - var line = getLine(cm.doc, lineN) - var visual = visualLine(line) - if (visual != line) { lineN = lineNo(visual) } - return endOfLine(true, cm, visual, lineN, 1) -} -function lineEnd(cm, lineN) { - var line = getLine(cm.doc, lineN) - var visual = visualLineEnd(line) - if (visual != line) { lineN = lineNo(visual) } - return endOfLine(true, cm, line, lineN, -1) -} -function lineStartSmart(cm, pos) { - var start = lineStart(cm, pos.line) - var line = getLine(cm.doc, start.line) - var order = getOrder(line, cm.doc.direction) - if (!order || order[0].level == 0) { - var firstNonWS = Math.max(0, line.text.search(/\S/)) - var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch - return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) - } - return start -} - -// Run a handler that was bound to a key. -function doHandleBinding(cm, bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound] - if (!bound) { return false } - } - // Ensure previous input has been read, so that the handler sees a - // consistent view of the document - cm.display.input.ensurePolled() - var prevShift = cm.display.shift, done = false - try { - if (cm.isReadOnly()) { cm.state.suppressEdits = true } - if (dropShift) { cm.display.shift = false } - done = bound(cm) != Pass - } finally { - cm.display.shift = prevShift - cm.state.suppressEdits = false - } - return done -} - -function lookupKeyForEditor(cm, name, handle) { - for (var i = 0; i < cm.state.keyMaps.length; i++) { - var result = lookupKey(name, cm.state.keyMaps[i], handle, cm) - if (result) { return result } - } - return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) - || lookupKey(name, cm.options.keyMap, handle, cm) -} - -var stopSeq = new Delayed -function dispatchKey(cm, name, e, handle) { - var seq = cm.state.keySeq - if (seq) { - if (isModifierKey(name)) { return "handled" } - stopSeq.set(50, function () { - if (cm.state.keySeq == seq) { - cm.state.keySeq = null - cm.display.input.reset() - } - }) - name = seq + " " + name - } - var result = lookupKeyForEditor(cm, name, handle) - - if (result == "multi") - { cm.state.keySeq = name } - if (result == "handled") - { signalLater(cm, "keyHandled", cm, name, e) } - - if (result == "handled" || result == "multi") { - e_preventDefault(e) - restartBlink(cm) - } - - if (seq && !result && /\'$/.test(name)) { - e_preventDefault(e) - return true - } - return !!result -} - -// Handle a key from the keydown event. -function handleKeyBinding(cm, e) { - var name = keyName(e, true) - if (!name) { return false } - - if (e.shiftKey && !cm.state.keySeq) { - // First try to resolve full name (including 'Shift-'). Failing - // that, see if there is a cursor-motion command (starting with - // 'go') bound to the keyname without 'Shift-'. - return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) - || dispatchKey(cm, name, e, function (b) { - if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) - { return doHandleBinding(cm, b) } - }) - } else { - return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) - } -} - -// Handle a key from the keypress event -function handleCharBinding(cm, e, ch) { - return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) -} - -var lastStoppedKey = null -function onKeyDown(e) { - var cm = this - cm.curOp.focus = activeElt() - if (signalDOMEvent(cm, e)) { return } - // IE does strange things with escape. - if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false } - var code = e.keyCode - cm.display.shift = code == 16 || e.shiftKey - var handled = handleKeyBinding(cm, e) - if (presto) { - lastStoppedKey = handled ? code : null - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) - { cm.replaceSelection("", null, "cut") } - } - - // Turn mouse into crosshair when Alt is held on Mac. - if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) - { showCrossHair(cm) } -} - -function showCrossHair(cm) { - var lineDiv = cm.display.lineDiv - addClass(lineDiv, "CodeMirror-crosshair") - - function up(e) { - if (e.keyCode == 18 || !e.altKey) { - rmClass(lineDiv, "CodeMirror-crosshair") - off(document, "keyup", up) - off(document, "mouseover", up) - } - } - on(document, "keyup", up) - on(document, "mouseover", up) -} - -function onKeyUp(e) { - if (e.keyCode == 16) { this.doc.sel.shift = false } - signalDOMEvent(this, e) -} - -function onKeyPress(e) { - var cm = this - if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } - var keyCode = e.keyCode, charCode = e.charCode - if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} - if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } - var ch = String.fromCharCode(charCode == null ? keyCode : charCode) - // Some browsers fire keypress events for backspace - if (ch == "\x08") { return } - if (handleCharBinding(cm, e, ch)) { return } - cm.display.input.onKeyPress(e) -} - -// A mouse down can be a single click, double click, triple click, -// start of selection drag, start of text drag, new cursor -// (ctrl-click), rectangle drag (alt-drag), or xwin -// middle-click-paste. Or it might be a click on something we should -// not interfere with, such as a scrollbar or widget. -function onMouseDown(e) { - var cm = this, display = cm.display - if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } - display.input.ensurePolled() - display.shift = e.shiftKey - - if (eventInWidget(display, e)) { - if (!webkit) { - // Briefly turn off draggability, to allow widgets to do - // normal dragging things. - display.scroller.draggable = false - setTimeout(function () { return display.scroller.draggable = true; }, 100) - } - return - } - if (clickInGutter(cm, e)) { return } - var start = posFromMouse(cm, e) - window.focus() - - switch (e_button(e)) { - case 1: - // #3261: make sure, that we're not starting a second selection - if (cm.state.selectingText) - { cm.state.selectingText(e) } - else if (start) - { leftButtonDown(cm, e, start) } - else if (e_target(e) == display.scroller) - { e_preventDefault(e) } - break - case 2: - if (webkit) { cm.state.lastMiddleDown = +new Date } - if (start) { extendSelection(cm.doc, start) } - setTimeout(function () { return display.input.focus(); }, 20) - e_preventDefault(e) - break - case 3: - if (captureRightClick) { onContextMenu(cm, e) } - else { delayBlurEvent(cm) } - break - } -} - -var lastClick; -var lastDoubleClick; -function leftButtonDown(cm, e, start) { - if (ie) { setTimeout(bind(ensureFocus, cm), 0) } - else { cm.curOp.focus = activeElt() } - - var now = +new Date, type - if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { - type = "triple" - } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { - type = "double" - lastDoubleClick = {time: now, pos: start} - } else { - type = "single" - lastClick = {time: now, pos: start} - } - - var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained - if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && - type == "single" && (contained = sel.contains(start)) > -1 && - (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) && - (cmp(contained.to(), start) > 0 || start.xRel < 0)) - { leftButtonStartDrag(cm, e, start, modifier) } - else - { leftButtonSelect(cm, e, start, type, modifier) } -} - -// Start a text drag. When it ends, see if any dragging actually -// happen, and treat as a click if it didn't. -function leftButtonStartDrag(cm, e, start, modifier) { - var display = cm.display, startTime = +new Date - var dragEnd = operation(cm, function (e2) { - if (webkit) { display.scroller.draggable = false } - cm.state.draggingText = false - off(document, "mouseup", dragEnd) - off(display.scroller, "drop", dragEnd) - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2) - if (!modifier && +new Date - 200 < startTime) - { extendSelection(cm.doc, start) } - // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) - if (webkit || ie && ie_version == 9) - { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) } - else - { display.input.focus() } - } - }) - // Let the drag handler handle this. - if (webkit) { display.scroller.draggable = true } - cm.state.draggingText = dragEnd - dragEnd.copy = mac ? e.altKey : e.ctrlKey - // IE's approach to draggable - if (display.scroller.dragDrop) { display.scroller.dragDrop() } - on(document, "mouseup", dragEnd) - on(display.scroller, "drop", dragEnd) -} - -// Normal selection, as opposed to text dragging. -function leftButtonSelect(cm, e, start, type, addNew) { - var display = cm.display, doc = cm.doc - e_preventDefault(e) - - var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges - if (addNew && !e.shiftKey) { - ourIndex = doc.sel.contains(start) - if (ourIndex > -1) - { ourRange = ranges[ourIndex] } - else - { ourRange = new Range(start, start) } - } else { - ourRange = doc.sel.primary() - ourIndex = doc.sel.primIndex - } - - if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) { - type = "rect" - if (!addNew) { ourRange = new Range(start, start) } - start = posFromMouse(cm, e, true, true) - ourIndex = -1 - } else if (type == "double") { - var word = cm.findWordAt(start) - if (cm.display.shift || doc.extend) - { ourRange = extendRange(doc, ourRange, word.anchor, word.head) } - else - { ourRange = word } - } else if (type == "triple") { - var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))) - if (cm.display.shift || doc.extend) - { ourRange = extendRange(doc, ourRange, line.anchor, line.head) } - else - { ourRange = line } - } else { - ourRange = extendRange(doc, ourRange, start) - } - - if (!addNew) { - ourIndex = 0 - setSelection(doc, new Selection([ourRange], 0), sel_mouse) - startSel = doc.sel - } else if (ourIndex == -1) { - ourIndex = ranges.length - setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), - {scroll: false, origin: "*mouse"}) - } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) { - setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), - {scroll: false, origin: "*mouse"}) - startSel = doc.sel - } else { - replaceOneSelection(doc, ourIndex, ourRange, sel_mouse) - } - - var lastPos = start - function extendTo(pos) { - if (cmp(lastPos, pos) == 0) { return } - lastPos = pos - - if (type == "rect") { - var ranges = [], tabSize = cm.options.tabSize - var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize) - var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize) - var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol) - for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); - line <= end; line++) { - var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize) - if (left == right) - { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) } - else if (text.length > leftPos) - { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) } - } - if (!ranges.length) { ranges.push(new Range(start, start)) } - setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), - {origin: "*mouse", scroll: false}) - cm.scrollIntoView(pos) - } else { - var oldRange = ourRange - var anchor = oldRange.anchor, head = pos - if (type != "single") { - var range - if (type == "double") - { range = cm.findWordAt(pos) } - else - { range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))) } - if (cmp(range.anchor, anchor) > 0) { - head = range.head - anchor = minPos(oldRange.from(), range.anchor) - } else { - head = range.anchor - anchor = maxPos(oldRange.to(), range.head) - } - } - var ranges$1 = startSel.ranges.slice(0) - ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head) - setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse) - } - } - - var editorSize = display.wrapper.getBoundingClientRect() - // Used to ensure timeout re-tries don't fire when another extend - // happened in the meantime (clearTimeout isn't reliable -- at - // least on Chrome, the timeouts still happen even when cleared, - // if the clear happens after their scheduled firing time). - var counter = 0 - - function extend(e) { - var curCount = ++counter - var cur = posFromMouse(cm, e, true, type == "rect") - if (!cur) { return } - if (cmp(cur, lastPos) != 0) { - cm.curOp.focus = activeElt() - extendTo(cur) - var visible = visibleLines(display, doc) - if (cur.line >= visible.to || cur.line < visible.from) - { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e) }}), 150) } - } else { - var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0 - if (outside) { setTimeout(operation(cm, function () { - if (counter != curCount) { return } - display.scroller.scrollTop += outside - extend(e) - }), 50) } - } - } - - function done(e) { - cm.state.selectingText = false - counter = Infinity - e_preventDefault(e) - display.input.focus() - off(document, "mousemove", move) - off(document, "mouseup", up) - doc.history.lastSelOrigin = null - } - - var move = operation(cm, function (e) { - if (!e_button(e)) { done(e) } - else { extend(e) } - }) - var up = operation(cm, done) - cm.state.selectingText = up - on(document, "mousemove", move) - on(document, "mouseup", up) -} - - -// Determines whether an event happened in the gutter, and fires the -// handlers for the corresponding event. -function gutterEvent(cm, e, type, prevent) { - var mX, mY - try { mX = e.clientX; mY = e.clientY } - catch(e) { return false } - if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } - if (prevent) { e_preventDefault(e) } - - var display = cm.display - var lineBox = display.lineDiv.getBoundingClientRect() - - if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } - mY -= lineBox.top - display.viewOffset - - for (var i = 0; i < cm.options.gutters.length; ++i) { - var g = display.gutters.childNodes[i] - if (g && g.getBoundingClientRect().right >= mX) { - var line = lineAtHeight(cm.doc, mY) - var gutter = cm.options.gutters[i] - signal(cm, type, cm, line, gutter, e) - return e_defaultPrevented(e) - } - } -} - -function clickInGutter(cm, e) { - return gutterEvent(cm, e, "gutterClick", true) -} - -// CONTEXT MENU HANDLING - -// To make the context menu work, we need to briefly unhide the -// textarea (making it as unobtrusive as possible) to let the -// right-click take effect on it. -function onContextMenu(cm, e) { - if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } - if (signalDOMEvent(cm, e, "contextmenu")) { return } - cm.display.input.onContextMenu(e) -} - -function contextMenuInGutter(cm, e) { - if (!hasHandler(cm, "gutterContextMenu")) { return false } - return gutterEvent(cm, e, "gutterContextMenu", false) -} - -function themeChanged(cm) { - cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + - cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-") - clearCaches(cm) -} - -var Init = {toString: function(){return "CodeMirror.Init"}} - -var defaults = {} -var optionHandlers = {} - -function defineOptions(CodeMirror) { - var optionHandlers = CodeMirror.optionHandlers - - function option(name, deflt, handle, notOnInit) { - CodeMirror.defaults[name] = deflt - if (handle) { optionHandlers[name] = - notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old) }} : handle } - } - - CodeMirror.defineOption = option - - // Passed to option handlers when there is no old value. - CodeMirror.Init = Init - - // These two are, on init, called from the constructor because they - // have to be initialized before the editor can start at all. - option("value", "", function (cm, val) { return cm.setValue(val); }, true) - option("mode", null, function (cm, val) { - cm.doc.modeOption = val - loadMode(cm) - }, true) - - option("indentUnit", 2, loadMode, true) - option("indentWithTabs", false) - option("smartIndent", true) - option("tabSize", 4, function (cm) { - resetModeState(cm) - clearCaches(cm) - regChange(cm) - }, true) - option("lineSeparator", null, function (cm, val) { - cm.doc.lineSep = val - if (!val) { return } - var newBreaks = [], lineNo = cm.doc.first - cm.doc.iter(function (line) { - for (var pos = 0;;) { - var found = line.text.indexOf(val, pos) - if (found == -1) { break } - pos = found + val.length - newBreaks.push(Pos(lineNo, found)) - } - lineNo++ - }) - for (var i = newBreaks.length - 1; i >= 0; i--) - { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) } - }) - option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) { - cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g") - if (old != Init) { cm.refresh() } - }) - option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true) - option("electricChars", true) - option("inputStyle", mobile ? "contenteditable" : "textarea", function () { - throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME - }, true) - option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true) - option("rtlMoveVisually", !windows) - option("wholeLineUpdateBefore", true) - - option("theme", "default", function (cm) { - themeChanged(cm) - guttersChanged(cm) - }, true) - option("keyMap", "default", function (cm, val, old) { - var next = getKeyMap(val) - var prev = old != Init && getKeyMap(old) - if (prev && prev.detach) { prev.detach(cm, next) } - if (next.attach) { next.attach(cm, prev || null) } - }) - option("extraKeys", null) - - option("lineWrapping", false, wrappingChanged, true) - option("gutters", [], function (cm) { - setGuttersForLineNumbers(cm.options) - guttersChanged(cm) - }, true) - option("fixedGutter", true, function (cm, val) { - cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0" - cm.refresh() - }, true) - option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true) - option("scrollbarStyle", "native", function (cm) { - initScrollbars(cm) - updateScrollbars(cm) - cm.display.scrollbars.setScrollTop(cm.doc.scrollTop) - cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft) - }, true) - option("lineNumbers", false, function (cm) { - setGuttersForLineNumbers(cm.options) - guttersChanged(cm) - }, true) - option("firstLineNumber", 1, guttersChanged, true) - option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true) - option("showCursorWhenSelecting", false, updateSelection, true) - - option("resetSelectionOnContextMenu", true) - option("lineWiseCopyCut", true) - - option("readOnly", false, function (cm, val) { - if (val == "nocursor") { - onBlur(cm) - cm.display.input.blur() - cm.display.disabled = true - } else { - cm.display.disabled = false - } - cm.display.input.readOnlyChanged(val) - }) - option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset() }}, true) - option("dragDrop", true, dragDropChanged) - option("allowDropFileTypes", null) - - option("cursorBlinkRate", 530) - option("cursorScrollMargin", 0) - option("cursorHeight", 1, updateSelection, true) - option("singleCursorHeightPerLine", true, updateSelection, true) - option("workTime", 100) - option("workDelay", 100) - option("flattenSpans", true, resetModeState, true) - option("addModeClass", false, resetModeState, true) - option("pollInterval", 100) - option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }) - option("historyEventDelay", 1250) - option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true) - option("maxHighlightLength", 10000, resetModeState, true) - option("moveInputWithCursor", true, function (cm, val) { - if (!val) { cm.display.input.resetPosition() } - }) - - option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }) - option("autofocus", null) - option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true) -} - -function guttersChanged(cm) { - updateGutters(cm) - regChange(cm) - alignHorizontally(cm) -} - -function dragDropChanged(cm, value, old) { - var wasOn = old && old != Init - if (!value != !wasOn) { - var funcs = cm.display.dragFunctions - var toggle = value ? on : off - toggle(cm.display.scroller, "dragstart", funcs.start) - toggle(cm.display.scroller, "dragenter", funcs.enter) - toggle(cm.display.scroller, "dragover", funcs.over) - toggle(cm.display.scroller, "dragleave", funcs.leave) - toggle(cm.display.scroller, "drop", funcs.drop) - } -} - -function wrappingChanged(cm) { - if (cm.options.lineWrapping) { - addClass(cm.display.wrapper, "CodeMirror-wrap") - cm.display.sizer.style.minWidth = "" - cm.display.sizerWidth = null - } else { - rmClass(cm.display.wrapper, "CodeMirror-wrap") - findMaxLine(cm) - } - estimateLineHeights(cm) - regChange(cm) - clearCaches(cm) - setTimeout(function () { return updateScrollbars(cm); }, 100) -} - -// A CodeMirror instance represents an editor. This is the object -// that user code is usually dealing with. - -function CodeMirror(place, options) { - var this$1 = this; - - if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } - - this.options = options = options ? copyObj(options) : {} - // Determine effective options based on given values and defaults. - copyObj(defaults, options, false) - setGuttersForLineNumbers(options) - - var doc = options.value - if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction) } - this.doc = doc - - var input = new CodeMirror.inputStyles[options.inputStyle](this) - var display = this.display = new Display(place, doc, input) - display.wrapper.CodeMirror = this - updateGutters(this) - themeChanged(this) - if (options.lineWrapping) - { this.display.wrapper.className += " CodeMirror-wrap" } - initScrollbars(this) - - this.state = { - keyMaps: [], // stores maps added by addKeyMap - overlays: [], // highlighting overlays, as added by addOverlay - modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info - overwrite: false, - delayingBlurEvent: false, - focused: false, - suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll - selectingText: false, - draggingText: false, - highlight: new Delayed(), // stores highlight worker timeout - keySeq: null, // Unfinished key sequence - specialChars: null - } - - if (options.autofocus && !mobile) { display.input.focus() } - - // Override magic textarea content restore that IE sometimes does - // on our hidden textarea on reload - if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20) } - - registerEventHandlers(this) - ensureGlobalHandlers() - - startOperation(this) - this.curOp.forceUpdate = true - attachDoc(this, doc) - - if ((options.autofocus && !mobile) || this.hasFocus()) - { setTimeout(bind(onFocus, this), 20) } - else - { onBlur(this) } - - for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) - { optionHandlers[opt](this$1, options[opt], Init) } } - maybeUpdateLineNumberWidth(this) - if (options.finishInit) { options.finishInit(this) } - for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1) } - endOperation(this) - // Suppress optimizelegibility in Webkit, since it breaks text - // measuring on line wrapping boundaries. - if (webkit && options.lineWrapping && - getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") - { display.lineDiv.style.textRendering = "auto" } -} - -// The default configuration options. -CodeMirror.defaults = defaults -// Functions to run when options are changed. -CodeMirror.optionHandlers = optionHandlers - -// Attach the necessary event handlers when initializing the editor -function registerEventHandlers(cm) { - var d = cm.display - on(d.scroller, "mousedown", operation(cm, onMouseDown)) - // Older IE's will not fire a second mousedown for a double click - if (ie && ie_version < 11) - { on(d.scroller, "dblclick", operation(cm, function (e) { - if (signalDOMEvent(cm, e)) { return } - var pos = posFromMouse(cm, e) - if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } - e_preventDefault(e) - var word = cm.findWordAt(pos) - extendSelection(cm.doc, word.anchor, word.head) - })) } - else - { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }) } - // Some browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for these browsers. - if (!captureRightClick) { on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }) } - - // Used to suppress mouse event handling when a touch happens - var touchFinished, prevTouch = {end: 0} - function finishTouch() { - if (d.activeTouch) { - touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000) - prevTouch = d.activeTouch - prevTouch.end = +new Date - } - } - function isMouseLikeTouchEvent(e) { - if (e.touches.length != 1) { return false } - var touch = e.touches[0] - return touch.radiusX <= 1 && touch.radiusY <= 1 - } - function farAway(touch, other) { - if (other.left == null) { return true } - var dx = other.left - touch.left, dy = other.top - touch.top - return dx * dx + dy * dy > 20 * 20 - } - on(d.scroller, "touchstart", function (e) { - if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { - d.input.ensurePolled() - clearTimeout(touchFinished) - var now = +new Date - d.activeTouch = {start: now, moved: false, - prev: now - prevTouch.end <= 300 ? prevTouch : null} - if (e.touches.length == 1) { - d.activeTouch.left = e.touches[0].pageX - d.activeTouch.top = e.touches[0].pageY - } - } - }) - on(d.scroller, "touchmove", function () { - if (d.activeTouch) { d.activeTouch.moved = true } - }) - on(d.scroller, "touchend", function (e) { - var touch = d.activeTouch - if (touch && !eventInWidget(d, e) && touch.left != null && - !touch.moved && new Date - touch.start < 300) { - var pos = cm.coordsChar(d.activeTouch, "page"), range - if (!touch.prev || farAway(touch, touch.prev)) // Single tap - { range = new Range(pos, pos) } - else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap - { range = cm.findWordAt(pos) } - else // Triple tap - { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } - cm.setSelection(range.anchor, range.head) - cm.focus() - e_preventDefault(e) - } - finishTouch() - }) - on(d.scroller, "touchcancel", finishTouch) - - // Sync scrolling between fake scrollbars and real scrollable - // area, ensure viewport is updated when scrolling. - on(d.scroller, "scroll", function () { - if (d.scroller.clientHeight) { - setScrollTop(cm, d.scroller.scrollTop) - setScrollLeft(cm, d.scroller.scrollLeft, true) - signal(cm, "scroll", cm) - } - }) - - // Listen to wheel events in order to try and update the viewport on time. - on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }) - on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }) - - // Prevent wrapper from ever scrolling - on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }) - - d.dragFunctions = { - enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e) }}, - over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }}, - start: function (e) { return onDragStart(cm, e); }, - drop: operation(cm, onDrop), - leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }} - } - - var inp = d.input.getField() - on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }) - on(inp, "keydown", operation(cm, onKeyDown)) - on(inp, "keypress", operation(cm, onKeyPress)) - on(inp, "focus", function (e) { return onFocus(cm, e); }) - on(inp, "blur", function (e) { return onBlur(cm, e); }) -} - -var initHooks = [] -CodeMirror.defineInitHook = function (f) { return initHooks.push(f); } - -// Indent the given line. The how parameter can be "smart", -// "add"/null, "subtract", or "prev". When aggressive is false -// (typically set to true for forced single-line indents), empty -// lines are not indented, and places where the mode returns Pass -// are left alone. -function indentLine(cm, n, how, aggressive) { - var doc = cm.doc, state - if (how == null) { how = "add" } - if (how == "smart") { - // Fall back to "prev" when the mode doesn't have an indentation - // method. - if (!doc.mode.indent) { how = "prev" } - else { state = getStateBefore(cm, n) } - } - - var tabSize = cm.options.tabSize - var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize) - if (line.stateAfter) { line.stateAfter = null } - var curSpaceString = line.text.match(/^\s*/)[0], indentation - if (!aggressive && !/\S/.test(line.text)) { - indentation = 0 - how = "not" - } else if (how == "smart") { - indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text) - if (indentation == Pass || indentation > 150) { - if (!aggressive) { return } - how = "prev" - } - } - if (how == "prev") { - if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize) } - else { indentation = 0 } - } else if (how == "add") { - indentation = curSpace + cm.options.indentUnit - } else if (how == "subtract") { - indentation = curSpace - cm.options.indentUnit - } else if (typeof how == "number") { - indentation = curSpace + how - } - indentation = Math.max(0, indentation) - - var indentString = "", pos = 0 - if (cm.options.indentWithTabs) - { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"} } - if (pos < indentation) { indentString += spaceStr(indentation - pos) } - - if (indentString != curSpaceString) { - replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input") - line.stateAfter = null - return true - } else { - // Ensure that, if the cursor was in the whitespace at the start - // of the line, it is moved to the end of that space. - for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { - var range = doc.sel.ranges[i$1] - if (range.head.line == n && range.head.ch < curSpaceString.length) { - var pos$1 = Pos(n, curSpaceString.length) - replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)) - break - } - } - } -} - -// This will be set to a {lineWise: bool, text: [string]} object, so -// that, when pasting, we know what kind of selections the copied -// text was made out of. -var lastCopied = null - -function setLastCopied(newLastCopied) { - lastCopied = newLastCopied -} - -function applyTextInput(cm, inserted, deleted, sel, origin) { - var doc = cm.doc - cm.display.shift = false - if (!sel) { sel = doc.sel } - - var paste = cm.state.pasteIncoming || origin == "paste" - var textLines = splitLinesAuto(inserted), multiPaste = null - // When pasing N lines into N selections, insert one line per selection - if (paste && sel.ranges.length > 1) { - if (lastCopied && lastCopied.text.join("\n") == inserted) { - if (sel.ranges.length % lastCopied.text.length == 0) { - multiPaste = [] - for (var i = 0; i < lastCopied.text.length; i++) - { multiPaste.push(doc.splitLines(lastCopied.text[i])) } - } - } else if (textLines.length == sel.ranges.length) { - multiPaste = map(textLines, function (l) { return [l]; }) - } - } - - var updateInput - // Normal behavior is to insert the new text into every selection - for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { - var range = sel.ranges[i$1] - var from = range.from(), to = range.to() - if (range.empty()) { - if (deleted && deleted > 0) // Handle deletion - { from = Pos(from.line, from.ch - deleted) } - else if (cm.state.overwrite && !paste) // Handle overwrite - { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)) } - else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) - { from = to = Pos(from.line, 0) } - } - updateInput = cm.curOp.updateInput - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, - origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")} - makeChange(cm.doc, changeEvent) - signalLater(cm, "inputRead", cm, changeEvent) - } - if (inserted && !paste) - { triggerElectric(cm, inserted) } - - ensureCursorVisible(cm) - cm.curOp.updateInput = updateInput - cm.curOp.typing = true - cm.state.pasteIncoming = cm.state.cutIncoming = false -} - -function handlePaste(e, cm) { - var pasted = e.clipboardData && e.clipboardData.getData("Text") - if (pasted) { - e.preventDefault() - if (!cm.isReadOnly() && !cm.options.disableInput) - { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }) } - return true - } -} - -function triggerElectric(cm, inserted) { - // When an 'electric' character is inserted, immediately trigger a reindent - if (!cm.options.electricChars || !cm.options.smartIndent) { return } - var sel = cm.doc.sel - - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i] - if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } - var mode = cm.getModeAt(range.head) - var indented = false - if (mode.electricChars) { - for (var j = 0; j < mode.electricChars.length; j++) - { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indented = indentLine(cm, range.head.line, "smart") - break - } } - } else if (mode.electricInput) { - if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) - { indented = indentLine(cm, range.head.line, "smart") } - } - if (indented) { signalLater(cm, "electricInput", cm, range.head.line) } - } -} - -function copyableRanges(cm) { - var text = [], ranges = [] - for (var i = 0; i < cm.doc.sel.ranges.length; i++) { - var line = cm.doc.sel.ranges[i].head.line - var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)} - ranges.push(lineRange) - text.push(cm.getRange(lineRange.anchor, lineRange.head)) - } - return {text: text, ranges: ranges} -} - -function disableBrowserMagic(field, spellcheck) { - field.setAttribute("autocorrect", "off") - field.setAttribute("autocapitalize", "off") - field.setAttribute("spellcheck", !!spellcheck) -} - -function hiddenTextarea() { - var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none") - var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;") - // The textarea is kept positioned near the cursor to prevent the - // fact that it'll be scrolled into view on input from scrolling - // our fake cursor out of view. On webkit, when wrap=off, paste is - // very slow. So make the area wide instead. - if (webkit) { te.style.width = "1000px" } - else { te.setAttribute("wrap", "off") } - // If border: 0; -- iOS fails to open keyboard (issue #1287) - if (ios) { te.style.border = "1px solid black" } - disableBrowserMagic(te) - return div -} - -// The publicly visible API. Note that methodOp(f) means -// 'wrap f in an operation, performed on its `this` parameter'. - -// This is not the complete set of editor methods. Most of the -// methods defined on the Doc type are also injected into -// CodeMirror.prototype, for backwards compatibility and -// convenience. - -function addEditorMethods(CodeMirror) { - var optionHandlers = CodeMirror.optionHandlers - - var helpers = CodeMirror.helpers = {} - - CodeMirror.prototype = { - constructor: CodeMirror, - focus: function(){window.focus(); this.display.input.focus()}, - - setOption: function(option, value) { - var options = this.options, old = options[option] - if (options[option] == value && option != "mode") { return } - options[option] = value - if (optionHandlers.hasOwnProperty(option)) - { operation(this, optionHandlers[option])(this, value, old) } - signal(this, "optionChange", this, option) - }, - - getOption: function(option) {return this.options[option]}, - getDoc: function() {return this.doc}, - - addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)) - }, - removeKeyMap: function(map) { - var maps = this.state.keyMaps - for (var i = 0; i < maps.length; ++i) - { if (maps[i] == map || maps[i].name == map) { - maps.splice(i, 1) - return true - } } - }, - - addOverlay: methodOp(function(spec, options) { - var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec) - if (mode.startState) { throw new Error("Overlays may not be stateful.") } - insertSorted(this.state.overlays, - {mode: mode, modeSpec: spec, opaque: options && options.opaque, - priority: (options && options.priority) || 0}, - function (overlay) { return overlay.priority; }) - this.state.modeGen++ - regChange(this) - }), - removeOverlay: methodOp(function(spec) { - var this$1 = this; - - var overlays = this.state.overlays - for (var i = 0; i < overlays.length; ++i) { - var cur = overlays[i].modeSpec - if (cur == spec || typeof spec == "string" && cur.name == spec) { - overlays.splice(i, 1) - this$1.state.modeGen++ - regChange(this$1) - return - } - } - }), - - indentLine: methodOp(function(n, dir, aggressive) { - if (typeof dir != "string" && typeof dir != "number") { - if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev" } - else { dir = dir ? "add" : "subtract" } - } - if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive) } - }), - indentSelection: methodOp(function(how) { - var this$1 = this; - - var ranges = this.doc.sel.ranges, end = -1 - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i] - if (!range.empty()) { - var from = range.from(), to = range.to() - var start = Math.max(end, from.line) - end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1 - for (var j = start; j < end; ++j) - { indentLine(this$1, j, how) } - var newRanges = this$1.doc.sel.ranges - if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) - { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) } - } else if (range.head.line > end) { - indentLine(this$1, range.head.line, how, true) - end = range.head.line - if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1) } - } - } - }), - - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(pos, precise) { - return takeToken(this, pos, precise) - }, - - getLineTokens: function(line, precise) { - return takeToken(this, Pos(line), precise, true) - }, - - getTokenTypeAt: function(pos) { - pos = clipPos(this.doc, pos) - var styles = getLineStyles(this, getLine(this.doc, pos.line)) - var before = 0, after = (styles.length - 1) / 2, ch = pos.ch - var type - if (ch == 0) { type = styles[2] } - else { for (;;) { - var mid = (before + after) >> 1 - if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid } - else if (styles[mid * 2 + 1] < ch) { before = mid + 1 } - else { type = styles[mid * 2 + 2]; break } - } } - var cut = type ? type.indexOf("overlay ") : -1 - return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) - }, - - getModeAt: function(pos) { - var mode = this.doc.mode - if (!mode.innerMode) { return mode } - return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode - }, - - getHelper: function(pos, type) { - return this.getHelpers(pos, type)[0] - }, - - getHelpers: function(pos, type) { - var this$1 = this; - - var found = [] - if (!helpers.hasOwnProperty(type)) { return found } - var help = helpers[type], mode = this.getModeAt(pos) - if (typeof mode[type] == "string") { - if (help[mode[type]]) { found.push(help[mode[type]]) } - } else if (mode[type]) { - for (var i = 0; i < mode[type].length; i++) { - var val = help[mode[type][i]] - if (val) { found.push(val) } - } - } else if (mode.helperType && help[mode.helperType]) { - found.push(help[mode.helperType]) - } else if (help[mode.name]) { - found.push(help[mode.name]) - } - for (var i$1 = 0; i$1 < help._global.length; i$1++) { - var cur = help._global[i$1] - if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1) - { found.push(cur.val) } - } - return found - }, - - getStateAfter: function(line, precise) { - var doc = this.doc - line = clipLine(doc, line == null ? doc.first + doc.size - 1: line) - return getStateBefore(this, line + 1, precise) - }, - - cursorCoords: function(start, mode) { - var pos, range = this.doc.sel.primary() - if (start == null) { pos = range.head } - else if (typeof start == "object") { pos = clipPos(this.doc, start) } - else { pos = start ? range.from() : range.to() } - return cursorCoords(this, pos, mode || "page") - }, - - charCoords: function(pos, mode) { - return charCoords(this, clipPos(this.doc, pos), mode || "page") - }, - - coordsChar: function(coords, mode) { - coords = fromCoordSystem(this, coords, mode || "page") - return coordsChar(this, coords.left, coords.top) - }, - - lineAtHeight: function(height, mode) { - height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top - return lineAtHeight(this.doc, height + this.display.viewOffset) - }, - heightAtLine: function(line, mode, includeWidgets) { - var end = false, lineObj - if (typeof line == "number") { - var last = this.doc.first + this.doc.size - 1 - if (line < this.doc.first) { line = this.doc.first } - else if (line > last) { line = last; end = true } - lineObj = getLine(this.doc, line) - } else { - lineObj = line - } - return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + - (end ? this.doc.height - heightAtLine(lineObj) : 0) - }, - - defaultTextHeight: function() { return textHeight(this.display) }, - defaultCharWidth: function() { return charWidth(this.display) }, - - getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, - - addWidget: function(pos, node, scroll, vert, horiz) { - var display = this.display - pos = cursorCoords(this, clipPos(this.doc, pos)) - var top = pos.bottom, left = pos.left - node.style.position = "absolute" - node.setAttribute("cm-ignore-events", "true") - this.display.input.setUneditable(node) - display.sizer.appendChild(node) - if (vert == "over") { - top = pos.top - } else if (vert == "above" || vert == "near") { - var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), - hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth) - // Default to positioning above (if specified and possible); otherwise default to positioning below - if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) - { top = pos.top - node.offsetHeight } - else if (pos.bottom + node.offsetHeight <= vspace) - { top = pos.bottom } - if (left + node.offsetWidth > hspace) - { left = hspace - node.offsetWidth } - } - node.style.top = top + "px" - node.style.left = node.style.right = "" - if (horiz == "right") { - left = display.sizer.clientWidth - node.offsetWidth - node.style.right = "0px" - } else { - if (horiz == "left") { left = 0 } - else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2 } - node.style.left = left + "px" - } - if (scroll) - { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}) } - }, - - triggerOnKeyDown: methodOp(onKeyDown), - triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: onKeyUp, - - execCommand: function(cmd) { - if (commands.hasOwnProperty(cmd)) - { return commands[cmd].call(null, this) } - }, - - triggerElectric: methodOp(function(text) { triggerElectric(this, text) }), - - findPosH: function(from, amount, unit, visually) { - var this$1 = this; - - var dir = 1 - if (amount < 0) { dir = -1; amount = -amount } - var cur = clipPos(this.doc, from) - for (var i = 0; i < amount; ++i) { - cur = findPosH(this$1.doc, cur, dir, unit, visually) - if (cur.hitSide) { break } - } - return cur - }, - - moveH: methodOp(function(dir, unit) { - var this$1 = this; - - this.extendSelectionsBy(function (range) { - if (this$1.display.shift || this$1.doc.extend || range.empty()) - { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } - else - { return dir < 0 ? range.from() : range.to() } - }, sel_move) - }), - - deleteH: methodOp(function(dir, unit) { - var sel = this.doc.sel, doc = this.doc - if (sel.somethingSelected()) - { doc.replaceSelection("", null, "+delete") } - else - { deleteNearSelection(this, function (range) { - var other = findPosH(doc, range.head, dir, unit, false) - return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} - }) } - }), - - findPosV: function(from, amount, unit, goalColumn) { - var this$1 = this; - - var dir = 1, x = goalColumn - if (amount < 0) { dir = -1; amount = -amount } - var cur = clipPos(this.doc, from) - for (var i = 0; i < amount; ++i) { - var coords = cursorCoords(this$1, cur, "div") - if (x == null) { x = coords.left } - else { coords.left = x } - cur = findPosV(this$1, coords, dir, unit) - if (cur.hitSide) { break } - } - return cur - }, - - moveV: methodOp(function(dir, unit) { - var this$1 = this; - - var doc = this.doc, goals = [] - var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected() - doc.extendSelectionsBy(function (range) { - if (collapse) - { return dir < 0 ? range.from() : range.to() } - var headPos = cursorCoords(this$1, range.head, "div") - if (range.goalColumn != null) { headPos.left = range.goalColumn } - goals.push(headPos.left) - var pos = findPosV(this$1, headPos, dir, unit) - if (unit == "page" && range == doc.sel.primary()) - { addToScrollPos(this$1, null, charCoords(this$1, pos, "div").top - headPos.top) } - return pos - }, sel_move) - if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) - { doc.sel.ranges[i].goalColumn = goals[i] } } - }), - - // Find the word at the given position (as returned by coordsChar). - findWordAt: function(pos) { - var doc = this.doc, line = getLine(doc, pos.line).text - var start = pos.ch, end = pos.ch - if (line) { - var helper = this.getHelper(pos, "wordChars") - if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end } - var startChar = line.charAt(start) - var check = isWordChar(startChar, helper) - ? function (ch) { return isWordChar(ch, helper); } - : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } - : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); } - while (start > 0 && check(line.charAt(start - 1))) { --start } - while (end < line.length && check(line.charAt(end))) { ++end } - } - return new Range(Pos(pos.line, start), Pos(pos.line, end)) - }, - - toggleOverwrite: function(value) { - if (value != null && value == this.state.overwrite) { return } - if (this.state.overwrite = !this.state.overwrite) - { addClass(this.display.cursorDiv, "CodeMirror-overwrite") } - else - { rmClass(this.display.cursorDiv, "CodeMirror-overwrite") } - - signal(this, "overwriteToggle", this, this.state.overwrite) - }, - hasFocus: function() { return this.display.input.getField() == activeElt() }, - isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, - - scrollTo: methodOp(function(x, y) { - if (x != null || y != null) { resolveScrollToPos(this) } - if (x != null) { this.curOp.scrollLeft = x } - if (y != null) { this.curOp.scrollTop = y } - }), - getScrollInfo: function() { - var scroller = this.display.scroller - return {left: scroller.scrollLeft, top: scroller.scrollTop, - height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, - width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, - clientHeight: displayHeight(this), clientWidth: displayWidth(this)} - }, - - scrollIntoView: methodOp(function(range, margin) { - if (range == null) { - range = {from: this.doc.sel.primary().head, to: null} - if (margin == null) { margin = this.options.cursorScrollMargin } - } else if (typeof range == "number") { - range = {from: Pos(range, 0), to: null} - } else if (range.from == null) { - range = {from: range, to: null} - } - if (!range.to) { range.to = range.from } - range.margin = margin || 0 - - if (range.from.line != null) { - resolveScrollToPos(this) - this.curOp.scrollToPos = range - } else { - var sPos = calculateScrollPos(this, { - left: Math.min(range.from.left, range.to.left), - top: Math.min(range.from.top, range.to.top) - range.margin, - right: Math.max(range.from.right, range.to.right), - bottom: Math.max(range.from.bottom, range.to.bottom) + range.margin - }) - this.scrollTo(sPos.scrollLeft, sPos.scrollTop) - } - }), - - setSize: methodOp(function(width, height) { - var this$1 = this; - - var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; } - if (width != null) { this.display.wrapper.style.width = interpret(width) } - if (height != null) { this.display.wrapper.style.height = interpret(height) } - if (this.options.lineWrapping) { clearLineMeasurementCache(this) } - var lineNo = this.display.viewFrom - this.doc.iter(lineNo, this.display.viewTo, function (line) { - if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) - { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } - ++lineNo - }) - this.curOp.forceUpdate = true - signal(this, "refresh", this) - }), - - operation: function(f){return runInOp(this, f)}, - - refresh: methodOp(function() { - var oldHeight = this.display.cachedTextHeight - regChange(this) - this.curOp.forceUpdate = true - clearCaches(this) - this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop) - updateGutterSpace(this) - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) - { estimateLineHeights(this) } - signal(this, "refresh", this) - }), - - swapDoc: methodOp(function(doc) { - var old = this.doc - old.cm = null - attachDoc(this, doc) - clearCaches(this) - this.display.input.reset() - this.scrollTo(doc.scrollLeft, doc.scrollTop) - this.curOp.forceScroll = true - signalLater(this, "swapDoc", this, old) - return old - }), - - getInputField: function(){return this.display.input.getField()}, - getWrapperElement: function(){return this.display.wrapper}, - getScrollerElement: function(){return this.display.scroller}, - getGutterElement: function(){return this.display.gutters} - } - eventMixin(CodeMirror) - - CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []} } - helpers[type][name] = value - } - CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { - CodeMirror.registerHelper(type, name, value) - helpers[type]._global.push({pred: predicate, val: value}) - } -} - -// Used for horizontal relative motion. Dir is -1 or 1 (left or -// right), unit can be "char", "column" (like char, but doesn't -// cross line boundaries), "word" (across next word), or "group" (to -// the start of next group of word or non-word-non-whitespace -// chars). The visually param controls whether, in right-to-left -// text, direction 1 means to move towards the next index in the -// string, or towards the character to the right of the current -// position. The resulting position will have a hitSide=true -// property if it reached the end of the document. -function findPosH(doc, pos, dir, unit, visually) { - var oldPos = pos - var origDir = dir - var lineObj = getLine(doc, pos.line) - function findNextLine() { - var l = pos.line + dir - if (l < doc.first || l >= doc.first + doc.size) { return false } - pos = new Pos(l, pos.ch, pos.sticky) - return lineObj = getLine(doc, l) - } - function moveOnce(boundToLine) { - var next - if (visually) { - next = moveVisually(doc.cm, lineObj, pos, dir) - } else { - next = moveLogically(lineObj, pos, dir) - } - if (next == null) { - if (!boundToLine && findNextLine()) - { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir) } - else - { return false } - } else { - pos = next - } - return true - } - - if (unit == "char") { - moveOnce() - } else if (unit == "column") { - moveOnce(true) - } else if (unit == "word" || unit == "group") { - var sawType = null, group = unit == "group" - var helper = doc.cm && doc.cm.getHelper(pos, "wordChars") - for (var first = true;; first = false) { - if (dir < 0 && !moveOnce(!first)) { break } - var cur = lineObj.text.charAt(pos.ch) || "\n" - var type = isWordChar(cur, helper) ? "w" - : group && cur == "\n" ? "n" - : !group || /\s/.test(cur) ? null - : "p" - if (group && !first && !type) { type = "s" } - if (sawType && sawType != type) { - if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after"} - break - } - - if (type) { sawType = type } - if (dir > 0 && !moveOnce(!first)) { break } - } - } - var result = skipAtomic(doc, pos, oldPos, origDir, true) - if (equalCursorPos(oldPos, result)) { result.hitSide = true } - return result -} - -// For relative vertical movement. Dir may be -1 or 1. Unit can be -// "page" or "line". The resulting position will have a hitSide=true -// property if it reached the end of the document. -function findPosV(cm, pos, dir, unit) { - var doc = cm.doc, x = pos.left, y - if (unit == "page") { - var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight) - var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3) - y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount - - } else if (unit == "line") { - y = dir > 0 ? pos.bottom + 3 : pos.top - 3 - } - var target - for (;;) { - target = coordsChar(cm, x, y) - if (!target.outside) { break } - if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } - y += dir * 5 - } - return target -} - -// CONTENTEDITABLE INPUT STYLE - -var ContentEditableInput = function(cm) { - this.cm = cm - this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null - this.polling = new Delayed() - this.composing = null - this.gracePeriod = false - this.readDOMTimeout = null -}; - -ContentEditableInput.prototype.init = function (display) { - var this$1 = this; - - var input = this, cm = input.cm - var div = input.div = display.lineDiv - disableBrowserMagic(div, cm.options.spellcheck) - - on(div, "paste", function (e) { - if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - // IE doesn't fire input events, so we schedule a read for the pasted content in this way - if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20) } - }) - - on(div, "compositionstart", function (e) { - this$1.composing = {data: e.data, done: false} - }) - on(div, "compositionupdate", function (e) { - if (!this$1.composing) { this$1.composing = {data: e.data, done: false} } - }) - on(div, "compositionend", function (e) { - if (this$1.composing) { - if (e.data != this$1.composing.data) { this$1.readFromDOMSoon() } - this$1.composing.done = true - } - }) - - on(div, "touchstart", function () { return input.forceCompositionEnd(); }) - - on(div, "input", function () { - if (!this$1.composing) { this$1.readFromDOMSoon() } - }) - - function onCopyCut(e) { - if (signalDOMEvent(cm, e)) { return } - if (cm.somethingSelected()) { - setLastCopied({lineWise: false, text: cm.getSelections()}) - if (e.type == "cut") { cm.replaceSelection("", null, "cut") } - } else if (!cm.options.lineWiseCopyCut) { - return - } else { - var ranges = copyableRanges(cm) - setLastCopied({lineWise: true, text: ranges.text}) - if (e.type == "cut") { - cm.operation(function () { - cm.setSelections(ranges.ranges, 0, sel_dontScroll) - cm.replaceSelection("", null, "cut") - }) - } - } - if (e.clipboardData) { - e.clipboardData.clearData() - var content = lastCopied.text.join("\n") - // iOS exposes the clipboard API, but seems to discard content inserted into it - e.clipboardData.setData("Text", content) - if (e.clipboardData.getData("Text") == content) { - e.preventDefault() - return - } - } - // Old-fashioned briefly-focus-a-textarea hack - var kludge = hiddenTextarea(), te = kludge.firstChild - cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild) - te.value = lastCopied.text.join("\n") - var hadFocus = document.activeElement - selectInput(te) - setTimeout(function () { - cm.display.lineSpace.removeChild(kludge) - hadFocus.focus() - if (hadFocus == div) { input.showPrimarySelection() } - }, 50) - } - on(div, "copy", onCopyCut) - on(div, "cut", onCopyCut) -}; - -ContentEditableInput.prototype.prepareSelection = function () { - var result = prepareSelection(this.cm, false) - result.focus = this.cm.state.focused - return result -}; - -ContentEditableInput.prototype.showSelection = function (info, takeFocus) { - if (!info || !this.cm.display.view.length) { return } - if (info.focus || takeFocus) { this.showPrimarySelection() } - this.showMultipleSelections(info) -}; - -ContentEditableInput.prototype.showPrimarySelection = function () { - var sel = window.getSelection(), prim = this.cm.doc.sel.primary() - var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset) - var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset) - if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && - cmp(minPos(curAnchor, curFocus), prim.from()) == 0 && - cmp(maxPos(curAnchor, curFocus), prim.to()) == 0) - { return } - - var start = posToDOM(this.cm, prim.from()) - var end = posToDOM(this.cm, prim.to()) - if (!start && !end) { - sel.removeAllRanges() - return - } - - var view = this.cm.display.view - var old = sel.rangeCount && sel.getRangeAt(0) - if (!start) { - start = {node: view[0].measure.map[2], offset: 0} - } else if (!end) { // FIXME dangerously hacky - var measure = view[view.length - 1].measure - var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map - end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]} - } - - var rng - try { rng = range(start.node, start.offset, end.offset, end.node) } - catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible - if (rng) { - if (!gecko && this.cm.state.focused) { - sel.collapse(start.node, start.offset) - if (!rng.collapsed) { - sel.removeAllRanges() - sel.addRange(rng) - } - } else { - sel.removeAllRanges() - sel.addRange(rng) - } - if (old && sel.anchorNode == null) { sel.addRange(old) } - else if (gecko) { this.startGracePeriod() } - } - this.rememberSelection() -}; - -ContentEditableInput.prototype.startGracePeriod = function () { - var this$1 = this; - - clearTimeout(this.gracePeriod) - this.gracePeriod = setTimeout(function () { - this$1.gracePeriod = false - if (this$1.selectionChanged()) - { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }) } - }, 20) -}; - -ContentEditableInput.prototype.showMultipleSelections = function (info) { - removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors) - removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection) -}; - -ContentEditableInput.prototype.rememberSelection = function () { - var sel = window.getSelection() - this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset - this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset -}; - -ContentEditableInput.prototype.selectionInEditor = function () { - var sel = window.getSelection() - if (!sel.rangeCount) { return false } - var node = sel.getRangeAt(0).commonAncestorContainer - return contains(this.div, node) -}; - -ContentEditableInput.prototype.focus = function () { - if (this.cm.options.readOnly != "nocursor") { - if (!this.selectionInEditor()) - { this.showSelection(this.prepareSelection(), true) } - this.div.focus() - } -}; -ContentEditableInput.prototype.blur = function () { this.div.blur() }; -ContentEditableInput.prototype.getField = function () { return this.div }; - -ContentEditableInput.prototype.supportsTouch = function () { return true }; - -ContentEditableInput.prototype.receivedFocus = function () { - var input = this - if (this.selectionInEditor()) - { this.pollSelection() } - else - { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }) } - - function poll() { - if (input.cm.state.focused) { - input.pollSelection() - input.polling.set(input.cm.options.pollInterval, poll) - } - } - this.polling.set(this.cm.options.pollInterval, poll) -}; - -ContentEditableInput.prototype.selectionChanged = function () { - var sel = window.getSelection() - return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || - sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset -}; - -ContentEditableInput.prototype.pollSelection = function () { - if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } - var sel = window.getSelection(), cm = this.cm - // On Android Chrome (version 56, at least), backspacing into an - // uneditable block element will put the cursor in that element, - // and then, because it's not editable, hide the virtual keyboard. - // Because Android doesn't allow us to actually detect backspace - // presses in a sane way, this code checks for when that happens - // and simulates a backspace press in this case. - if (android && chrome && this.cm.options.gutters.length && isInGutter(sel.anchorNode)) { - this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}) - this.blur() - this.focus() - return - } - if (this.composing) { return } - this.rememberSelection() - var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset) - var head = domToPos(cm, sel.focusNode, sel.focusOffset) - if (anchor && head) { runInOp(cm, function () { - setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll) - if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true } - }) } -}; - -ContentEditableInput.prototype.pollContent = function () { - if (this.readDOMTimeout != null) { - clearTimeout(this.readDOMTimeout) - this.readDOMTimeout = null - } - - var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary() - var from = sel.from(), to = sel.to() - if (from.ch == 0 && from.line > cm.firstLine()) - { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length) } - if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) - { to = Pos(to.line + 1, 0) } - if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } - - var fromIndex, fromLine, fromNode - if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { - fromLine = lineNo(display.view[0].line) - fromNode = display.view[0].node - } else { - fromLine = lineNo(display.view[fromIndex].line) - fromNode = display.view[fromIndex - 1].node.nextSibling - } - var toIndex = findViewIndex(cm, to.line) - var toLine, toNode - if (toIndex == display.view.length - 1) { - toLine = display.viewTo - 1 - toNode = display.lineDiv.lastChild - } else { - toLine = lineNo(display.view[toIndex + 1].line) - 1 - toNode = display.view[toIndex + 1].node.previousSibling - } - - if (!fromNode) { return false } - var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)) - var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)) - while (newText.length > 1 && oldText.length > 1) { - if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine-- } - else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++ } - else { break } - } - - var cutFront = 0, cutEnd = 0 - var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length) - while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) - { ++cutFront } - var newBot = lst(newText), oldBot = lst(oldText) - var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), - oldBot.length - (oldText.length == 1 ? cutFront : 0)) - while (cutEnd < maxCutEnd && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) - { ++cutEnd } - // Try to move start of change to start of selection if ambiguous - if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { - while (cutFront && cutFront > from.ch && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { - cutFront-- - cutEnd++ - } - } - - newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "") - newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "") - - var chFrom = Pos(fromLine, cutFront) - var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0) - if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { - replaceRange(cm.doc, newText, chFrom, chTo, "+input") - return true - } -}; - -ContentEditableInput.prototype.ensurePolled = function () { - this.forceCompositionEnd() -}; -ContentEditableInput.prototype.reset = function () { - this.forceCompositionEnd() -}; -ContentEditableInput.prototype.forceCompositionEnd = function () { - if (!this.composing) { return } - clearTimeout(this.readDOMTimeout) - this.composing = null - this.updateFromDOM() - this.div.blur() - this.div.focus() -}; -ContentEditableInput.prototype.readFromDOMSoon = function () { - var this$1 = this; - - if (this.readDOMTimeout != null) { return } - this.readDOMTimeout = setTimeout(function () { - this$1.readDOMTimeout = null - if (this$1.composing) { - if (this$1.composing.done) { this$1.composing = null } - else { return } - } - this$1.updateFromDOM() - }, 80) -}; - -ContentEditableInput.prototype.updateFromDOM = function () { - var this$1 = this; - - if (this.cm.isReadOnly() || !this.pollContent()) - { runInOp(this.cm, function () { return regChange(this$1.cm); }) } -}; - -ContentEditableInput.prototype.setUneditable = function (node) { - node.contentEditable = "false" -}; - -ContentEditableInput.prototype.onKeyPress = function (e) { - if (e.charCode == 0) { return } - e.preventDefault() - if (!this.cm.isReadOnly()) - { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) } -}; - -ContentEditableInput.prototype.readOnlyChanged = function (val) { - this.div.contentEditable = String(val != "nocursor") -}; - -ContentEditableInput.prototype.onContextMenu = function () {}; -ContentEditableInput.prototype.resetPosition = function () {}; - -ContentEditableInput.prototype.needsContentAttribute = true - -function posToDOM(cm, pos) { - var view = findViewForLine(cm, pos.line) - if (!view || view.hidden) { return null } - var line = getLine(cm.doc, pos.line) - var info = mapFromLineView(view, line, pos.line) - - var order = getOrder(line, cm.doc.direction), side = "left" - if (order) { - var partPos = getBidiPartAt(order, pos.ch) - side = partPos % 2 ? "right" : "left" - } - var result = nodeAndOffsetInLineMap(info.map, pos.ch, side) - result.offset = result.collapse == "right" ? result.end : result.start - return result -} - -function isInGutter(node) { - for (var scan = node; scan; scan = scan.parentNode) - { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } - return false -} - -function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } - -function domTextBetween(cm, from, to, fromLine, toLine) { - var text = "", closing = false, lineSep = cm.doc.lineSeparator() - function recognizeMarker(id) { return function (marker) { return marker.id == id; } } - function close() { - if (closing) { - text += lineSep - closing = false - } - } - function addText(str) { - if (str) { - close() - text += str - } - } - function walk(node) { - if (node.nodeType == 1) { - var cmText = node.getAttribute("cm-text") - if (cmText != null) { - addText(cmText || node.textContent.replace(/\u200b/g, "")) - return - } - var markerID = node.getAttribute("cm-marker"), range - if (markerID) { - var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)) - if (found.length && (range = found[0].find())) - { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)) } - return - } - if (node.getAttribute("contenteditable") == "false") { return } - var isBlock = /^(pre|div|p)$/i.test(node.nodeName) - if (isBlock) { close() } - for (var i = 0; i < node.childNodes.length; i++) - { walk(node.childNodes[i]) } - if (isBlock) { closing = true } - } else if (node.nodeType == 3) { - addText(node.nodeValue) - } - } - for (;;) { - walk(from) - if (from == to) { break } - from = from.nextSibling - } - return text -} - -function domToPos(cm, node, offset) { - var lineNode - if (node == cm.display.lineDiv) { - lineNode = cm.display.lineDiv.childNodes[offset] - if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } - node = null; offset = 0 - } else { - for (lineNode = node;; lineNode = lineNode.parentNode) { - if (!lineNode || lineNode == cm.display.lineDiv) { return null } - if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } - } - } - for (var i = 0; i < cm.display.view.length; i++) { - var lineView = cm.display.view[i] - if (lineView.node == lineNode) - { return locateNodeInLineView(lineView, node, offset) } - } -} - -function locateNodeInLineView(lineView, node, offset) { - var wrapper = lineView.text.firstChild, bad = false - if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } - if (node == wrapper) { - bad = true - node = wrapper.childNodes[offset] - offset = 0 - if (!node) { - var line = lineView.rest ? lst(lineView.rest) : lineView.line - return badPos(Pos(lineNo(line), line.text.length), bad) - } - } - - var textNode = node.nodeType == 3 ? node : null, topNode = node - if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { - textNode = node.firstChild - if (offset) { offset = textNode.nodeValue.length } - } - while (topNode.parentNode != wrapper) { topNode = topNode.parentNode } - var measure = lineView.measure, maps = measure.maps - - function find(textNode, topNode, offset) { - for (var i = -1; i < (maps ? maps.length : 0); i++) { - var map = i < 0 ? measure.map : maps[i] - for (var j = 0; j < map.length; j += 3) { - var curNode = map[j + 2] - if (curNode == textNode || curNode == topNode) { - var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]) - var ch = map[j] + offset - if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)] } - return Pos(line, ch) - } - } - } - } - var found = find(textNode, topNode, offset) - if (found) { return badPos(found, bad) } - - // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems - for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { - found = find(after, after.firstChild, 0) - if (found) - { return badPos(Pos(found.line, found.ch - dist), bad) } - else - { dist += after.textContent.length } - } - for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { - found = find(before, before.firstChild, -1) - if (found) - { return badPos(Pos(found.line, found.ch + dist$1), bad) } - else - { dist$1 += before.textContent.length } - } -} - -// TEXTAREA INPUT STYLE - -var TextareaInput = function(cm) { - this.cm = cm - // See input.poll and input.reset - this.prevInput = "" - - // Flag that indicates whether we expect input to appear real soon - // now (after some event like 'keypress' or 'input') and are - // polling intensively. - this.pollingFast = false - // Self-resetting timeout for the poller - this.polling = new Delayed() - // Tracks when input.reset has punted to just putting a short - // string into the textarea instead of the full selection. - this.inaccurateSelection = false - // Used to work around IE issue with selection being forgotten when focus moves away from textarea - this.hasSelection = false - this.composing = null -}; - -TextareaInput.prototype.init = function (display) { - var this$1 = this; - - var input = this, cm = this.cm - - // Wraps and hides input textarea - var div = this.wrapper = hiddenTextarea() - // The semihidden textarea that is focused when the editor is - // focused, and receives input. - var te = this.textarea = div.firstChild - display.wrapper.insertBefore(div, display.wrapper.firstChild) - - // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) - if (ios) { te.style.width = "0px" } - - on(te, "input", function () { - if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null } - input.poll() - }) - - on(te, "paste", function (e) { - if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - - cm.state.pasteIncoming = true - input.fastPoll() - }) - - function prepareCopyCut(e) { - if (signalDOMEvent(cm, e)) { return } - if (cm.somethingSelected()) { - setLastCopied({lineWise: false, text: cm.getSelections()}) - if (input.inaccurateSelection) { - input.prevInput = "" - input.inaccurateSelection = false - te.value = lastCopied.text.join("\n") - selectInput(te) - } - } else if (!cm.options.lineWiseCopyCut) { - return - } else { - var ranges = copyableRanges(cm) - setLastCopied({lineWise: true, text: ranges.text}) - if (e.type == "cut") { - cm.setSelections(ranges.ranges, null, sel_dontScroll) - } else { - input.prevInput = "" - te.value = ranges.text.join("\n") - selectInput(te) - } - } - if (e.type == "cut") { cm.state.cutIncoming = true } - } - on(te, "cut", prepareCopyCut) - on(te, "copy", prepareCopyCut) - - on(display.scroller, "paste", function (e) { - if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } - cm.state.pasteIncoming = true - input.focus() - }) - - // Prevent normal selection in the editor (we handle our own) - on(display.lineSpace, "selectstart", function (e) { - if (!eventInWidget(display, e)) { e_preventDefault(e) } - }) - - on(te, "compositionstart", function () { - var start = cm.getCursor("from") - if (input.composing) { input.composing.range.clear() } - input.composing = { - start: start, - range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) - } - }) - on(te, "compositionend", function () { - if (input.composing) { - input.poll() - input.composing.range.clear() - input.composing = null - } - }) -}; - -TextareaInput.prototype.prepareSelection = function () { - // Redraw the selection and/or cursor - var cm = this.cm, display = cm.display, doc = cm.doc - var result = prepareSelection(cm) - - // Move the hidden textarea near the cursor to prevent scrolling artifacts - if (cm.options.moveInputWithCursor) { - var headPos = cursorCoords(cm, doc.sel.primary().head, "div") - var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect() - result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)) - result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)) - } - - return result -}; - -TextareaInput.prototype.showSelection = function (drawn) { - var cm = this.cm, display = cm.display - removeChildrenAndAdd(display.cursorDiv, drawn.cursors) - removeChildrenAndAdd(display.selectionDiv, drawn.selection) - if (drawn.teTop != null) { - this.wrapper.style.top = drawn.teTop + "px" - this.wrapper.style.left = drawn.teLeft + "px" - } -}; - -// Reset the input to correspond to the selection (or to be empty, -// when not typing and nothing is selected) -TextareaInput.prototype.reset = function (typing) { - if (this.contextMenuPending) { return } - var minimal, selected, cm = this.cm, doc = cm.doc - if (cm.somethingSelected()) { - this.prevInput = "" - var range = doc.sel.primary() - minimal = hasCopyEvent && - (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000) - var content = minimal ? "-" : selected || cm.getSelection() - this.textarea.value = content - if (cm.state.focused) { selectInput(this.textarea) } - if (ie && ie_version >= 9) { this.hasSelection = content } - } else if (!typing) { - this.prevInput = this.textarea.value = "" - if (ie && ie_version >= 9) { this.hasSelection = null } - } - this.inaccurateSelection = minimal -}; - -TextareaInput.prototype.getField = function () { return this.textarea }; - -TextareaInput.prototype.supportsTouch = function () { return false }; - -TextareaInput.prototype.focus = function () { - if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { - try { this.textarea.focus() } - catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM - } -}; - -TextareaInput.prototype.blur = function () { this.textarea.blur() }; - -TextareaInput.prototype.resetPosition = function () { - this.wrapper.style.top = this.wrapper.style.left = 0 -}; - -TextareaInput.prototype.receivedFocus = function () { this.slowPoll() }; - -// Poll for input changes, using the normal rate of polling. This -// runs as long as the editor is focused. -TextareaInput.prototype.slowPoll = function () { - var this$1 = this; - - if (this.pollingFast) { return } - this.polling.set(this.cm.options.pollInterval, function () { - this$1.poll() - if (this$1.cm.state.focused) { this$1.slowPoll() } - }) -}; - -// When an event has just come in that is likely to add or change -// something in the input textarea, we poll faster, to ensure that -// the change appears on the screen quickly. -TextareaInput.prototype.fastPoll = function () { - var missed = false, input = this - input.pollingFast = true - function p() { - var changed = input.poll() - if (!changed && !missed) {missed = true; input.polling.set(60, p)} - else {input.pollingFast = false; input.slowPoll()} - } - input.polling.set(20, p) -}; - -// Read input from the textarea, and update the document to match. -// When something is selected, it is present in the textarea, and -// selected (unless it is huge, in which case a placeholder is -// used). When nothing is selected, the cursor sits after previously -// seen text (can be empty), which is stored in prevInput (we must -// not reset the textarea when typing, because that breaks IME). -TextareaInput.prototype.poll = function () { - var this$1 = this; - - var cm = this.cm, input = this.textarea, prevInput = this.prevInput - // Since this is called a *lot*, try to bail out as cheaply as - // possible when it is clear that nothing happened. hasSelection - // will be the case when there is a lot of text in the textarea, - // in which case reading its value would be expensive. - if (this.contextMenuPending || !cm.state.focused || - (hasSelection(input) && !prevInput && !this.composing) || - cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) - { return false } - - var text = input.value - // If nothing changed, bail. - if (text == prevInput && !cm.somethingSelected()) { return false } - // Work around nonsensical selection resetting in IE9/10, and - // inexplicable appearance of private area unicode characters on - // some key combos in Mac (#2689). - if (ie && ie_version >= 9 && this.hasSelection === text || - mac && /[\uf700-\uf7ff]/.test(text)) { - cm.display.input.reset() - return false - } - - if (cm.doc.sel == cm.display.selForContextMenu) { - var first = text.charCodeAt(0) - if (first == 0x200b && !prevInput) { prevInput = "\u200b" } - if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } - } - // Find the part of the input that is actually new - var same = 0, l = Math.min(prevInput.length, text.length) - while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same } - - runInOp(cm, function () { - applyTextInput(cm, text.slice(same), prevInput.length - same, - null, this$1.composing ? "*compose" : null) - - // Don't leave long text in the textarea, since it makes further polling slow - if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = "" } - else { this$1.prevInput = text } - - if (this$1.composing) { - this$1.composing.range.clear() - this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), - {className: "CodeMirror-composing"}) - } - }) - return true -}; - -TextareaInput.prototype.ensurePolled = function () { - if (this.pollingFast && this.poll()) { this.pollingFast = false } -}; - -TextareaInput.prototype.onKeyPress = function () { - if (ie && ie_version >= 9) { this.hasSelection = null } - this.fastPoll() -}; - -TextareaInput.prototype.onContextMenu = function (e) { - var input = this, cm = input.cm, display = cm.display, te = input.textarea - var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop - if (!pos || presto) { return } // Opera is difficult. - - // Reset the current text selection only if the click is done outside of the selection - // and 'resetSelectionOnContextMenu' option is true. - var reset = cm.options.resetSelectionOnContextMenu - if (reset && cm.doc.sel.contains(pos) == -1) - { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) } - - var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText - input.wrapper.style.cssText = "position: absolute" - var wrapperBox = input.wrapper.getBoundingClientRect() - te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);" - var oldScrollY - if (webkit) { oldScrollY = window.scrollY } // Work around Chrome issue (#2712) - display.input.focus() - if (webkit) { window.scrollTo(null, oldScrollY) } - display.input.reset() - // Adds "Select all" to context menu in FF - if (!cm.somethingSelected()) { te.value = input.prevInput = " " } - input.contextMenuPending = true - display.selForContextMenu = cm.doc.sel - clearTimeout(display.detectingSelectAll) - - // Select-all will be greyed out if there's nothing to select, so - // this adds a zero-width space so that we can later check whether - // it got selected. - function prepareSelectAllHack() { - if (te.selectionStart != null) { - var selected = cm.somethingSelected() - var extval = "\u200b" + (selected ? te.value : "") - te.value = "\u21da" // Used to catch context-menu undo - te.value = extval - input.prevInput = selected ? "" : "\u200b" - te.selectionStart = 1; te.selectionEnd = extval.length - // Re-set this, in case some other handler touched the - // selection in the meantime. - display.selForContextMenu = cm.doc.sel - } - } - function rehide() { - input.contextMenuPending = false - input.wrapper.style.cssText = oldWrapperCSS - te.style.cssText = oldCSS - if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) } - - // Try to detect the user choosing select-all - if (te.selectionStart != null) { - if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack() } - var i = 0, poll = function () { - if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && - te.selectionEnd > 0 && input.prevInput == "\u200b") { - operation(cm, selectAll)(cm) - } else if (i++ < 10) { - display.detectingSelectAll = setTimeout(poll, 500) - } else { - display.selForContextMenu = null - display.input.reset() - } - } - display.detectingSelectAll = setTimeout(poll, 200) - } - } - - if (ie && ie_version >= 9) { prepareSelectAllHack() } - if (captureRightClick) { - e_stop(e) - var mouseup = function () { - off(window, "mouseup", mouseup) - setTimeout(rehide, 20) - } - on(window, "mouseup", mouseup) - } else { - setTimeout(rehide, 50) - } -}; - -TextareaInput.prototype.readOnlyChanged = function (val) { - if (!val) { this.reset() } -}; - -TextareaInput.prototype.setUneditable = function () {}; - -TextareaInput.prototype.needsContentAttribute = false - -function fromTextArea(textarea, options) { - options = options ? copyObj(options) : {} - options.value = textarea.value - if (!options.tabindex && textarea.tabIndex) - { options.tabindex = textarea.tabIndex } - if (!options.placeholder && textarea.placeholder) - { options.placeholder = textarea.placeholder } - // Set autofocus to true if this textarea is focused, or if it has - // autofocus and no other element is focused. - if (options.autofocus == null) { - var hasFocus = activeElt() - options.autofocus = hasFocus == textarea || - textarea.getAttribute("autofocus") != null && hasFocus == document.body - } - - function save() {textarea.value = cm.getValue()} - - var realSubmit - if (textarea.form) { - on(textarea.form, "submit", save) - // Deplorable hack to make the submit method do the right thing. - if (!options.leaveSubmitMethodAlone) { - var form = textarea.form - realSubmit = form.submit - try { - var wrappedSubmit = form.submit = function () { - save() - form.submit = realSubmit - form.submit() - form.submit = wrappedSubmit - } - } catch(e) {} - } - } - - options.finishInit = function (cm) { - cm.save = save - cm.getTextArea = function () { return textarea; } - cm.toTextArea = function () { - cm.toTextArea = isNaN // Prevent this from being ran twice - save() - textarea.parentNode.removeChild(cm.getWrapperElement()) - textarea.style.display = "" - if (textarea.form) { - off(textarea.form, "submit", save) - if (typeof textarea.form.submit == "function") - { textarea.form.submit = realSubmit } - } - } - } - - textarea.style.display = "none" - var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, - options) - return cm -} - -function addLegacyProps(CodeMirror) { - CodeMirror.off = off - CodeMirror.on = on - CodeMirror.wheelEventPixels = wheelEventPixels - CodeMirror.Doc = Doc - CodeMirror.splitLines = splitLinesAuto - CodeMirror.countColumn = countColumn - CodeMirror.findColumn = findColumn - CodeMirror.isWordChar = isWordCharBasic - CodeMirror.Pass = Pass - CodeMirror.signal = signal - CodeMirror.Line = Line - CodeMirror.changeEnd = changeEnd - CodeMirror.scrollbarModel = scrollbarModel - CodeMirror.Pos = Pos - CodeMirror.cmpPos = cmp - CodeMirror.modes = modes - CodeMirror.mimeModes = mimeModes - CodeMirror.resolveMode = resolveMode - CodeMirror.getMode = getMode - CodeMirror.modeExtensions = modeExtensions - CodeMirror.extendMode = extendMode - CodeMirror.copyState = copyState - CodeMirror.startState = startState - CodeMirror.innerMode = innerMode - CodeMirror.commands = commands - CodeMirror.keyMap = keyMap - CodeMirror.keyName = keyName - CodeMirror.isModifierKey = isModifierKey - CodeMirror.lookupKey = lookupKey - CodeMirror.normalizeKeyMap = normalizeKeyMap - CodeMirror.StringStream = StringStream - CodeMirror.SharedTextMarker = SharedTextMarker - CodeMirror.TextMarker = TextMarker - CodeMirror.LineWidget = LineWidget - CodeMirror.e_preventDefault = e_preventDefault - CodeMirror.e_stopPropagation = e_stopPropagation - CodeMirror.e_stop = e_stop - CodeMirror.addClass = addClass - CodeMirror.contains = contains - CodeMirror.rmClass = rmClass - CodeMirror.keyNames = keyNames -} - -// EDITOR CONSTRUCTOR - -defineOptions(CodeMirror) - -addEditorMethods(CodeMirror) - -// Set up methods on CodeMirror's prototype to redirect to the editor's document. -var dontDelegate = "iter insert remove copy getEditor constructor".split(" ") -for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) - { CodeMirror.prototype[prop] = (function(method) { - return function() {return method.apply(this.doc, arguments)} - })(Doc.prototype[prop]) } } - -eventMixin(Doc) - -// INPUT HANDLING - -CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput} - -// MODE DEFINITION AND QUERYING - -// Extra arguments are stored as the mode's dependencies, which is -// used by (legacy) mechanisms like loadmode.js to automatically -// load a mode. (Preferred mechanism is the require/define calls.) -CodeMirror.defineMode = function(name/*, mode, …*/) { - if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name } - defineMode.apply(this, arguments) -} - -CodeMirror.defineMIME = defineMIME - -// Minimal default mode. -CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }) -CodeMirror.defineMIME("text/plain", "null") - -// EXTENSIONS - -CodeMirror.defineExtension = function (name, func) { - CodeMirror.prototype[name] = func -} -CodeMirror.defineDocExtension = function (name, func) { - Doc.prototype[name] = func -} - -CodeMirror.fromTextArea = fromTextArea - -addLegacyProps(CodeMirror) - -CodeMirror.version = "5.25.0" - -return CodeMirror; - -}))); \ No newline at end of file diff --git a/vendor/assets/javascripts/markdown.js b/vendor/assets/javascripts/markdown.js deleted file mode 100644 index e649b09..0000000 --- a/vendor/assets/javascripts/markdown.js +++ /dev/null @@ -1,808 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../meta"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { - - var htmlMode = CodeMirror.getMode(cmCfg, "text/html"); - var htmlModeMissing = htmlMode.name == "null" - - function getMode(name) { - if (CodeMirror.findModeByName) { - var found = CodeMirror.findModeByName(name); - if (found) name = found.mime || found.mimes[0]; - } - var mode = CodeMirror.getMode(cmCfg, name); - return mode.name == "null" ? null : mode; - } - - // Should characters that affect highlighting be highlighted separate? - // Does not include characters that will be output (such as `1.` and `-` for lists) - if (modeCfg.highlightFormatting === undefined) - modeCfg.highlightFormatting = false; - - // Maximum number of nested blockquotes. Set to 0 for infinite nesting. - // Excess `>` will emit `error` token. - if (modeCfg.maxBlockquoteDepth === undefined) - modeCfg.maxBlockquoteDepth = 0; - - // Should underscores in words open/close em/strong? - if (modeCfg.underscoresBreakWords === undefined) - modeCfg.underscoresBreakWords = true; - - // Use `fencedCodeBlocks` to configure fenced code blocks. false to - // disable, string to specify a precise regexp that the fence should - // match, and true to allow three or more backticks or tildes (as - // per CommonMark). - - // Turn on task lists? ("- [ ] " and "- [x] ") - if (modeCfg.taskLists === undefined) modeCfg.taskLists = false; - - // Turn on strikethrough syntax - if (modeCfg.strikethrough === undefined) - modeCfg.strikethrough = false; - - // Allow token types to be overridden by user-provided token types. - if (modeCfg.tokenTypeOverrides === undefined) - modeCfg.tokenTypeOverrides = {}; - - var tokenTypes = { - header: "header", - code: "comment", - quote: "quote", - list1: "variable-2", - list2: "variable-3", - list3: "keyword", - hr: "hr", - image: "image", - imageAltText: "image-alt-text", - imageMarker: "image-marker", - formatting: "formatting", - linkInline: "link", - linkEmail: "link", - linkText: "link", - linkHref: "string", - em: "em", - strong: "strong", - strikethrough: "strikethrough" - }; - - for (var tokenType in tokenTypes) { - if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) { - tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType]; - } - } - - var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/ - , listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/ - , taskListRE = /^\[(x| )\](?=\s)/ // Must follow listRE - , atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/ - , setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/ - , textRE = /^[^#!\[\]*_\\<>` "'(~]+/ - , fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) + - ")[ \\t]*([\\w+#\-]*)"); - - function switchInline(stream, state, f) { - state.f = state.inline = f; - return f(stream, state); - } - - function switchBlock(stream, state, f) { - state.f = state.block = f; - return f(stream, state); - } - - function lineIsEmpty(line) { - return !line || !/\S/.test(line.string) - } - - // Blocks - - function blankLine(state) { - // Reset linkTitle state - state.linkTitle = false; - // Reset EM state - state.em = false; - // Reset STRONG state - state.strong = false; - // Reset strikethrough state - state.strikethrough = false; - // Reset state.quote - state.quote = 0; - // Reset state.indentedCode - state.indentedCode = false; - if (state.f == htmlBlock) { - state.f = inlineNormal; - state.block = blockNormal; - } - // Reset state.trailingSpace - state.trailingSpace = 0; - state.trailingSpaceNewLine = false; - // Mark this line as blank - state.prevLine = state.thisLine - state.thisLine = null - return null; - } - - function blockNormal(stream, state) { - - var sol = stream.sol(); - - var prevLineIsList = state.list !== false, - prevLineIsIndentedCode = state.indentedCode; - - state.indentedCode = false; - - if (prevLineIsList) { - if (state.indentationDiff >= 0) { // Continued list - if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block - state.indentation -= state.indentationDiff; - } - state.list = null; - } else if (state.indentation > 0) { - state.list = null; - } else { // No longer a list - state.list = false; - } - } - - var match = null; - if (state.indentationDiff >= 4) { - stream.skipToEnd(); - if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) { - state.indentation -= 4; - state.indentedCode = true; - return tokenTypes.code; - } else { - return null; - } - } else if (stream.eatSpace()) { - return null; - } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) { - state.header = match[1].length; - if (modeCfg.highlightFormatting) state.formatting = "header"; - state.f = state.inline; - return getType(state); - } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList && - !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) { - state.header = match[0].charAt(0) == '=' ? 1 : 2; - if (modeCfg.highlightFormatting) state.formatting = "header"; - state.f = state.inline; - return getType(state); - } else if (stream.eat('>')) { - state.quote = sol ? 1 : state.quote + 1; - if (modeCfg.highlightFormatting) state.formatting = "quote"; - stream.eatSpace(); - return getType(state); - } else if (stream.peek() === '[') { - return switchInline(stream, state, footnoteLink); - } else if (stream.match(hrRE, true)) { - state.hr = true; - return tokenTypes.hr; - } else if (match = stream.match(listRE)) { - var listType = match[1] ? "ol" : "ul"; - state.indentation = stream.column() + stream.current().length; - state.list = true; - - // While this list item's marker's indentation - // is less than the deepest list item's content's indentation, - // pop the deepest list item indentation off the stack. - while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) { - state.listStack.pop(); - } - - // Add this list item's content's indentation to the stack - state.listStack.push(state.indentation); - - if (modeCfg.taskLists && stream.match(taskListRE, false)) { - state.taskList = true; - } - state.f = state.inline; - if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType]; - return getType(state); - } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) { - state.fencedChars = match[1] - // try switching mode - state.localMode = getMode(match[2]); - if (state.localMode) state.localState = CodeMirror.startState(state.localMode); - state.f = state.block = local; - if (modeCfg.highlightFormatting) state.formatting = "code-block"; - state.code = -1 - return getType(state); - } - - return switchInline(stream, state, state.inline); - } - - function htmlBlock(stream, state) { - var style = htmlMode.token(stream, state.htmlState); - if (!htmlModeMissing) { - var inner = CodeMirror.innerMode(htmlMode, state.htmlState) - if ((inner.mode.name == "xml" && inner.state.tagStart === null && - (!inner.state.context && inner.state.tokenize.isInText)) || - (state.md_inside && stream.current().indexOf(">") > -1)) { - state.f = inlineNormal; - state.block = blockNormal; - state.htmlState = null; - } - } - return style; - } - - function local(stream, state) { - if (state.fencedChars && stream.match(state.fencedChars)) { - if (modeCfg.highlightFormatting) state.formatting = "code-block"; - var returnType = getType(state) - state.localMode = state.localState = null; - state.block = blockNormal; - state.f = inlineNormal; - state.fencedChars = null; - state.code = 0 - return returnType; - } else if (state.fencedChars && stream.skipTo(state.fencedChars)) { - return "comment" - } else if (state.localMode) { - return state.localMode.token(stream, state.localState); - } else { - stream.skipToEnd(); - return tokenTypes.code; - } - } - - // Inline - function getType(state) { - var styles = []; - - if (state.formatting) { - styles.push(tokenTypes.formatting); - - if (typeof state.formatting === "string") state.formatting = [state.formatting]; - - for (var i = 0; i < state.formatting.length; i++) { - styles.push(tokenTypes.formatting + "-" + state.formatting[i]); - - if (state.formatting[i] === "header") { - styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header); - } - - // Add `formatting-quote` and `formatting-quote-#` for blockquotes - // Add `error` instead if the maximum blockquote nesting depth is passed - if (state.formatting[i] === "quote") { - if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { - styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote); - } else { - styles.push("error"); - } - } - } - } - - if (state.taskOpen) { - styles.push("meta"); - return styles.length ? styles.join(' ') : null; - } - if (state.taskClosed) { - styles.push("property"); - return styles.length ? styles.join(' ') : null; - } - - if (state.linkHref) { - styles.push(tokenTypes.linkHref, "url"); - } else { // Only apply inline styles to non-url text - if (state.strong) { styles.push(tokenTypes.strong); } - if (state.em) { styles.push(tokenTypes.em); } - if (state.strikethrough) { styles.push(tokenTypes.strikethrough); } - if (state.linkText) { styles.push(tokenTypes.linkText); } - if (state.code) { styles.push(tokenTypes.code); } - if (state.image) { styles.push(tokenTypes.image); } - if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); } - if (state.imageMarker) { styles.push(tokenTypes.imageMarker); } - } - - if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); } - - if (state.quote) { - styles.push(tokenTypes.quote); - - // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth - if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { - styles.push(tokenTypes.quote + "-" + state.quote); - } else { - styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth); - } - } - - if (state.list !== false) { - var listMod = (state.listStack.length - 1) % 3; - if (!listMod) { - styles.push(tokenTypes.list1); - } else if (listMod === 1) { - styles.push(tokenTypes.list2); - } else { - styles.push(tokenTypes.list3); - } - } - - if (state.trailingSpaceNewLine) { - styles.push("trailing-space-new-line"); - } else if (state.trailingSpace) { - styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b")); - } - - return styles.length ? styles.join(' ') : null; - } - - function handleText(stream, state) { - if (stream.match(textRE, true)) { - return getType(state); - } - return undefined; - } - - function inlineNormal(stream, state) { - var style = state.text(stream, state); - if (typeof style !== 'undefined') - return style; - - if (state.list) { // List marker (*, +, -, 1., etc) - state.list = null; - return getType(state); - } - - if (state.taskList) { - var taskOpen = stream.match(taskListRE, true)[1] !== "x"; - if (taskOpen) state.taskOpen = true; - else state.taskClosed = true; - if (modeCfg.highlightFormatting) state.formatting = "task"; - state.taskList = false; - return getType(state); - } - - state.taskOpen = false; - state.taskClosed = false; - - if (state.header && stream.match(/^#+$/, true)) { - if (modeCfg.highlightFormatting) state.formatting = "header"; - return getType(state); - } - - // Get sol() value now, before character is consumed - var sol = stream.sol(); - - var ch = stream.next(); - - // Matches link titles present on next line - if (state.linkTitle) { - state.linkTitle = false; - var matchCh = ch; - if (ch === '(') { - matchCh = ')'; - } - matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh; - if (stream.match(new RegExp(regex), true)) { - return tokenTypes.linkHref; - } - } - - // If this block is changed, it may need to be updated in GFM mode - if (ch === '`') { - var previousFormatting = state.formatting; - if (modeCfg.highlightFormatting) state.formatting = "code"; - stream.eatWhile('`'); - var count = stream.current().length - if (state.code == 0) { - state.code = count - return getType(state) - } else if (count == state.code) { // Must be exact - var t = getType(state) - state.code = 0 - return t - } else { - state.formatting = previousFormatting - return getType(state) - } - } else if (state.code) { - return getType(state); - } - - if (ch === '\\') { - stream.next(); - if (modeCfg.highlightFormatting) { - var type = getType(state); - var formattingEscape = tokenTypes.formatting + "-escape"; - return type ? type + " " + formattingEscape : formattingEscape; - } - } - - if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) { - state.imageMarker = true; - state.image = true; - if (modeCfg.highlightFormatting) state.formatting = "image"; - return getType(state); - } - - if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) { - state.imageMarker = false; - state.imageAltText = true - if (modeCfg.highlightFormatting) state.formatting = "image"; - return getType(state); - } - - if (ch === ']' && state.imageAltText) { - if (modeCfg.highlightFormatting) state.formatting = "image"; - var type = getType(state); - state.imageAltText = false; - state.image = false; - state.inline = state.f = linkHref; - return type; - } - - if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false) && !state.image) { - state.linkText = true; - if (modeCfg.highlightFormatting) state.formatting = "link"; - return getType(state); - } - - if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) { - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - state.linkText = false; - state.inline = state.f = linkHref; - return type; - } - - if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) { - state.f = state.inline = linkInline; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + tokenTypes.linkInline; - } - - if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) { - state.f = state.inline = linkInline; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + tokenTypes.linkEmail; - } - - if (ch === '<' && stream.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i, false)) { - var end = stream.string.indexOf(">", stream.pos); - if (end != -1) { - var atts = stream.string.substring(stream.start, end); - if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true; - } - stream.backUp(1); - state.htmlState = CodeMirror.startState(htmlMode); - return switchBlock(stream, state, htmlBlock); - } - - if (ch === '<' && stream.match(/^\/\w*?>/)) { - state.md_inside = false; - return "tag"; - } - - var ignoreUnderscore = false; - if (!modeCfg.underscoresBreakWords) { - if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) { - var prevPos = stream.pos - 2; - if (prevPos >= 0) { - var prevCh = stream.string.charAt(prevPos); - if (prevCh !== '_' && prevCh.match(/(\w)/, false)) { - ignoreUnderscore = true; - } - } - } - } - if (ch === '*' || (ch === '_' && !ignoreUnderscore)) { - if (sol && stream.peek() === ' ') { - // Do nothing, surrounded by newline and space - } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG - if (modeCfg.highlightFormatting) state.formatting = "strong"; - var t = getType(state); - state.strong = false; - return t; - } else if (!state.strong && stream.eat(ch)) { // Add STRONG - state.strong = ch; - if (modeCfg.highlightFormatting) state.formatting = "strong"; - return getType(state); - } else if (state.em === ch) { // Remove EM - if (modeCfg.highlightFormatting) state.formatting = "em"; - var t = getType(state); - state.em = false; - return t; - } else if (!state.em) { // Add EM - state.em = ch; - if (modeCfg.highlightFormatting) state.formatting = "em"; - return getType(state); - } - } else if (ch === ' ') { - if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces - if (stream.peek() === ' ') { // Surrounded by spaces, ignore - return getType(state); - } else { // Not surrounded by spaces, back up pointer - stream.backUp(1); - } - } - } - - if (modeCfg.strikethrough) { - if (ch === '~' && stream.eatWhile(ch)) { - if (state.strikethrough) {// Remove strikethrough - if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; - var t = getType(state); - state.strikethrough = false; - return t; - } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough - state.strikethrough = true; - if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; - return getType(state); - } - } else if (ch === ' ') { - if (stream.match(/^~~/, true)) { // Probably surrounded by space - if (stream.peek() === ' ') { // Surrounded by spaces, ignore - return getType(state); - } else { // Not surrounded by spaces, back up pointer - stream.backUp(2); - } - } - } - } - - if (ch === ' ') { - if (stream.match(/ +$/, false)) { - state.trailingSpace++; - } else if (state.trailingSpace) { - state.trailingSpaceNewLine = true; - } - } - - return getType(state); - } - - function linkInline(stream, state) { - var ch = stream.next(); - - if (ch === ">") { - state.f = state.inline = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + tokenTypes.linkInline; - } - - stream.match(/^[^>]+/, true); - - return tokenTypes.linkInline; - } - - function linkHref(stream, state) { - // Check if space, and return NULL if so (to avoid marking the space) - if(stream.eatSpace()){ - return null; - } - var ch = stream.next(); - if (ch === '(' || ch === '[') { - state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0); - if (modeCfg.highlightFormatting) state.formatting = "link-string"; - state.linkHref = true; - return getType(state); - } - return 'error'; - } - - var linkRE = { - ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/, - "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/ - } - - function getLinkHrefInside(endChar) { - return function(stream, state) { - var ch = stream.next(); - - if (ch === endChar) { - state.f = state.inline = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "link-string"; - var returnState = getType(state); - state.linkHref = false; - return returnState; - } - - stream.match(linkRE[endChar]) - state.linkHref = true; - return getType(state); - }; - } - - function footnoteLink(stream, state) { - if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) { - state.f = footnoteLinkInside; - stream.next(); // Consume [ - if (modeCfg.highlightFormatting) state.formatting = "link"; - state.linkText = true; - return getType(state); - } - return switchInline(stream, state, inlineNormal); - } - - function footnoteLinkInside(stream, state) { - if (stream.match(/^\]:/, true)) { - state.f = state.inline = footnoteUrl; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var returnType = getType(state); - state.linkText = false; - return returnType; - } - - stream.match(/^([^\]\\]|\\.)+/, true); - - return tokenTypes.linkText; - } - - function footnoteUrl(stream, state) { - // Check if space, and return NULL if so (to avoid marking the space) - if(stream.eatSpace()){ - return null; - } - // Match URL - stream.match(/^[^\s]+/, true); - // Check for link title - if (stream.peek() === undefined) { // End of line, set flag to check next line - state.linkTitle = true; - } else { // More content on line, check if link title - stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true); - } - state.f = state.inline = inlineNormal; - return tokenTypes.linkHref + " url"; - } - - var mode = { - startState: function() { - return { - f: blockNormal, - - prevLine: null, - thisLine: null, - - block: blockNormal, - htmlState: null, - indentation: 0, - - inline: inlineNormal, - text: handleText, - - formatting: false, - linkText: false, - linkHref: false, - linkTitle: false, - code: 0, - em: false, - strong: false, - header: 0, - hr: false, - taskList: false, - list: false, - listStack: [], - quote: 0, - trailingSpace: 0, - trailingSpaceNewLine: false, - strikethrough: false, - fencedChars: null - }; - }, - - copyState: function(s) { - return { - f: s.f, - - prevLine: s.prevLine, - thisLine: s.thisLine, - - block: s.block, - htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), - indentation: s.indentation, - - localMode: s.localMode, - localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, - - inline: s.inline, - text: s.text, - formatting: false, - linkTitle: s.linkTitle, - code: s.code, - em: s.em, - strong: s.strong, - strikethrough: s.strikethrough, - header: s.header, - hr: s.hr, - taskList: s.taskList, - list: s.list, - listStack: s.listStack.slice(0), - quote: s.quote, - indentedCode: s.indentedCode, - trailingSpace: s.trailingSpace, - trailingSpaceNewLine: s.trailingSpaceNewLine, - md_inside: s.md_inside, - fencedChars: s.fencedChars - }; - }, - - token: function(stream, state) { - - // Reset state.formatting - state.formatting = false; - - if (stream != state.thisLine) { - var forceBlankLine = state.header || state.hr; - - // Reset state.header and state.hr - state.header = 0; - state.hr = false; - - if (stream.match(/^\s*$/, true) || forceBlankLine) { - blankLine(state); - if (!forceBlankLine) return null - state.prevLine = null - } - - state.prevLine = state.thisLine - state.thisLine = stream - - // Reset state.taskList - state.taskList = false; - - // Reset state.trailingSpace - state.trailingSpace = 0; - state.trailingSpaceNewLine = false; - - state.f = state.block; - var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length; - state.indentationDiff = Math.min(indentation - state.indentation, 4); - state.indentation = state.indentation + state.indentationDiff; - if (indentation > 0) return null; - } - return state.f(stream, state); - }, - - innerMode: function(state) { - if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; - if (state.localState) return {state: state.localState, mode: state.localMode}; - return {state: state, mode: mode}; - }, - - blankLine: blankLine, - - getType: getType, - - closeBrackets: "()[]{}''\"\"``", - fold: "markdown" - }; - return mode; -}, "xml"); - -CodeMirror.defineMIME("text/x-markdown", "markdown"); - -}); diff --git a/vendor/assets/javascripts/typeahead.js b/vendor/assets/javascripts/typeahead.js deleted file mode 100644 index 0996c9b..0000000 --- a/vendor/assets/javascripts/typeahead.js +++ /dev/null @@ -1,2451 +0,0 @@ -/*! - * typeahead.js 0.11.1 - * https://github.com/twitter/typeahead.js - * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT - */ - -(function(root, factory) { - if (typeof define === "function" && define.amd) { - define("bloodhound", [ "jquery" ], function(a0) { - return root["Bloodhound"] = factory(a0); - }); - } else if (typeof exports === "object") { - module.exports = factory(require("jquery")); - } else { - root["Bloodhound"] = factory(jQuery); - } -})(this, function($) { - var _ = function() { - "use strict"; - return { - isMsie: function() { - return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; - }, - isBlankString: function(str) { - return !str || /^\s*$/.test(str); - }, - escapeRegExChars: function(str) { - return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); - }, - isString: function(obj) { - return typeof obj === "string"; - }, - isNumber: function(obj) { - return typeof obj === "number"; - }, - isArray: $.isArray, - isFunction: $.isFunction, - isObject: $.isPlainObject, - isUndefined: function(obj) { - return typeof obj === "undefined"; - }, - isElement: function(obj) { - return !!(obj && obj.nodeType === 1); - }, - isJQuery: function(obj) { - return obj instanceof $; - }, - toStr: function toStr(s) { - return _.isUndefined(s) || s === null ? "" : s + ""; - }, - bind: $.proxy, - each: function(collection, cb) { - $.each(collection, reverseArgs); - function reverseArgs(index, value) { - return cb(value, index); - } - }, - map: $.map, - filter: $.grep, - every: function(obj, test) { - var result = true; - if (!obj) { - return result; - } - $.each(obj, function(key, val) { - if (!(result = test.call(null, val, key, obj))) { - return false; - } - }); - return !!result; - }, - some: function(obj, test) { - var result = false; - if (!obj) { - return result; - } - $.each(obj, function(key, val) { - if (result = test.call(null, val, key, obj)) { - return false; - } - }); - return !!result; - }, - mixin: $.extend, - identity: function(x) { - return x; - }, - clone: function(obj) { - return $.extend(true, {}, obj); - }, - getIdGenerator: function() { - var counter = 0; - return function() { - return counter++; - }; - }, - templatify: function templatify(obj) { - return $.isFunction(obj) ? obj : template; - function template() { - return String(obj); - } - }, - defer: function(fn) { - setTimeout(fn, 0); - }, - debounce: function(func, wait, immediate) { - var timeout, result; - return function() { - var context = this, args = arguments, later, callNow; - later = function() { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - } - }; - callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - } - return result; - }; - }, - throttle: function(func, wait) { - var context, args, timeout, result, previous, later; - previous = 0; - later = function() { - previous = new Date(); - timeout = null; - result = func.apply(context, args); - }; - return function() { - var now = new Date(), remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = func.apply(context, args); - } else if (!timeout) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }, - stringify: function(val) { - return _.isString(val) ? val : JSON.stringify(val); - }, - noop: function() {} - }; - }(); - var VERSION = "0.11.1"; - var tokenizers = function() { - "use strict"; - return { - nonword: nonword, - whitespace: whitespace, - obj: { - nonword: getObjTokenizer(nonword), - whitespace: getObjTokenizer(whitespace) - } - }; - function whitespace(str) { - str = _.toStr(str); - return str ? str.split(/\s+/) : []; - } - function nonword(str) { - str = _.toStr(str); - return str ? str.split(/\W+/) : []; - } - function getObjTokenizer(tokenizer) { - return function setKey(keys) { - keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0); - return function tokenize(o) { - var tokens = []; - _.each(keys, function(k) { - tokens = tokens.concat(tokenizer(_.toStr(o[k]))); - }); - return tokens; - }; - }; - } - }(); - var LruCache = function() { - "use strict"; - function LruCache(maxSize) { - this.maxSize = _.isNumber(maxSize) ? maxSize : 100; - this.reset(); - if (this.maxSize <= 0) { - this.set = this.get = $.noop; - } - } - _.mixin(LruCache.prototype, { - set: function set(key, val) { - var tailItem = this.list.tail, node; - if (this.size >= this.maxSize) { - this.list.remove(tailItem); - delete this.hash[tailItem.key]; - this.size--; - } - if (node = this.hash[key]) { - node.val = val; - this.list.moveToFront(node); - } else { - node = new Node(key, val); - this.list.add(node); - this.hash[key] = node; - this.size++; - } - }, - get: function get(key) { - var node = this.hash[key]; - if (node) { - this.list.moveToFront(node); - return node.val; - } - }, - reset: function reset() { - this.size = 0; - this.hash = {}; - this.list = new List(); - } - }); - function List() { - this.head = this.tail = null; - } - _.mixin(List.prototype, { - add: function add(node) { - if (this.head) { - node.next = this.head; - this.head.prev = node; - } - this.head = node; - this.tail = this.tail || node; - }, - remove: function remove(node) { - node.prev ? node.prev.next = node.next : this.head = node.next; - node.next ? node.next.prev = node.prev : this.tail = node.prev; - }, - moveToFront: function(node) { - this.remove(node); - this.add(node); - } - }); - function Node(key, val) { - this.key = key; - this.val = val; - this.prev = this.next = null; - } - return LruCache; - }(); - var PersistentStorage = function() { - "use strict"; - var LOCAL_STORAGE; - try { - LOCAL_STORAGE = window.localStorage; - LOCAL_STORAGE.setItem("~~~", "!"); - LOCAL_STORAGE.removeItem("~~~"); - } catch (err) { - LOCAL_STORAGE = null; - } - function PersistentStorage(namespace, override) { - this.prefix = [ "__", namespace, "__" ].join(""); - this.ttlKey = "__ttl__"; - this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix)); - this.ls = override || LOCAL_STORAGE; - !this.ls && this._noop(); - } - _.mixin(PersistentStorage.prototype, { - _prefix: function(key) { - return this.prefix + key; - }, - _ttlKey: function(key) { - return this._prefix(key) + this.ttlKey; - }, - _noop: function() { - this.get = this.set = this.remove = this.clear = this.isExpired = _.noop; - }, - _safeSet: function(key, val) { - try { - this.ls.setItem(key, val); - } catch (err) { - if (err.name === "QuotaExceededError") { - this.clear(); - this._noop(); - } - } - }, - get: function(key) { - if (this.isExpired(key)) { - this.remove(key); - } - return decode(this.ls.getItem(this._prefix(key))); - }, - set: function(key, val, ttl) { - if (_.isNumber(ttl)) { - this._safeSet(this._ttlKey(key), encode(now() + ttl)); - } else { - this.ls.removeItem(this._ttlKey(key)); - } - return this._safeSet(this._prefix(key), encode(val)); - }, - remove: function(key) { - this.ls.removeItem(this._ttlKey(key)); - this.ls.removeItem(this._prefix(key)); - return this; - }, - clear: function() { - var i, keys = gatherMatchingKeys(this.keyMatcher); - for (i = keys.length; i--; ) { - this.remove(keys[i]); - } - return this; - }, - isExpired: function(key) { - var ttl = decode(this.ls.getItem(this._ttlKey(key))); - return _.isNumber(ttl) && now() > ttl ? true : false; - } - }); - return PersistentStorage; - function now() { - return new Date().getTime(); - } - function encode(val) { - return JSON.stringify(_.isUndefined(val) ? null : val); - } - function decode(val) { - return $.parseJSON(val); - } - function gatherMatchingKeys(keyMatcher) { - var i, key, keys = [], len = LOCAL_STORAGE.length; - for (i = 0; i < len; i++) { - if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) { - keys.push(key.replace(keyMatcher, "")); - } - } - return keys; - } - }(); - var Transport = function() { - "use strict"; - var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10); - function Transport(o) { - o = o || {}; - this.cancelled = false; - this.lastReq = null; - this._send = o.transport; - this._get = o.limiter ? o.limiter(this._get) : this._get; - this._cache = o.cache === false ? new LruCache(0) : sharedCache; - } - Transport.setMaxPendingRequests = function setMaxPendingRequests(num) { - maxPendingRequests = num; - }; - Transport.resetCache = function resetCache() { - sharedCache.reset(); - }; - _.mixin(Transport.prototype, { - _fingerprint: function fingerprint(o) { - o = o || {}; - return o.url + o.type + $.param(o.data || {}); - }, - _get: function(o, cb) { - var that = this, fingerprint, jqXhr; - fingerprint = this._fingerprint(o); - if (this.cancelled || fingerprint !== this.lastReq) { - return; - } - if (jqXhr = pendingRequests[fingerprint]) { - jqXhr.done(done).fail(fail); - } else if (pendingRequestsCount < maxPendingRequests) { - pendingRequestsCount++; - pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always); - } else { - this.onDeckRequestArgs = [].slice.call(arguments, 0); - } - function done(resp) { - cb(null, resp); - that._cache.set(fingerprint, resp); - } - function fail() { - cb(true); - } - function always() { - pendingRequestsCount--; - delete pendingRequests[fingerprint]; - if (that.onDeckRequestArgs) { - that._get.apply(that, that.onDeckRequestArgs); - that.onDeckRequestArgs = null; - } - } - }, - get: function(o, cb) { - var resp, fingerprint; - cb = cb || $.noop; - o = _.isString(o) ? { - url: o - } : o || {}; - fingerprint = this._fingerprint(o); - this.cancelled = false; - this.lastReq = fingerprint; - if (resp = this._cache.get(fingerprint)) { - cb(null, resp); - } else { - this._get(o, cb); - } - }, - cancel: function() { - this.cancelled = true; - } - }); - return Transport; - }(); - var SearchIndex = window.SearchIndex = function() { - "use strict"; - var CHILDREN = "c", IDS = "i"; - function SearchIndex(o) { - o = o || {}; - if (!o.datumTokenizer || !o.queryTokenizer) { - $.error("datumTokenizer and queryTokenizer are both required"); - } - this.identify = o.identify || _.stringify; - this.datumTokenizer = o.datumTokenizer; - this.queryTokenizer = o.queryTokenizer; - this.reset(); - } - _.mixin(SearchIndex.prototype, { - bootstrap: function bootstrap(o) { - this.datums = o.datums; - this.trie = o.trie; - }, - add: function(data) { - var that = this; - data = _.isArray(data) ? data : [ data ]; - _.each(data, function(datum) { - var id, tokens; - that.datums[id = that.identify(datum)] = datum; - tokens = normalizeTokens(that.datumTokenizer(datum)); - _.each(tokens, function(token) { - var node, chars, ch; - node = that.trie; - chars = token.split(""); - while (ch = chars.shift()) { - node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode()); - node[IDS].push(id); - } - }); - }); - }, - get: function get(ids) { - var that = this; - return _.map(ids, function(id) { - return that.datums[id]; - }); - }, - search: function search(query) { - var that = this, tokens, matches; - tokens = normalizeTokens(this.queryTokenizer(query)); - _.each(tokens, function(token) { - var node, chars, ch, ids; - if (matches && matches.length === 0) { - return false; - } - node = that.trie; - chars = token.split(""); - while (node && (ch = chars.shift())) { - node = node[CHILDREN][ch]; - } - if (node && chars.length === 0) { - ids = node[IDS].slice(0); - matches = matches ? getIntersection(matches, ids) : ids; - } else { - matches = []; - return false; - } - }); - return matches ? _.map(unique(matches), function(id) { - return that.datums[id]; - }) : []; - }, - all: function all() { - var values = []; - for (var key in this.datums) { - values.push(this.datums[key]); - } - return values; - }, - reset: function reset() { - this.datums = {}; - this.trie = newNode(); - }, - serialize: function serialize() { - return { - datums: this.datums, - trie: this.trie - }; - } - }); - return SearchIndex; - function normalizeTokens(tokens) { - tokens = _.filter(tokens, function(token) { - return !!token; - }); - tokens = _.map(tokens, function(token) { - return token.toLowerCase(); - }); - return tokens; - } - function newNode() { - var node = {}; - node[IDS] = []; - node[CHILDREN] = {}; - return node; - } - function unique(array) { - var seen = {}, uniques = []; - for (var i = 0, len = array.length; i < len; i++) { - if (!seen[array[i]]) { - seen[array[i]] = true; - uniques.push(array[i]); - } - } - return uniques; - } - function getIntersection(arrayA, arrayB) { - var ai = 0, bi = 0, intersection = []; - arrayA = arrayA.sort(); - arrayB = arrayB.sort(); - var lenArrayA = arrayA.length, lenArrayB = arrayB.length; - while (ai < lenArrayA && bi < lenArrayB) { - if (arrayA[ai] < arrayB[bi]) { - ai++; - } else if (arrayA[ai] > arrayB[bi]) { - bi++; - } else { - intersection.push(arrayA[ai]); - ai++; - bi++; - } - } - return intersection; - } - }(); - var Prefetch = function() { - "use strict"; - var keys; - keys = { - data: "data", - protocol: "protocol", - thumbprint: "thumbprint" - }; - function Prefetch(o) { - this.url = o.url; - this.ttl = o.ttl; - this.cache = o.cache; - this.prepare = o.prepare; - this.transform = o.transform; - this.transport = o.transport; - this.thumbprint = o.thumbprint; - this.storage = new PersistentStorage(o.cacheKey); - } - _.mixin(Prefetch.prototype, { - _settings: function settings() { - return { - url: this.url, - type: "GET", - dataType: "json" - }; - }, - store: function store(data) { - if (!this.cache) { - return; - } - this.storage.set(keys.data, data, this.ttl); - this.storage.set(keys.protocol, location.protocol, this.ttl); - this.storage.set(keys.thumbprint, this.thumbprint, this.ttl); - }, - fromCache: function fromCache() { - var stored = {}, isExpired; - if (!this.cache) { - return null; - } - stored.data = this.storage.get(keys.data); - stored.protocol = this.storage.get(keys.protocol); - stored.thumbprint = this.storage.get(keys.thumbprint); - isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol; - return stored.data && !isExpired ? stored.data : null; - }, - fromNetwork: function(cb) { - var that = this, settings; - if (!cb) { - return; - } - settings = this.prepare(this._settings()); - this.transport(settings).fail(onError).done(onResponse); - function onError() { - cb(true); - } - function onResponse(resp) { - cb(null, that.transform(resp)); - } - }, - clear: function clear() { - this.storage.clear(); - return this; - } - }); - return Prefetch; - }(); - var Remote = function() { - "use strict"; - function Remote(o) { - this.url = o.url; - this.prepare = o.prepare; - this.transform = o.transform; - this.transport = new Transport({ - cache: o.cache, - limiter: o.limiter, - transport: o.transport - }); - } - _.mixin(Remote.prototype, { - _settings: function settings() { - return { - url: this.url, - type: "GET", - dataType: "json" - }; - }, - get: function get(query, cb) { - var that = this, settings; - if (!cb) { - return; - } - query = query || ""; - settings = this.prepare(query, this._settings()); - return this.transport.get(settings, onResponse); - function onResponse(err, resp) { - err ? cb([]) : cb(that.transform(resp)); - } - }, - cancelLastRequest: function cancelLastRequest() { - this.transport.cancel(); - } - }); - return Remote; - }(); - var oParser = function() { - "use strict"; - return function parse(o) { - var defaults, sorter; - defaults = { - initialize: true, - identify: _.stringify, - datumTokenizer: null, - queryTokenizer: null, - sufficient: 5, - sorter: null, - local: [], - prefetch: null, - remote: null - }; - o = _.mixin(defaults, o || {}); - !o.datumTokenizer && $.error("datumTokenizer is required"); - !o.queryTokenizer && $.error("queryTokenizer is required"); - sorter = o.sorter; - o.sorter = sorter ? function(x) { - return x.sort(sorter); - } : _.identity; - o.local = _.isFunction(o.local) ? o.local() : o.local; - o.prefetch = parsePrefetch(o.prefetch); - o.remote = parseRemote(o.remote); - return o; - }; - function parsePrefetch(o) { - var defaults; - if (!o) { - return null; - } - defaults = { - url: null, - ttl: 24 * 60 * 60 * 1e3, - cache: true, - cacheKey: null, - thumbprint: "", - prepare: _.identity, - transform: _.identity, - transport: null - }; - o = _.isString(o) ? { - url: o - } : o; - o = _.mixin(defaults, o); - !o.url && $.error("prefetch requires url to be set"); - o.transform = o.filter || o.transform; - o.cacheKey = o.cacheKey || o.url; - o.thumbprint = VERSION + o.thumbprint; - o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; - return o; - } - function parseRemote(o) { - var defaults; - if (!o) { - return; - } - defaults = { - url: null, - cache: true, - prepare: null, - replace: null, - wildcard: null, - limiter: null, - rateLimitBy: "debounce", - rateLimitWait: 300, - transform: _.identity, - transport: null - }; - o = _.isString(o) ? { - url: o - } : o; - o = _.mixin(defaults, o); - !o.url && $.error("remote requires url to be set"); - o.transform = o.filter || o.transform; - o.prepare = toRemotePrepare(o); - o.limiter = toLimiter(o); - o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; - delete o.replace; - delete o.wildcard; - delete o.rateLimitBy; - delete o.rateLimitWait; - return o; - } - function toRemotePrepare(o) { - var prepare, replace, wildcard; - prepare = o.prepare; - replace = o.replace; - wildcard = o.wildcard; - if (prepare) { - return prepare; - } - if (replace) { - prepare = prepareByReplace; - } else if (o.wildcard) { - prepare = prepareByWildcard; - } else { - prepare = idenityPrepare; - } - return prepare; - function prepareByReplace(query, settings) { - settings.url = replace(settings.url, query); - return settings; - } - function prepareByWildcard(query, settings) { - settings.url = settings.url.replace(wildcard, encodeURIComponent(query)); - return settings; - } - function idenityPrepare(query, settings) { - return settings; - } - } - function toLimiter(o) { - var limiter, method, wait; - limiter = o.limiter; - method = o.rateLimitBy; - wait = o.rateLimitWait; - if (!limiter) { - limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait); - } - return limiter; - function debounce(wait) { - return function debounce(fn) { - return _.debounce(fn, wait); - }; - } - function throttle(wait) { - return function throttle(fn) { - return _.throttle(fn, wait); - }; - } - } - function callbackToDeferred(fn) { - return function wrapper(o) { - var deferred = $.Deferred(); - fn(o, onSuccess, onError); - return deferred; - function onSuccess(resp) { - _.defer(function() { - deferred.resolve(resp); - }); - } - function onError(err) { - _.defer(function() { - deferred.reject(err); - }); - } - }; - } - }(); - var Bloodhound = function() { - "use strict"; - var old; - old = window && window.Bloodhound; - function Bloodhound(o) { - o = oParser(o); - this.sorter = o.sorter; - this.identify = o.identify; - this.sufficient = o.sufficient; - this.local = o.local; - this.remote = o.remote ? new Remote(o.remote) : null; - this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null; - this.index = new SearchIndex({ - identify: this.identify, - datumTokenizer: o.datumTokenizer, - queryTokenizer: o.queryTokenizer - }); - o.initialize !== false && this.initialize(); - } - Bloodhound.noConflict = function noConflict() { - window && (window.Bloodhound = old); - return Bloodhound; - }; - Bloodhound.tokenizers = tokenizers; - _.mixin(Bloodhound.prototype, { - __ttAdapter: function ttAdapter() { - var that = this; - return this.remote ? withAsync : withoutAsync; - function withAsync(query, sync, async) { - return that.search(query, sync, async); - } - function withoutAsync(query, sync) { - return that.search(query, sync); - } - }, - _loadPrefetch: function loadPrefetch() { - var that = this, deferred, serialized; - deferred = $.Deferred(); - if (!this.prefetch) { - deferred.resolve(); - } else if (serialized = this.prefetch.fromCache()) { - this.index.bootstrap(serialized); - deferred.resolve(); - } else { - this.prefetch.fromNetwork(done); - } - return deferred.promise(); - function done(err, data) { - if (err) { - return deferred.reject(); - } - that.add(data); - that.prefetch.store(that.index.serialize()); - deferred.resolve(); - } - }, - _initialize: function initialize() { - var that = this, deferred; - this.clear(); - (this.initPromise = this._loadPrefetch()).done(addLocalToIndex); - return this.initPromise; - function addLocalToIndex() { - that.add(that.local); - } - }, - initialize: function initialize(force) { - return !this.initPromise || force ? this._initialize() : this.initPromise; - }, - add: function add(data) { - this.index.add(data); - return this; - }, - get: function get(ids) { - ids = _.isArray(ids) ? ids : [].slice.call(arguments); - return this.index.get(ids); - }, - search: function search(query, sync, async) { - var that = this, local; - local = this.sorter(this.index.search(query)); - sync(this.remote ? local.slice() : local); - if (this.remote && local.length < this.sufficient) { - this.remote.get(query, processRemote); - } else if (this.remote) { - this.remote.cancelLastRequest(); - } - return this; - function processRemote(remote) { - var nonDuplicates = []; - _.each(remote, function(r) { - !_.some(local, function(l) { - return that.identify(r) === that.identify(l); - }) && nonDuplicates.push(r); - }); - async && async(nonDuplicates); - } - }, - all: function all() { - return this.index.all(); - }, - clear: function clear() { - this.index.reset(); - return this; - }, - clearPrefetchCache: function clearPrefetchCache() { - this.prefetch && this.prefetch.clear(); - return this; - }, - clearRemoteCache: function clearRemoteCache() { - Transport.resetCache(); - return this; - }, - ttAdapter: function ttAdapter() { - return this.__ttAdapter(); - } - }); - return Bloodhound; - }(); - return Bloodhound; -}); - -(function(root, factory) { - if (typeof define === "function" && define.amd) { - define("typeahead.js", [ "jquery" ], function(a0) { - return factory(a0); - }); - } else if (typeof exports === "object") { - module.exports = factory(require("jquery")); - } else { - factory(jQuery); - } -})(this, function($) { - var _ = function() { - "use strict"; - return { - isMsie: function() { - return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; - }, - isBlankString: function(str) { - return !str || /^\s*$/.test(str); - }, - escapeRegExChars: function(str) { - return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); - }, - isString: function(obj) { - return typeof obj === "string"; - }, - isNumber: function(obj) { - return typeof obj === "number"; - }, - isArray: $.isArray, - isFunction: $.isFunction, - isObject: $.isPlainObject, - isUndefined: function(obj) { - return typeof obj === "undefined"; - }, - isElement: function(obj) { - return !!(obj && obj.nodeType === 1); - }, - isJQuery: function(obj) { - return obj instanceof $; - }, - toStr: function toStr(s) { - return _.isUndefined(s) || s === null ? "" : s + ""; - }, - bind: $.proxy, - each: function(collection, cb) { - $.each(collection, reverseArgs); - function reverseArgs(index, value) { - return cb(value, index); - } - }, - map: $.map, - filter: $.grep, - every: function(obj, test) { - var result = true; - if (!obj) { - return result; - } - $.each(obj, function(key, val) { - if (!(result = test.call(null, val, key, obj))) { - return false; - } - }); - return !!result; - }, - some: function(obj, test) { - var result = false; - if (!obj) { - return result; - } - $.each(obj, function(key, val) { - if (result = test.call(null, val, key, obj)) { - return false; - } - }); - return !!result; - }, - mixin: $.extend, - identity: function(x) { - return x; - }, - clone: function(obj) { - return $.extend(true, {}, obj); - }, - getIdGenerator: function() { - var counter = 0; - return function() { - return counter++; - }; - }, - templatify: function templatify(obj) { - return $.isFunction(obj) ? obj : template; - function template() { - return String(obj); - } - }, - defer: function(fn) { - setTimeout(fn, 0); - }, - debounce: function(func, wait, immediate) { - var timeout, result; - return function() { - var context = this, args = arguments, later, callNow; - later = function() { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - } - }; - callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - } - return result; - }; - }, - throttle: function(func, wait) { - var context, args, timeout, result, previous, later; - previous = 0; - later = function() { - previous = new Date(); - timeout = null; - result = func.apply(context, args); - }; - return function() { - var now = new Date(), remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = func.apply(context, args); - } else if (!timeout) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }, - stringify: function(val) { - return _.isString(val) ? val : JSON.stringify(val); - }, - noop: function() {} - }; - }(); - var WWW = function() { - "use strict"; - var defaultClassNames = { - wrapper: "twitter-typeahead", - input: "tt-input", - hint: "tt-hint", - menu: "tt-menu", - dataset: "tt-dataset", - suggestion: "tt-suggestion", - selectable: "tt-selectable", - empty: "tt-empty", - open: "tt-open", - cursor: "tt-cursor", - highlight: "tt-highlight" - }; - return build; - function build(o) { - var www, classes; - classes = _.mixin({}, defaultClassNames, o); - www = { - css: buildCss(), - classes: classes, - html: buildHtml(classes), - selectors: buildSelectors(classes) - }; - return { - css: www.css, - html: www.html, - classes: www.classes, - selectors: www.selectors, - mixin: function(o) { - _.mixin(o, www); - } - }; - } - function buildHtml(c) { - return { - wrapper: '', - menu: '
      ' - }; - } - function buildSelectors(classes) { - var selectors = {}; - _.each(classes, function(v, k) { - selectors[k] = "." + v; - }); - return selectors; - } - function buildCss() { - var css = { - wrapper: { - position: "relative", - display: "inline-block" - }, - hint: { - position: "absolute", - top: "0", - left: "0", - borderColor: "transparent", - boxShadow: "none", - opacity: "1" - }, - input: { - position: "relative", - verticalAlign: "top", - backgroundColor: "transparent" - }, - inputWithNoHint: { - position: "relative", - verticalAlign: "top" - }, - menu: { - position: "absolute", - top: "100%", - left: "0", - zIndex: "100", - display: "none" - }, - ltr: { - left: "0", - right: "auto" - }, - rtl: { - left: "auto", - right: " 0" - } - }; - if (_.isMsie()) { - _.mixin(css.input, { - backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" - }); - } - return css; - } - }(); - var EventBus = function() { - "use strict"; - var namespace, deprecationMap; - namespace = "typeahead:"; - deprecationMap = { - render: "rendered", - cursorchange: "cursorchanged", - select: "selected", - autocomplete: "autocompleted" - }; - function EventBus(o) { - if (!o || !o.el) { - $.error("EventBus initialized without el"); - } - this.$el = $(o.el); - } - _.mixin(EventBus.prototype, { - _trigger: function(type, args) { - var $e; - $e = $.Event(namespace + type); - (args = args || []).unshift($e); - this.$el.trigger.apply(this.$el, args); - return $e; - }, - before: function(type) { - var args, $e; - args = [].slice.call(arguments, 1); - $e = this._trigger("before" + type, args); - return $e.isDefaultPrevented(); - }, - trigger: function(type) { - var deprecatedType; - this._trigger(type, [].slice.call(arguments, 1)); - if (deprecatedType = deprecationMap[type]) { - this._trigger(deprecatedType, [].slice.call(arguments, 1)); - } - } - }); - return EventBus; - }(); - var EventEmitter = function() { - "use strict"; - var splitter = /\s+/, nextTick = getNextTick(); - return { - onSync: onSync, - onAsync: onAsync, - off: off, - trigger: trigger - }; - function on(method, types, cb, context) { - var type; - if (!cb) { - return this; - } - types = types.split(splitter); - cb = context ? bindContext(cb, context) : cb; - this._callbacks = this._callbacks || {}; - while (type = types.shift()) { - this._callbacks[type] = this._callbacks[type] || { - sync: [], - async: [] - }; - this._callbacks[type][method].push(cb); - } - return this; - } - function onAsync(types, cb, context) { - return on.call(this, "async", types, cb, context); - } - function onSync(types, cb, context) { - return on.call(this, "sync", types, cb, context); - } - function off(types) { - var type; - if (!this._callbacks) { - return this; - } - types = types.split(splitter); - while (type = types.shift()) { - delete this._callbacks[type]; - } - return this; - } - function trigger(types) { - var type, callbacks, args, syncFlush, asyncFlush; - if (!this._callbacks) { - return this; - } - types = types.split(splitter); - args = [].slice.call(arguments, 1); - while ((type = types.shift()) && (callbacks = this._callbacks[type])) { - syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); - asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); - syncFlush() && nextTick(asyncFlush); - } - return this; - } - function getFlush(callbacks, context, args) { - return flush; - function flush() { - var cancelled; - for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { - cancelled = callbacks[i].apply(context, args) === false; - } - return !cancelled; - } - } - function getNextTick() { - var nextTickFn; - if (window.setImmediate) { - nextTickFn = function nextTickSetImmediate(fn) { - setImmediate(function() { - fn(); - }); - }; - } else { - nextTickFn = function nextTickSetTimeout(fn) { - setTimeout(function() { - fn(); - }, 0); - }; - } - return nextTickFn; - } - function bindContext(fn, context) { - return fn.bind ? fn.bind(context) : function() { - fn.apply(context, [].slice.call(arguments, 0)); - }; - } - }(); - var highlight = function(doc) { - "use strict"; - var defaults = { - node: null, - pattern: null, - tagName: "strong", - className: null, - wordsOnly: false, - caseSensitive: false - }; - return function hightlight(o) { - var regex; - o = _.mixin({}, defaults, o); - if (!o.node || !o.pattern) { - return; - } - o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; - regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); - traverse(o.node, hightlightTextNode); - function hightlightTextNode(textNode) { - var match, patternNode, wrapperNode; - if (match = regex.exec(textNode.data)) { - wrapperNode = doc.createElement(o.tagName); - o.className && (wrapperNode.className = o.className); - patternNode = textNode.splitText(match.index); - patternNode.splitText(match[0].length); - wrapperNode.appendChild(patternNode.cloneNode(true)); - textNode.parentNode.replaceChild(wrapperNode, patternNode); - } - return !!match; - } - function traverse(el, hightlightTextNode) { - var childNode, TEXT_NODE_TYPE = 3; - for (var i = 0; i < el.childNodes.length; i++) { - childNode = el.childNodes[i]; - if (childNode.nodeType === TEXT_NODE_TYPE) { - i += hightlightTextNode(childNode) ? 1 : 0; - } else { - traverse(childNode, hightlightTextNode); - } - } - } - }; - function getRegex(patterns, caseSensitive, wordsOnly) { - var escapedPatterns = [], regexStr; - for (var i = 0, len = patterns.length; i < len; i++) { - escapedPatterns.push(_.escapeRegExChars(patterns[i])); - } - regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; - return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); - } - }(window.document); - var Input = function() { - "use strict"; - var specialKeyCodeMap; - specialKeyCodeMap = { - 9: "tab", - 27: "esc", - 37: "left", - 39: "right", - 13: "enter", - 38: "up", - 40: "down" - }; - function Input(o, www) { - o = o || {}; - if (!o.input) { - $.error("input is missing"); - } - www.mixin(this); - this.$hint = $(o.hint); - this.$input = $(o.input); - this.query = this.$input.val(); - this.queryWhenFocused = this.hasFocus() ? this.query : null; - this.$overflowHelper = buildOverflowHelper(this.$input); - this._checkLanguageDirection(); - if (this.$hint.length === 0) { - this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; - } - } - Input.normalizeQuery = function(str) { - return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); - }; - _.mixin(Input.prototype, EventEmitter, { - _onBlur: function onBlur() { - this.resetInputValue(); - this.trigger("blurred"); - }, - _onFocus: function onFocus() { - this.queryWhenFocused = this.query; - this.trigger("focused"); - }, - _onKeydown: function onKeydown($e) { - var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; - this._managePreventDefault(keyName, $e); - if (keyName && this._shouldTrigger(keyName, $e)) { - this.trigger(keyName + "Keyed", $e); - } - }, - _onInput: function onInput() { - this._setQuery(this.getInputValue()); - this.clearHintIfInvalid(); - this._checkLanguageDirection(); - }, - _managePreventDefault: function managePreventDefault(keyName, $e) { - var preventDefault; - switch (keyName) { - case "up": - case "down": - preventDefault = !withModifier($e); - break; - - default: - preventDefault = false; - } - preventDefault && $e.preventDefault(); - }, - _shouldTrigger: function shouldTrigger(keyName, $e) { - var trigger; - switch (keyName) { - case "tab": - trigger = !withModifier($e); - break; - - default: - trigger = true; - } - return trigger; - }, - _checkLanguageDirection: function checkLanguageDirection() { - var dir = (this.$input.css("direction") || "ltr").toLowerCase(); - if (this.dir !== dir) { - this.dir = dir; - this.$hint.attr("dir", dir); - this.trigger("langDirChanged", dir); - } - }, - _setQuery: function setQuery(val, silent) { - var areEquivalent, hasDifferentWhitespace; - areEquivalent = areQueriesEquivalent(val, this.query); - hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; - this.query = val; - if (!silent && !areEquivalent) { - this.trigger("queryChanged", this.query); - } else if (!silent && hasDifferentWhitespace) { - this.trigger("whitespaceChanged", this.query); - } - }, - bind: function() { - var that = this, onBlur, onFocus, onKeydown, onInput; - onBlur = _.bind(this._onBlur, this); - onFocus = _.bind(this._onFocus, this); - onKeydown = _.bind(this._onKeydown, this); - onInput = _.bind(this._onInput, this); - this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); - if (!_.isMsie() || _.isMsie() > 9) { - this.$input.on("input.tt", onInput); - } else { - this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { - if (specialKeyCodeMap[$e.which || $e.keyCode]) { - return; - } - _.defer(_.bind(that._onInput, that, $e)); - }); - } - return this; - }, - focus: function focus() { - this.$input.focus(); - }, - blur: function blur() { - this.$input.blur(); - }, - getLangDir: function getLangDir() { - return this.dir; - }, - getQuery: function getQuery() { - return this.query || ""; - }, - setQuery: function setQuery(val, silent) { - this.setInputValue(val); - this._setQuery(val, silent); - }, - hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { - return this.query !== this.queryWhenFocused; - }, - getInputValue: function getInputValue() { - return this.$input.val(); - }, - setInputValue: function setInputValue(value) { - this.$input.val(value); - this.clearHintIfInvalid(); - this._checkLanguageDirection(); - }, - resetInputValue: function resetInputValue() { - this.setInputValue(this.query); - }, - getHint: function getHint() { - return this.$hint.val(); - }, - setHint: function setHint(value) { - this.$hint.val(value); - }, - clearHint: function clearHint() { - this.setHint(""); - }, - clearHintIfInvalid: function clearHintIfInvalid() { - var val, hint, valIsPrefixOfHint, isValid; - val = this.getInputValue(); - hint = this.getHint(); - valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; - isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); - !isValid && this.clearHint(); - }, - hasFocus: function hasFocus() { - return this.$input.is(":focus"); - }, - hasOverflow: function hasOverflow() { - var constraint = this.$input.width() - 2; - this.$overflowHelper.text(this.getInputValue()); - return this.$overflowHelper.width() >= constraint; - }, - isCursorAtEnd: function() { - var valueLength, selectionStart, range; - valueLength = this.$input.val().length; - selectionStart = this.$input[0].selectionStart; - if (_.isNumber(selectionStart)) { - return selectionStart === valueLength; - } else if (document.selection) { - range = document.selection.createRange(); - range.moveStart("character", -valueLength); - return valueLength === range.text.length; - } - return true; - }, - destroy: function destroy() { - this.$hint.off(".tt"); - this.$input.off(".tt"); - this.$overflowHelper.remove(); - this.$hint = this.$input = this.$overflowHelper = $("
      "); - } - }); - return Input; - function buildOverflowHelper($input) { - return $('').css({ - position: "absolute", - visibility: "hidden", - whiteSpace: "pre", - fontFamily: $input.css("font-family"), - fontSize: $input.css("font-size"), - fontStyle: $input.css("font-style"), - fontVariant: $input.css("font-variant"), - fontWeight: $input.css("font-weight"), - wordSpacing: $input.css("word-spacing"), - letterSpacing: $input.css("letter-spacing"), - textIndent: $input.css("text-indent"), - textRendering: $input.css("text-rendering"), - textTransform: $input.css("text-transform") - }).insertAfter($input); - } - function areQueriesEquivalent(a, b) { - return Input.normalizeQuery(a) === Input.normalizeQuery(b); - } - function withModifier($e) { - return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; - } - }(); - var Dataset = function() { - "use strict"; - var keys, nameGenerator; - keys = { - val: "tt-selectable-display", - obj: "tt-selectable-object" - }; - nameGenerator = _.getIdGenerator(); - function Dataset(o, www) { - o = o || {}; - o.templates = o.templates || {}; - o.templates.notFound = o.templates.notFound || o.templates.empty; - if (!o.source) { - $.error("missing source"); - } - if (!o.node) { - $.error("missing node"); - } - if (o.name && !isValidName(o.name)) { - $.error("invalid dataset name: " + o.name); - } - www.mixin(this); - this.highlight = !!o.highlight; - this.name = o.name || nameGenerator(); - this.limit = o.limit || 5; - this.displayFn = getDisplayFn(o.display || o.displayKey); - this.templates = getTemplates(o.templates, this.displayFn); - this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; - this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; - this._resetLastSuggestion(); - this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); - } - Dataset.extractData = function extractData(el) { - var $el = $(el); - if ($el.data(keys.obj)) { - return { - val: $el.data(keys.val) || "", - obj: $el.data(keys.obj) || null - }; - } - return null; - }; - _.mixin(Dataset.prototype, EventEmitter, { - _overwrite: function overwrite(query, suggestions) { - suggestions = suggestions || []; - if (suggestions.length) { - this._renderSuggestions(query, suggestions); - } else if (this.async && this.templates.pending) { - this._renderPending(query); - } else if (!this.async && this.templates.notFound) { - this._renderNotFound(query); - } else { - this._empty(); - } - this.trigger("rendered", this.name, suggestions, false); - }, - _append: function append(query, suggestions) { - suggestions = suggestions || []; - if (suggestions.length && this.$lastSuggestion.length) { - this._appendSuggestions(query, suggestions); - } else if (suggestions.length) { - this._renderSuggestions(query, suggestions); - } else if (!this.$lastSuggestion.length && this.templates.notFound) { - this._renderNotFound(query); - } - this.trigger("rendered", this.name, suggestions, true); - }, - _renderSuggestions: function renderSuggestions(query, suggestions) { - var $fragment; - $fragment = this._getSuggestionsFragment(query, suggestions); - this.$lastSuggestion = $fragment.children().last(); - this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); - }, - _appendSuggestions: function appendSuggestions(query, suggestions) { - var $fragment, $lastSuggestion; - $fragment = this._getSuggestionsFragment(query, suggestions); - $lastSuggestion = $fragment.children().last(); - this.$lastSuggestion.after($fragment); - this.$lastSuggestion = $lastSuggestion; - }, - _renderPending: function renderPending(query) { - var template = this.templates.pending; - this._resetLastSuggestion(); - template && this.$el.html(template({ - query: query, - dataset: this.name - })); - }, - _renderNotFound: function renderNotFound(query) { - var template = this.templates.notFound; - this._resetLastSuggestion(); - template && this.$el.html(template({ - query: query, - dataset: this.name - })); - }, - _empty: function empty() { - this.$el.empty(); - this._resetLastSuggestion(); - }, - _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { - var that = this, fragment; - fragment = document.createDocumentFragment(); - _.each(suggestions, function getSuggestionNode(suggestion) { - var $el, context; - context = that._injectQuery(query, suggestion); - $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); - fragment.appendChild($el[0]); - }); - this.highlight && highlight({ - className: this.classes.highlight, - node: fragment, - pattern: query - }); - return $(fragment); - }, - _getFooter: function getFooter(query, suggestions) { - return this.templates.footer ? this.templates.footer({ - query: query, - suggestions: suggestions, - dataset: this.name - }) : null; - }, - _getHeader: function getHeader(query, suggestions) { - return this.templates.header ? this.templates.header({ - query: query, - suggestions: suggestions, - dataset: this.name - }) : null; - }, - _resetLastSuggestion: function resetLastSuggestion() { - this.$lastSuggestion = $(); - }, - _injectQuery: function injectQuery(query, obj) { - return _.isObject(obj) ? _.mixin({ - _query: query - }, obj) : obj; - }, - update: function update(query) { - var that = this, canceled = false, syncCalled = false, rendered = 0; - this.cancel(); - this.cancel = function cancel() { - canceled = true; - that.cancel = $.noop; - that.async && that.trigger("asyncCanceled", query); - }; - this.source(query, sync, async); - !syncCalled && sync([]); - function sync(suggestions) { - if (syncCalled) { - return; - } - syncCalled = true; - suggestions = (suggestions || []).slice(0, that.limit); - rendered = suggestions.length; - that._overwrite(query, suggestions); - if (rendered < that.limit && that.async) { - that.trigger("asyncRequested", query); - } - } - function async(suggestions) { - suggestions = suggestions || []; - if (!canceled && rendered < that.limit) { - that.cancel = $.noop; - rendered += suggestions.length; - that._append(query, suggestions.slice(0, that.limit - rendered)); - that.async && that.trigger("asyncReceived", query); - } - } - }, - cancel: $.noop, - clear: function clear() { - this._empty(); - this.cancel(); - this.trigger("cleared"); - }, - isEmpty: function isEmpty() { - return this.$el.is(":empty"); - }, - destroy: function destroy() { - this.$el = $("
      "); - } - }); - return Dataset; - function getDisplayFn(display) { - display = display || _.stringify; - return _.isFunction(display) ? display : displayFn; - function displayFn(obj) { - return obj[display]; - } - } - function getTemplates(templates, displayFn) { - return { - notFound: templates.notFound && _.templatify(templates.notFound), - pending: templates.pending && _.templatify(templates.pending), - header: templates.header && _.templatify(templates.header), - footer: templates.footer && _.templatify(templates.footer), - suggestion: templates.suggestion || suggestionTemplate - }; - function suggestionTemplate(context) { - return $("
      ").text(displayFn(context)); - } - } - function isValidName(str) { - return /^[_a-zA-Z0-9-]+$/.test(str); - } - }(); - var Menu = function() { - "use strict"; - function Menu(o, www) { - var that = this; - o = o || {}; - if (!o.node) { - $.error("node is required"); - } - www.mixin(this); - this.$node = $(o.node); - this.query = null; - this.datasets = _.map(o.datasets, initializeDataset); - function initializeDataset(oDataset) { - var node = that.$node.find(oDataset.node).first(); - oDataset.node = node.length ? node : $("
      ").appendTo(that.$node); - return new Dataset(oDataset, www); - } - } - _.mixin(Menu.prototype, EventEmitter, { - _onSelectableClick: function onSelectableClick($e) { - this.trigger("selectableClicked", $($e.currentTarget)); - }, - _onRendered: function onRendered(type, dataset, suggestions, async) { - this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); - this.trigger("datasetRendered", dataset, suggestions, async); - }, - _onCleared: function onCleared() { - this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); - this.trigger("datasetCleared"); - }, - _propagate: function propagate() { - this.trigger.apply(this, arguments); - }, - _allDatasetsEmpty: function allDatasetsEmpty() { - return _.every(this.datasets, isDatasetEmpty); - function isDatasetEmpty(dataset) { - return dataset.isEmpty(); - } - }, - _getSelectables: function getSelectables() { - return this.$node.find(this.selectors.selectable); - }, - _removeCursor: function _removeCursor() { - var $selectable = this.getActiveSelectable(); - $selectable && $selectable.removeClass(this.classes.cursor); - }, - _ensureVisible: function ensureVisible($el) { - var elTop, elBottom, nodeScrollTop, nodeHeight; - elTop = $el.position().top; - elBottom = elTop + $el.outerHeight(true); - nodeScrollTop = this.$node.scrollTop(); - nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); - if (elTop < 0) { - this.$node.scrollTop(nodeScrollTop + elTop); - } else if (nodeHeight < elBottom) { - this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); - } - }, - bind: function() { - var that = this, onSelectableClick; - onSelectableClick = _.bind(this._onSelectableClick, this); - this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); - _.each(this.datasets, function(dataset) { - dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); - }); - return this; - }, - isOpen: function isOpen() { - return this.$node.hasClass(this.classes.open); - }, - open: function open() { - this.$node.addClass(this.classes.open); - }, - close: function close() { - this.$node.removeClass(this.classes.open); - this._removeCursor(); - }, - setLanguageDirection: function setLanguageDirection(dir) { - this.$node.attr("dir", dir); - }, - selectableRelativeToCursor: function selectableRelativeToCursor(delta) { - var $selectables, $oldCursor, oldIndex, newIndex; - $oldCursor = this.getActiveSelectable(); - $selectables = this._getSelectables(); - oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; - newIndex = oldIndex + delta; - newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; - newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; - return newIndex === -1 ? null : $selectables.eq(newIndex); - }, - setCursor: function setCursor($selectable) { - this._removeCursor(); - if ($selectable = $selectable && $selectable.first()) { - $selectable.addClass(this.classes.cursor); - this._ensureVisible($selectable); - } - }, - getSelectableData: function getSelectableData($el) { - return $el && $el.length ? Dataset.extractData($el) : null; - }, - getActiveSelectable: function getActiveSelectable() { - var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); - return $selectable.length ? $selectable : null; - }, - getTopSelectable: function getTopSelectable() { - var $selectable = this._getSelectables().first(); - return $selectable.length ? $selectable : null; - }, - update: function update(query) { - var isValidUpdate = query !== this.query; - if (isValidUpdate) { - this.query = query; - _.each(this.datasets, updateDataset); - } - return isValidUpdate; - function updateDataset(dataset) { - dataset.update(query); - } - }, - empty: function empty() { - _.each(this.datasets, clearDataset); - this.query = null; - this.$node.addClass(this.classes.empty); - function clearDataset(dataset) { - dataset.clear(); - } - }, - destroy: function destroy() { - this.$node.off(".tt"); - this.$node = $("
      "); - _.each(this.datasets, destroyDataset); - function destroyDataset(dataset) { - dataset.destroy(); - } - } - }); - return Menu; - }(); - var DefaultMenu = function() { - "use strict"; - var s = Menu.prototype; - function DefaultMenu() { - Menu.apply(this, [].slice.call(arguments, 0)); - } - _.mixin(DefaultMenu.prototype, Menu.prototype, { - open: function open() { - !this._allDatasetsEmpty() && this._show(); - return s.open.apply(this, [].slice.call(arguments, 0)); - }, - close: function close() { - this._hide(); - return s.close.apply(this, [].slice.call(arguments, 0)); - }, - _onRendered: function onRendered() { - if (this._allDatasetsEmpty()) { - this._hide(); - } else { - this.isOpen() && this._show(); - } - return s._onRendered.apply(this, [].slice.call(arguments, 0)); - }, - _onCleared: function onCleared() { - if (this._allDatasetsEmpty()) { - this._hide(); - } else { - this.isOpen() && this._show(); - } - return s._onCleared.apply(this, [].slice.call(arguments, 0)); - }, - setLanguageDirection: function setLanguageDirection(dir) { - this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); - return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); - }, - _hide: function hide() { - this.$node.hide(); - }, - _show: function show() { - this.$node.css("display", "block"); - } - }); - return DefaultMenu; - }(); - var Typeahead = function() { - "use strict"; - function Typeahead(o, www) { - var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; - o = o || {}; - if (!o.input) { - $.error("missing input"); - } - if (!o.menu) { - $.error("missing menu"); - } - if (!o.eventBus) { - $.error("missing event bus"); - } - www.mixin(this); - this.eventBus = o.eventBus; - this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; - this.input = o.input; - this.menu = o.menu; - this.enabled = true; - this.active = false; - this.input.hasFocus() && this.activate(); - this.dir = this.input.getLangDir(); - this._hacks(); - this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); - onFocused = c(this, "activate", "open", "_onFocused"); - onBlurred = c(this, "deactivate", "_onBlurred"); - onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); - onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); - onEscKeyed = c(this, "isActive", "_onEscKeyed"); - onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); - onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); - onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); - onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); - onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); - onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); - this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); - } - _.mixin(Typeahead.prototype, { - _hacks: function hacks() { - var $input, $menu; - $input = this.input.$input || $("
      "); - $menu = this.menu.$node || $("
      "); - $input.on("blur.tt", function($e) { - var active, isActive, hasActive; - active = document.activeElement; - isActive = $menu.is(active); - hasActive = $menu.has(active).length > 0; - if (_.isMsie() && (isActive || hasActive)) { - $e.preventDefault(); - $e.stopImmediatePropagation(); - _.defer(function() { - $input.focus(); - }); - } - }); - $menu.on("mousedown.tt", function($e) { - $e.preventDefault(); - }); - }, - _onSelectableClicked: function onSelectableClicked(type, $el) { - this.select($el); - }, - _onDatasetCleared: function onDatasetCleared() { - this._updateHint(); - }, - _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) { - this._updateHint(); - this.eventBus.trigger("render", suggestions, async, dataset); - }, - _onAsyncRequested: function onAsyncRequested(type, dataset, query) { - this.eventBus.trigger("asyncrequest", query, dataset); - }, - _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { - this.eventBus.trigger("asynccancel", query, dataset); - }, - _onAsyncReceived: function onAsyncReceived(type, dataset, query) { - this.eventBus.trigger("asyncreceive", query, dataset); - }, - _onFocused: function onFocused() { - this._minLengthMet() && this.menu.update(this.input.getQuery()); - }, - _onBlurred: function onBlurred() { - if (this.input.hasQueryChangedSinceLastFocus()) { - this.eventBus.trigger("change", this.input.getQuery()); - } - }, - _onEnterKeyed: function onEnterKeyed(type, $e) { - var $selectable; - if ($selectable = this.menu.getActiveSelectable()) { - this.select($selectable) && $e.preventDefault(); - } - }, - _onTabKeyed: function onTabKeyed(type, $e) { - var $selectable; - if ($selectable = this.menu.getActiveSelectable()) { - this.select($selectable) && $e.preventDefault(); - } else if ($selectable = this.menu.getTopSelectable()) { - this.autocomplete($selectable) && $e.preventDefault(); - } - }, - _onEscKeyed: function onEscKeyed() { - this.close(); - }, - _onUpKeyed: function onUpKeyed() { - this.moveCursor(-1); - }, - _onDownKeyed: function onDownKeyed() { - this.moveCursor(+1); - }, - _onLeftKeyed: function onLeftKeyed() { - if (this.dir === "rtl" && this.input.isCursorAtEnd()) { - this.autocomplete(this.menu.getTopSelectable()); - } - }, - _onRightKeyed: function onRightKeyed() { - if (this.dir === "ltr" && this.input.isCursorAtEnd()) { - this.autocomplete(this.menu.getTopSelectable()); - } - }, - _onQueryChanged: function onQueryChanged(e, query) { - this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); - }, - _onWhitespaceChanged: function onWhitespaceChanged() { - this._updateHint(); - }, - _onLangDirChanged: function onLangDirChanged(e, dir) { - if (this.dir !== dir) { - this.dir = dir; - this.menu.setLanguageDirection(dir); - } - }, - _openIfActive: function openIfActive() { - this.isActive() && this.open(); - }, - _minLengthMet: function minLengthMet(query) { - query = _.isString(query) ? query : this.input.getQuery() || ""; - return query.length >= this.minLength; - }, - _updateHint: function updateHint() { - var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; - $selectable = this.menu.getTopSelectable(); - data = this.menu.getSelectableData($selectable); - val = this.input.getInputValue(); - if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { - query = Input.normalizeQuery(val); - escapedQuery = _.escapeRegExChars(query); - frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); - match = frontMatchRegEx.exec(data.val); - match && this.input.setHint(val + match[1]); - } else { - this.input.clearHint(); - } - }, - isEnabled: function isEnabled() { - return this.enabled; - }, - enable: function enable() { - this.enabled = true; - }, - disable: function disable() { - this.enabled = false; - }, - isActive: function isActive() { - return this.active; - }, - activate: function activate() { - if (this.isActive()) { - return true; - } else if (!this.isEnabled() || this.eventBus.before("active")) { - return false; - } else { - this.active = true; - this.eventBus.trigger("active"); - return true; - } - }, - deactivate: function deactivate() { - if (!this.isActive()) { - return true; - } else if (this.eventBus.before("idle")) { - return false; - } else { - this.active = false; - this.close(); - this.eventBus.trigger("idle"); - return true; - } - }, - isOpen: function isOpen() { - return this.menu.isOpen(); - }, - open: function open() { - if (!this.isOpen() && !this.eventBus.before("open")) { - this.menu.open(); - this._updateHint(); - this.eventBus.trigger("open"); - } - return this.isOpen(); - }, - close: function close() { - if (this.isOpen() && !this.eventBus.before("close")) { - this.menu.close(); - this.input.clearHint(); - this.input.resetInputValue(); - this.eventBus.trigger("close"); - } - return !this.isOpen(); - }, - setVal: function setVal(val) { - this.input.setQuery(_.toStr(val)); - }, - getVal: function getVal() { - return this.input.getQuery(); - }, - select: function select($selectable) { - var data = this.menu.getSelectableData($selectable); - if (data && !this.eventBus.before("select", data.obj)) { - this.input.setQuery(data.val, true); - this.eventBus.trigger("select", data.obj); - this.close(); - return true; - } - return false; - }, - autocomplete: function autocomplete($selectable) { - var query, data, isValid; - query = this.input.getQuery(); - data = this.menu.getSelectableData($selectable); - isValid = data && query !== data.val; - if (isValid && !this.eventBus.before("autocomplete", data.obj)) { - this.input.setQuery(data.val); - this.eventBus.trigger("autocomplete", data.obj); - return true; - } - return false; - }, - moveCursor: function moveCursor(delta) { - var query, $candidate, data, payload, cancelMove; - query = this.input.getQuery(); - $candidate = this.menu.selectableRelativeToCursor(delta); - data = this.menu.getSelectableData($candidate); - payload = data ? data.obj : null; - cancelMove = this._minLengthMet() && this.menu.update(query); - if (!cancelMove && !this.eventBus.before("cursorchange", payload)) { - this.menu.setCursor($candidate); - if (data) { - this.input.setInputValue(data.val); - } else { - this.input.resetInputValue(); - this._updateHint(); - } - this.eventBus.trigger("cursorchange", payload); - return true; - } - return false; - }, - destroy: function destroy() { - this.input.destroy(); - this.menu.destroy(); - } - }); - return Typeahead; - function c(ctx) { - var methods = [].slice.call(arguments, 1); - return function() { - var args = [].slice.call(arguments); - _.each(methods, function(method) { - return ctx[method].apply(ctx, args); - }); - }; - } - }(); - (function() { - "use strict"; - var old, keys, methods; - old = $.fn.typeahead; - keys = { - www: "tt-www", - attrs: "tt-attrs", - typeahead: "tt-typeahead" - }; - methods = { - initialize: function initialize(o, datasets) { - var www; - datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); - o = o || {}; - www = WWW(o.classNames); - return this.each(attach); - function attach() { - var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor; - _.each(datasets, function(d) { - d.highlight = !!o.highlight; - }); - $input = $(this); - $wrapper = $(www.html.wrapper); - $hint = $elOrNull(o.hint); - $menu = $elOrNull(o.menu); - defaultHint = o.hint !== false && !$hint; - defaultMenu = o.menu !== false && !$menu; - defaultHint && ($hint = buildHintFromInput($input, www)); - defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); - $hint && $hint.val(""); - $input = prepInput($input, www); - if (defaultHint || defaultMenu) { - $wrapper.css(www.css.wrapper); - $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); - $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); - } - MenuConstructor = defaultMenu ? DefaultMenu : Menu; - eventBus = new EventBus({ - el: $input - }); - input = new Input({ - hint: $hint, - input: $input - }, www); - menu = new MenuConstructor({ - node: $menu, - datasets: datasets - }, www); - typeahead = new Typeahead({ - input: input, - menu: menu, - eventBus: eventBus, - minLength: o.minLength - }, www); - $input.data(keys.www, www); - $input.data(keys.typeahead, typeahead); - } - }, - isEnabled: function isEnabled() { - var enabled; - ttEach(this.first(), function(t) { - enabled = t.isEnabled(); - }); - return enabled; - }, - enable: function enable() { - ttEach(this, function(t) { - t.enable(); - }); - return this; - }, - disable: function disable() { - ttEach(this, function(t) { - t.disable(); - }); - return this; - }, - isActive: function isActive() { - var active; - ttEach(this.first(), function(t) { - active = t.isActive(); - }); - return active; - }, - activate: function activate() { - ttEach(this, function(t) { - t.activate(); - }); - return this; - }, - deactivate: function deactivate() { - ttEach(this, function(t) { - t.deactivate(); - }); - return this; - }, - isOpen: function isOpen() { - var open; - ttEach(this.first(), function(t) { - open = t.isOpen(); - }); - return open; - }, - open: function open() { - ttEach(this, function(t) { - t.open(); - }); - return this; - }, - close: function close() { - ttEach(this, function(t) { - t.close(); - }); - return this; - }, - select: function select(el) { - var success = false, $el = $(el); - ttEach(this.first(), function(t) { - success = t.select($el); - }); - return success; - }, - autocomplete: function autocomplete(el) { - var success = false, $el = $(el); - ttEach(this.first(), function(t) { - success = t.autocomplete($el); - }); - return success; - }, - moveCursor: function moveCursoe(delta) { - var success = false; - ttEach(this.first(), function(t) { - success = t.moveCursor(delta); - }); - return success; - }, - val: function val(newVal) { - var query; - if (!arguments.length) { - ttEach(this.first(), function(t) { - query = t.getVal(); - }); - return query; - } else { - ttEach(this, function(t) { - t.setVal(newVal); - }); - return this; - } - }, - destroy: function destroy() { - ttEach(this, function(typeahead, $input) { - revert($input); - typeahead.destroy(); - }); - return this; - } - }; - $.fn.typeahead = function(method) { - if (methods[method]) { - return methods[method].apply(this, [].slice.call(arguments, 1)); - } else { - return methods.initialize.apply(this, arguments); - } - }; - $.fn.typeahead.noConflict = function noConflict() { - $.fn.typeahead = old; - return this; - }; - function ttEach($els, fn) { - $els.each(function() { - var $input = $(this), typeahead; - (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); - }); - } - function buildHintFromInput($input, www) { - return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({ - autocomplete: "off", - spellcheck: "false", - tabindex: -1 - }); - } - function prepInput($input, www) { - $input.data(keys.attrs, { - dir: $input.attr("dir"), - autocomplete: $input.attr("autocomplete"), - spellcheck: $input.attr("spellcheck"), - style: $input.attr("style") - }); - $input.addClass(www.classes.input).attr({ - autocomplete: "off", - spellcheck: false - }); - try { - !$input.attr("dir") && $input.attr("dir", "auto"); - } catch (e) {} - return $input; - } - function getBackgroundStyles($el) { - return { - backgroundAttachment: $el.css("background-attachment"), - backgroundClip: $el.css("background-clip"), - backgroundColor: $el.css("background-color"), - backgroundImage: $el.css("background-image"), - backgroundOrigin: $el.css("background-origin"), - backgroundPosition: $el.css("background-position"), - backgroundRepeat: $el.css("background-repeat"), - backgroundSize: $el.css("background-size") - }; - } - function revert($input) { - var www, $wrapper; - www = $input.data(keys.www); - $wrapper = $input.parent().filter(www.selectors.wrapper); - _.each($input.data(keys.attrs), function(val, key) { - _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); - }); - $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); - if ($wrapper.length) { - $input.detach().insertAfter($wrapper); - $wrapper.remove(); - } - } - function $elOrNull(obj) { - var isValid, $el; - isValid = _.isJQuery(obj) || _.isElement(obj); - $el = isValid ? $(obj).first() : []; - return $el.length ? $el : null; - } - })(); -}); \ No newline at end of file diff --git a/vendor/assets/javascripts/underscore.js b/vendor/assets/javascripts/underscore.js deleted file mode 100644 index bccaf53..0000000 --- a/vendor/assets/javascripts/underscore.js +++ /dev/null @@ -1,1548 +0,0 @@ -// Underscore.js 1.8.3 -// http://underscorejs.org -// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -(function() { - - // Baseline setup - // -------------- - - // Establish the root object, `window` in the browser, or `exports` on the server. - var root = this; - - // Save the previous value of the `_` variable. - var previousUnderscore = root._; - - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - - // Create quick reference variables for speed access to core prototypes. - var - push = ArrayProto.push, - slice = ArrayProto.slice, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeBind = FuncProto.bind, - nativeCreate = Object.create; - - // Naked function reference for surrogate-prototype-swapping. - var Ctor = function(){}; - - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for the old `require()` API. If we're in - // the browser, add `_` as a global object. - if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - - // Current version. - _.VERSION = '1.8.3'; - - // Internal function that returns an efficient (for current engines) version - // of the passed-in callback, to be repeatedly applied in other Underscore - // functions. - var optimizeCb = function(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: return function(value) { - return func.call(context, value); - }; - case 2: return function(value, other) { - return func.call(context, value, other); - }; - case 3: return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; - }; - - // A mostly-internal function to generate callbacks that can be applied - // to each element in a collection, returning the desired result — either - // identity, an arbitrary callback, a property matcher, or a property accessor. - var cb = function(value, context, argCount) { - if (value == null) return _.identity; - if (_.isFunction(value)) return optimizeCb(value, context, argCount); - if (_.isObject(value)) return _.matcher(value); - return _.property(value); - }; - _.iteratee = function(value, context) { - return cb(value, context, Infinity); - }; - - // An internal function for creating assigner functions. - var createAssigner = function(keysFunc, undefinedOnly) { - return function(obj) { - var length = arguments.length; - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], - keys = keysFunc(source), - l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; - } - } - return obj; - }; - }; - - // An internal function for creating a new object that inherits from another. - var baseCreate = function(prototype) { - if (!_.isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - Ctor.prototype = prototype; - var result = new Ctor; - Ctor.prototype = null; - return result; - }; - - var property = function(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; - }; - - // Helper for collection methods to determine whether a collection - // should be iterated as an array or as an object - // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength - // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 - var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - var getLength = property('length'); - var isArrayLike = function(collection) { - var length = getLength(collection); - return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; - }; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles raw objects in addition to array-likes. Treats all - // sparse array-likes as if they were dense. - _.each = _.forEach = function(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); - } - } - return obj; - }; - - // Return the results of applying the iteratee to each element. - _.map = _.collect = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Create a reducing function iterating left or right. - function createReduce(dir) { - // Optimized iterator function as using arguments.length - // in the main function will deoptimize the, see #1991. - function iterator(obj, iteratee, memo, keys, index, length) { - for (; index >= 0 && index < length; index += dir) { - var currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - } - - return function(obj, iteratee, memo, context) { - iteratee = optimizeCb(iteratee, context, 4); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - index = dir > 0 ? 0 : length - 1; - // Determine the initial value if none is provided. - if (arguments.length < 3) { - memo = obj[keys ? keys[index] : index]; - index += dir; - } - return iterator(obj, iteratee, memo, keys, index, length); - }; - } - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. - _.reduce = _.foldl = _.inject = createReduce(1); - - // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = createReduce(-1); - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, predicate, context) { - var key; - if (isArrayLike(obj)) { - key = _.findIndex(obj, predicate, context); - } else { - key = _.findKey(obj, predicate, context); - } - if (key !== void 0 && key !== -1) return obj[key]; - }; - - // Return all the elements that pass a truth test. - // Aliased as `select`. - _.filter = _.select = function(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(cb(predicate)), context); - }; - - // Determine whether all of the elements match a truth test. - // Aliased as `all`. - _.every = _.all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; - } - return true; - }; - - // Determine if at least one element in the object matches a truth test. - // Aliased as `any`. - _.some = _.any = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; - } - return false; - }; - - // Determine if the array or object contains a given item (using `===`). - // Aliased as `includes` and `include`. - _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - if (typeof fromIndex != 'number' || guard) fromIndex = 0; - return _.indexOf(obj, item, fromIndex) >= 0; - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - var func = isFunc ? method : value[method]; - return func == null ? func : func.apply(value, args); - }); - }; - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs) { - return _.filter(obj, _.matcher(attrs)); - }; - - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matcher(attrs)); - }; - - // Return the maximum element (or element-based computation). - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value > result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value < result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Shuffle a collection, using the modern version of the - // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). - _.shuffle = function(obj) { - var set = isArrayLike(obj) ? obj : _.values(obj); - var length = set.length; - var shuffled = Array(length); - for (var index = 0, rand; index < length; index++) { - rand = _.random(0, index); - if (rand !== index) shuffled[index] = shuffled[rand]; - shuffled[rand] = set[index]; - } - return shuffled; - }; - - // Sample **n** random values from a collection. - // If **n** is not specified, returns a single random element. - // The internal `guard` argument allows it to work with `map`. - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; - } - return _.shuffle(obj).slice(0, Math.max(0, n)); - }; - - // Sort the object's values by a criterion produced by an iteratee. - _.sortBy = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iteratee(value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(behavior) { - return function(obj, iteratee, context) { - var result = {}; - iteratee = cb(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) result[key].push(value); else result[key] = [value]; - }); - - // Indexes the object's values by a criterion, similar to `groupBy`, but for - // when you know that your index values will be unique. - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) result[key]++; else result[key] = 1; - }); - - // Safely create a real, live array from anything iterable. - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (isArrayLike(obj)) return _.map(obj, _.identity); - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : _.keys(obj).length; - }; - - // Split a collection into two arrays: one whose elements all satisfy the given - // predicate, and one whose elements all do not satisfy the predicate. - _.partition = function(obj, predicate, context) { - predicate = cb(predicate, context); - var pass = [], fail = []; - _.each(obj, function(value, key, obj) { - (predicate(value, key, obj) ? pass : fail).push(value); - }); - return [pass, fail]; - }; - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[0]; - return _.initial(array, array.length - n); - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. - _.last = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[array.length - 1]; - return _.rest(array, Math.max(0, array.length - n)); - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, _.identity); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, startIndex) { - var output = [], idx = 0; - for (var i = startIndex || 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { - //flatten current level of array or arguments object - if (!shallow) value = flatten(value, shallow, strict); - var j = 0, len = value.length; - output.length += len; - while (j < len) { - output[idx++] = value[j++]; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; - }; - - // Flatten out an array, either recursively (by default), or just one level. - _.flatten = function(array, shallow) { - return flatten(array, shallow, false); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], - computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!_.contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!_.contains(result, value)) { - result.push(value); - } - } - return result; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(flatten(arguments, true, true)); - }; - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) continue; - for (var j = 1; j < argsLength; j++) { - if (!_.contains(arguments[j], item)) break; - } - if (j === argsLength) result.push(item); - } - return result; - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = flatten(arguments, true, true, 1); - return _.filter(array, function(value){ - return !_.contains(rest, value); - }); - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function() { - return _.unzip(arguments); - }; - - // Complement of _.zip. Unzip accepts an array of arrays and groups - // each array's elements on shared indices - _.unzip = function(array) { - var length = array && _.max(array, getLength).length || 0; - var result = Array(length); - - for (var index = 0; index < length; index++) { - result[index] = _.pluck(array, index); - } - return result; - }; - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // Generator function to create the findIndex and findLastIndex functions - function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (; index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; - } - return -1; - }; - } - - // Returns the first index on an array-like that passes a predicate test - _.findIndex = createPredicateIndexFinder(1); - _.findLastIndex = createPredicateIndexFinder(-1); - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - - // Generator function to create the indexOf and lastIndexOf functions - function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == 'number') { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; - } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), _.isNaN); - return idx >= 0 ? idx + i : -1; - } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; - } - return -1; - }; - } - - // Return the position of the first occurrence of an item in an array, - // or -1 if the item is not included in the array. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); - _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; - } - step = step || 1; - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Determines whether to execute a function as a constructor - // or a normal function with the provided arguments - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (_.isObject(result)) return result; - return self; - }; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = function(func, context) { - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); - var args = slice.call(arguments, 2); - var bound = function() { - return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); - }; - return bound; - }; - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. _ acts - // as a placeholder, allowing any combination of arguments to be pre-filled. - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; - } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; - }; - - // Bind a number of an object's methods to that object. Remaining arguments - // are the method names to be bound. Useful for ensuring that all callbacks - // defined on an object belong to it. - _.bindAll = function(obj) { - var i, length = arguments.length, key; - if (length <= 1) throw new Error('bindAll must be passed function names'); - for (i = 1; i < length; i++) { - key = arguments[i]; - obj[key] = _.bind(obj[key], obj); - } - return obj; - }; - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = '' + (hasher ? hasher.apply(this, arguments) : key); - if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ - return func.apply(null, args); - }, wait); - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = _.partial(_.delay, _, 1); - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - if (!options) options = {}; - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; - - var later = function() { - var last = _.now() - timestamp; - - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - if (!timeout) context = args = null; - } - } - }; - - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - context = args = null; - } - - return result; - }; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - - // Returns a negated version of the passed-in predicate. - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); - return result; - }; - }; - - // Returns a function that will only be executed on and after the Nth call. - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Returns a function that will only be executed up to (but not including) the Nth call. - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = _.partial(_.before, 2); - - // Object Functions - // ---------------- - - // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. - var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); - var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', - 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - - function collectNonEnumProps(obj, keys) { - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; - - // Constructor is a special case. - var prop = 'constructor'; - if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); - - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { - keys.push(prop); - } - } - } - - // Retrieve the names of an object's own properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - - // Retrieve all the property names of an object. - _.allKeys = function(obj) { - if (!_.isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - - // Returns the results of applying the iteratee to each element of the object - // In contrast to _.map it returns an object - _.mapObject = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = _.keys(obj), - length = keys.length, - results = {}, - currentKey; - for (var index = 0; index < length; index++) { - currentKey = keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [keys[i], obj[keys[i]]]; - } - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; - } - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = createAssigner(_.allKeys); - - // Assigns a given object with all the own properties in the passed-in object(s) - // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) - _.extendOwn = _.assign = createAssigner(_.keys); - - // Returns the first key on an object that passes a predicate test - _.findKey = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = _.keys(obj), key; - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (predicate(obj[key], key, obj)) return key; - } - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(object, oiteratee, context) { - var result = {}, obj = object, iteratee, keys; - if (obj == null) return result; - if (_.isFunction(oiteratee)) { - keys = _.allKeys(obj); - iteratee = optimizeCb(oiteratee, context); - } else { - keys = flatten(arguments, false, false, 1); - iteratee = function(value, key, obj) { return key in obj; }; - obj = Object(obj); - } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } - return result; - }; - - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj, iteratee, context) { - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - } else { - var keys = _.map(flatten(arguments, false, false, 1), String); - iteratee = function(value, key) { - return !_.contains(keys, key); - }; - } - return _.pick(obj, iteratee, context); - }; - - // Fill in a given object with default properties. - _.defaults = createAssigner(_.allKeys, true); - - // Creates an object that inherits from the given prototype object. - // If additional properties are provided then they will be added to the - // created object. - _.create = function(prototype, props) { - var result = baseCreate(prototype); - if (props) _.extendOwn(result, props); - return result; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Returns whether an object has a given set of `key:value` pairs. - _.isMatch = function(object, attrs) { - var keys = _.keys(attrs), length = keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; - } - return true; - }; - - - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a === 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) return false; - switch (className) { - // Strings, numbers, regular expressions, dates, and booleans are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN - if (+a !== +a) return +b !== +b; - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - } - - var areArrays = className === '[object Array]'; - if (!areArrays) { - if (typeof a != 'object' || typeof b != 'object') return false; - - // Objects with different constructors are not equivalent, but `Object`s or `Array`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - && ('constructor' in a && 'constructor' in b)) { - return false; - } - } - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - - // Initializing stack of traversed objects. - // It's done here since we only need them for objects and arrays comparison. - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) return bStack[length] === b; - } - - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - - // Recursively compare objects and arrays. - if (areArrays) { - // Compare array lengths to determine if a deep comparison is necessary. - length = a.length; - if (length !== b.length) return false; - // Deep compare the contents, ignoring non-numeric properties. - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; - } - } else { - // Deep compare objects. - var keys = _.keys(a), key; - length = keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (_.keys(b).length !== length) return false; - while (length--) { - // Deep compare each member - key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return true; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; - return _.keys(obj).length === 0; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) === '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE < 9), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, 'callee'); - }; - } - - // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, - // IE 11 (#1621), and in Safari 8 (#1929). - if (typeof /./ != 'function' && typeof Int8Array != 'object') { - _.isFunction = function(obj) { - return typeof obj == 'function' || false; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj !== +obj; - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iteratees. - _.identity = function(value) { - return value; - }; - - // Predicate-generating functions. Often useful outside of Underscore. - _.constant = function(value) { - return function() { - return value; - }; - }; - - _.noop = function(){}; - - _.property = property; - - // Generates a function for a given object that returns a given property. - _.propertyOf = function(obj) { - return obj == null ? function(){} : function(key) { - return obj[key]; - }; - }; - - // Returns a predicate for checking whether an object has a given set of - // `key:value` pairs. - _.matcher = _.matches = function(attrs) { - attrs = _.extendOwn({}, attrs); - return function(obj) { - return _.isMatch(obj, attrs); - }; - }; - - // Run a function **n** times. - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - - // A (possibly faster) way to get the current timestamp as an integer. - _.now = Date.now || function() { - return new Date().getTime(); - }; - - // List of HTML entities for escaping. - var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' - }; - var unescapeMap = _.invert(escapeMap); - - // Functions for escaping and unescaping strings to/from HTML interpolation. - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped - var source = '(?:' + _.keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - - // If the value of the named `property` is a function then invoke it with the - // `object` as context; otherwise, return it. - _.result = function(object, property, fallback) { - var value = object == null ? void 0 : object[property]; - if (value === void 0) { - value = fallback; - } - return _.isFunction(value) ? value.call(object) : value; - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\u2028|\u2029/g; - - var escapeChar = function(match) { - return '\\' + escapes[match]; - }; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - // NB: `oldSettings` only exists for backwards compatibility. - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escaper, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offest. - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - try { - var render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled source as a convenience for precompilation. - var argument = settings.variable || 'obj'; - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function. Start chaining a wrapped Underscore object. - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var result = function(instance, obj) { - return instance._chain ? _(obj).chain() : obj; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result(this, func.apply(_, args)); - }; - }); - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; - return result(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - _.each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result(this, method.apply(this._wrapped, arguments)); - }; - }); - - // Extracts the result from a wrapped and chained object. - _.prototype.value = function() { - return this._wrapped; - }; - - // Provide unwrapping proxy for some methods used in engine operations - // such as arithmetic and JSON stringification. - _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; - - _.prototype.toString = function() { - return '' + this._wrapped; - }; - - // AMD registration happens at the end for compatibility with AMD loaders - // that may not enforce next-turn semantics on modules. Even though general - // practice for AMD registration is to be anonymous, underscore registers - // as a named module because, like jQuery, it is a base library that is - // popular enough to be bundled in a third party lib, but not be part of - // an AMD load request. Those cases could generate an error when an - // anonymous define() is called outside of a loader request. - if (typeof define === 'function' && define.amd) { - define('underscore', [], function() { - return _; - }); - } -}.call(this)); \ No newline at end of file diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/assets/stylesheets/bootstrap-datepicker3.css b/vendor/assets/stylesheets/bootstrap-datepicker3.css deleted file mode 100644 index 062d564..0000000 --- a/vendor/assets/stylesheets/bootstrap-datepicker3.css +++ /dev/null @@ -1,680 +0,0 @@ -/*! - * Datepicker for Bootstrap v1.6.1 (https://github.com/eternicode/bootstrap-datepicker) - * - * Copyright 2012 Stefan Petre - * Improvements by Andrew Rowls - * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - */ -.datepicker { - border-radius: 4px; - direction: ltr; -} -.datepicker-inline { - width: 220px; -} -.datepicker.datepicker-rtl { - direction: rtl; -} -.datepicker.datepicker-rtl table tr td span { - float: right; -} -.datepicker-dropdown { - top: 0; - left: 0; - padding: 4px; -} -.datepicker-dropdown:before { - content: ''; - display: inline-block; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid rgba(0, 0, 0, 0.15); - border-top: 0; - border-bottom-color: rgba(0, 0, 0, 0.2); - position: absolute; -} -.datepicker-dropdown:after { - content: ''; - display: inline-block; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-top: 0; - position: absolute; -} -.datepicker-dropdown.datepicker-orient-left:before { - left: 6px; -} -.datepicker-dropdown.datepicker-orient-left:after { - left: 7px; -} -.datepicker-dropdown.datepicker-orient-right:before { - right: 6px; -} -.datepicker-dropdown.datepicker-orient-right:after { - right: 7px; -} -.datepicker-dropdown.datepicker-orient-bottom:before { - top: -7px; -} -.datepicker-dropdown.datepicker-orient-bottom:after { - top: -6px; -} -.datepicker-dropdown.datepicker-orient-top:before { - bottom: -7px; - border-bottom: 0; - border-top: 7px solid rgba(0, 0, 0, 0.15); -} -.datepicker-dropdown.datepicker-orient-top:after { - bottom: -6px; - border-bottom: 0; - border-top: 6px solid #ffffff; -} -.datepicker > div { - display: none; -} -.datepicker table { - margin: 0; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.datepicker table tr td, -.datepicker table tr th { - text-align: center; - width: 30px; - height: 30px; - border-radius: 4px; - border: none; -} -.table-striped .datepicker table tr td, -.table-striped .datepicker table tr th { - background-color: transparent; -} -.datepicker table tr td.old, -.datepicker table tr td.new { - color: #777777; -} -.datepicker table tr td.day:hover, -.datepicker table tr td.focused { - background: #eeeeee; - cursor: pointer; -} -.datepicker table tr td.disabled, -.datepicker table tr td.disabled:hover { - background: none; - color: #777777; - cursor: default; -} -.datepicker table tr td.highlighted { - color: #000000; - background-color: #d9edf7; - border-color: #85c5e5; - border-radius: 0; -} -.datepicker table tr td.highlighted:focus, -.datepicker table tr td.highlighted.focus { - color: #000000; - background-color: #afd9ee; - border-color: #298fc2; -} -.datepicker table tr td.highlighted:hover { - color: #000000; - background-color: #afd9ee; - border-color: #52addb; -} -.datepicker table tr td.highlighted:active, -.datepicker table tr td.highlighted.active { - color: #000000; - background-color: #afd9ee; - border-color: #52addb; -} -.datepicker table tr td.highlighted:active:hover, -.datepicker table tr td.highlighted.active:hover, -.datepicker table tr td.highlighted:active:focus, -.datepicker table tr td.highlighted.active:focus, -.datepicker table tr td.highlighted:active.focus, -.datepicker table tr td.highlighted.active.focus { - color: #000000; - background-color: #91cbe8; - border-color: #298fc2; -} -.datepicker table tr td.highlighted.disabled:hover, -.datepicker table tr td.highlighted[disabled]:hover, -fieldset[disabled] .datepicker table tr td.highlighted:hover, -.datepicker table tr td.highlighted.disabled:focus, -.datepicker table tr td.highlighted[disabled]:focus, -fieldset[disabled] .datepicker table tr td.highlighted:focus, -.datepicker table tr td.highlighted.disabled.focus, -.datepicker table tr td.highlighted[disabled].focus, -fieldset[disabled] .datepicker table tr td.highlighted.focus { - background-color: #d9edf7; - border-color: #85c5e5; -} -.datepicker table tr td.highlighted.focused { - background: #afd9ee; -} -.datepicker table tr td.highlighted.disabled, -.datepicker table tr td.highlighted.disabled:active { - background: #d9edf7; - color: #777777; -} -.datepicker table tr td.today { - color: #000000; - background-color: #ffdb99; - border-color: #ffb733; -} -.datepicker table tr td.today:focus, -.datepicker table tr td.today.focus { - color: #000000; - background-color: #ffc966; - border-color: #b37400; -} -.datepicker table tr td.today:hover { - color: #000000; - background-color: #ffc966; - border-color: #f59e00; -} -.datepicker table tr td.today:active, -.datepicker table tr td.today.active { - color: #000000; - background-color: #ffc966; - border-color: #f59e00; -} -.datepicker table tr td.today:active:hover, -.datepicker table tr td.today.active:hover, -.datepicker table tr td.today:active:focus, -.datepicker table tr td.today.active:focus, -.datepicker table tr td.today:active.focus, -.datepicker table tr td.today.active.focus { - color: #000000; - background-color: #ffbc42; - border-color: #b37400; -} -.datepicker table tr td.today.disabled:hover, -.datepicker table tr td.today[disabled]:hover, -fieldset[disabled] .datepicker table tr td.today:hover, -.datepicker table tr td.today.disabled:focus, -.datepicker table tr td.today[disabled]:focus, -fieldset[disabled] .datepicker table tr td.today:focus, -.datepicker table tr td.today.disabled.focus, -.datepicker table tr td.today[disabled].focus, -fieldset[disabled] .datepicker table tr td.today.focus { - background-color: #ffdb99; - border-color: #ffb733; -} -.datepicker table tr td.today.focused { - background: #ffc966; -} -.datepicker table tr td.today.disabled, -.datepicker table tr td.today.disabled:active { - background: #ffdb99; - color: #777777; -} -.datepicker table tr td.range { - color: #000000; - background-color: #eeeeee; - border-color: #bbbbbb; - border-radius: 0; -} -.datepicker table tr td.range:focus, -.datepicker table tr td.range.focus { - color: #000000; - background-color: #d5d5d5; - border-color: #7c7c7c; -} -.datepicker table tr td.range:hover { - color: #000000; - background-color: #d5d5d5; - border-color: #9d9d9d; -} -.datepicker table tr td.range:active, -.datepicker table tr td.range.active { - color: #000000; - background-color: #d5d5d5; - border-color: #9d9d9d; -} -.datepicker table tr td.range:active:hover, -.datepicker table tr td.range.active:hover, -.datepicker table tr td.range:active:focus, -.datepicker table tr td.range.active:focus, -.datepicker table tr td.range:active.focus, -.datepicker table tr td.range.active.focus { - color: #000000; - background-color: #c3c3c3; - border-color: #7c7c7c; -} -.datepicker table tr td.range.disabled:hover, -.datepicker table tr td.range[disabled]:hover, -fieldset[disabled] .datepicker table tr td.range:hover, -.datepicker table tr td.range.disabled:focus, -.datepicker table tr td.range[disabled]:focus, -fieldset[disabled] .datepicker table tr td.range:focus, -.datepicker table tr td.range.disabled.focus, -.datepicker table tr td.range[disabled].focus, -fieldset[disabled] .datepicker table tr td.range.focus { - background-color: #eeeeee; - border-color: #bbbbbb; -} -.datepicker table tr td.range.focused { - background: #d5d5d5; -} -.datepicker table tr td.range.disabled, -.datepicker table tr td.range.disabled:active { - background: #eeeeee; - color: #777777; -} -.datepicker table tr td.range.highlighted { - color: #000000; - background-color: #e4eef3; - border-color: #9dc1d3; -} -.datepicker table tr td.range.highlighted:focus, -.datepicker table tr td.range.highlighted.focus { - color: #000000; - background-color: #c1d7e3; - border-color: #4b88a6; -} -.datepicker table tr td.range.highlighted:hover { - color: #000000; - background-color: #c1d7e3; - border-color: #73a6c0; -} -.datepicker table tr td.range.highlighted:active, -.datepicker table tr td.range.highlighted.active { - color: #000000; - background-color: #c1d7e3; - border-color: #73a6c0; -} -.datepicker table tr td.range.highlighted:active:hover, -.datepicker table tr td.range.highlighted.active:hover, -.datepicker table tr td.range.highlighted:active:focus, -.datepicker table tr td.range.highlighted.active:focus, -.datepicker table tr td.range.highlighted:active.focus, -.datepicker table tr td.range.highlighted.active.focus { - color: #000000; - background-color: #a8c8d8; - border-color: #4b88a6; -} -.datepicker table tr td.range.highlighted.disabled:hover, -.datepicker table tr td.range.highlighted[disabled]:hover, -fieldset[disabled] .datepicker table tr td.range.highlighted:hover, -.datepicker table tr td.range.highlighted.disabled:focus, -.datepicker table tr td.range.highlighted[disabled]:focus, -fieldset[disabled] .datepicker table tr td.range.highlighted:focus, -.datepicker table tr td.range.highlighted.disabled.focus, -.datepicker table tr td.range.highlighted[disabled].focus, -fieldset[disabled] .datepicker table tr td.range.highlighted.focus { - background-color: #e4eef3; - border-color: #9dc1d3; -} -.datepicker table tr td.range.highlighted.focused { - background: #c1d7e3; -} -.datepicker table tr td.range.highlighted.disabled, -.datepicker table tr td.range.highlighted.disabled:active { - background: #e4eef3; - color: #777777; -} -.datepicker table tr td.range.today { - color: #000000; - background-color: #f7ca77; - border-color: #f1a417; -} -.datepicker table tr td.range.today:focus, -.datepicker table tr td.range.today.focus { - color: #000000; - background-color: #f4b747; - border-color: #815608; -} -.datepicker table tr td.range.today:hover { - color: #000000; - background-color: #f4b747; - border-color: #bf800c; -} -.datepicker table tr td.range.today:active, -.datepicker table tr td.range.today.active { - color: #000000; - background-color: #f4b747; - border-color: #bf800c; -} -.datepicker table tr td.range.today:active:hover, -.datepicker table tr td.range.today.active:hover, -.datepicker table tr td.range.today:active:focus, -.datepicker table tr td.range.today.active:focus, -.datepicker table tr td.range.today:active.focus, -.datepicker table tr td.range.today.active.focus { - color: #000000; - background-color: #f2aa25; - border-color: #815608; -} -.datepicker table tr td.range.today.disabled:hover, -.datepicker table tr td.range.today[disabled]:hover, -fieldset[disabled] .datepicker table tr td.range.today:hover, -.datepicker table tr td.range.today.disabled:focus, -.datepicker table tr td.range.today[disabled]:focus, -fieldset[disabled] .datepicker table tr td.range.today:focus, -.datepicker table tr td.range.today.disabled.focus, -.datepicker table tr td.range.today[disabled].focus, -fieldset[disabled] .datepicker table tr td.range.today.focus { - background-color: #f7ca77; - border-color: #f1a417; -} -.datepicker table tr td.range.today.disabled, -.datepicker table tr td.range.today.disabled:active { - background: #f7ca77; - color: #777777; -} -.datepicker table tr td.selected, -.datepicker table tr td.selected.highlighted { - color: #ffffff; - background-color: #777777; - border-color: #555555; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.datepicker table tr td.selected:focus, -.datepicker table tr td.selected.highlighted:focus, -.datepicker table tr td.selected.focus, -.datepicker table tr td.selected.highlighted.focus { - color: #ffffff; - background-color: #5e5e5e; - border-color: #161616; -} -.datepicker table tr td.selected:hover, -.datepicker table tr td.selected.highlighted:hover { - color: #ffffff; - background-color: #5e5e5e; - border-color: #373737; -} -.datepicker table tr td.selected:active, -.datepicker table tr td.selected.highlighted:active, -.datepicker table tr td.selected.active, -.datepicker table tr td.selected.highlighted.active { - color: #ffffff; - background-color: #5e5e5e; - border-color: #373737; -} -.datepicker table tr td.selected:active:hover, -.datepicker table tr td.selected.highlighted:active:hover, -.datepicker table tr td.selected.active:hover, -.datepicker table tr td.selected.highlighted.active:hover, -.datepicker table tr td.selected:active:focus, -.datepicker table tr td.selected.highlighted:active:focus, -.datepicker table tr td.selected.active:focus, -.datepicker table tr td.selected.highlighted.active:focus, -.datepicker table tr td.selected:active.focus, -.datepicker table tr td.selected.highlighted:active.focus, -.datepicker table tr td.selected.active.focus, -.datepicker table tr td.selected.highlighted.active.focus { - color: #ffffff; - background-color: #4c4c4c; - border-color: #161616; -} -.datepicker table tr td.selected.disabled:hover, -.datepicker table tr td.selected.highlighted.disabled:hover, -.datepicker table tr td.selected[disabled]:hover, -.datepicker table tr td.selected.highlighted[disabled]:hover, -fieldset[disabled] .datepicker table tr td.selected:hover, -fieldset[disabled] .datepicker table tr td.selected.highlighted:hover, -.datepicker table tr td.selected.disabled:focus, -.datepicker table tr td.selected.highlighted.disabled:focus, -.datepicker table tr td.selected[disabled]:focus, -.datepicker table tr td.selected.highlighted[disabled]:focus, -fieldset[disabled] .datepicker table tr td.selected:focus, -fieldset[disabled] .datepicker table tr td.selected.highlighted:focus, -.datepicker table tr td.selected.disabled.focus, -.datepicker table tr td.selected.highlighted.disabled.focus, -.datepicker table tr td.selected[disabled].focus, -.datepicker table tr td.selected.highlighted[disabled].focus, -fieldset[disabled] .datepicker table tr td.selected.focus, -fieldset[disabled] .datepicker table tr td.selected.highlighted.focus { - background-color: #777777; - border-color: #555555; -} -.datepicker table tr td.active, -.datepicker table tr td.active.highlighted { - color: #ffffff; - background-color: #337ab7; - border-color: #2e6da4; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.datepicker table tr td.active:focus, -.datepicker table tr td.active.highlighted:focus, -.datepicker table tr td.active.focus, -.datepicker table tr td.active.highlighted.focus { - color: #ffffff; - background-color: #286090; - border-color: #122b40; -} -.datepicker table tr td.active:hover, -.datepicker table tr td.active.highlighted:hover { - color: #ffffff; - background-color: #286090; - border-color: #204d74; -} -.datepicker table tr td.active:active, -.datepicker table tr td.active.highlighted:active, -.datepicker table tr td.active.active, -.datepicker table tr td.active.highlighted.active { - color: #ffffff; - background-color: #286090; - border-color: #204d74; -} -.datepicker table tr td.active:active:hover, -.datepicker table tr td.active.highlighted:active:hover, -.datepicker table tr td.active.active:hover, -.datepicker table tr td.active.highlighted.active:hover, -.datepicker table tr td.active:active:focus, -.datepicker table tr td.active.highlighted:active:focus, -.datepicker table tr td.active.active:focus, -.datepicker table tr td.active.highlighted.active:focus, -.datepicker table tr td.active:active.focus, -.datepicker table tr td.active.highlighted:active.focus, -.datepicker table tr td.active.active.focus, -.datepicker table tr td.active.highlighted.active.focus { - color: #ffffff; - background-color: #204d74; - border-color: #122b40; -} -.datepicker table tr td.active.disabled:hover, -.datepicker table tr td.active.highlighted.disabled:hover, -.datepicker table tr td.active[disabled]:hover, -.datepicker table tr td.active.highlighted[disabled]:hover, -fieldset[disabled] .datepicker table tr td.active:hover, -fieldset[disabled] .datepicker table tr td.active.highlighted:hover, -.datepicker table tr td.active.disabled:focus, -.datepicker table tr td.active.highlighted.disabled:focus, -.datepicker table tr td.active[disabled]:focus, -.datepicker table tr td.active.highlighted[disabled]:focus, -fieldset[disabled] .datepicker table tr td.active:focus, -fieldset[disabled] .datepicker table tr td.active.highlighted:focus, -.datepicker table tr td.active.disabled.focus, -.datepicker table tr td.active.highlighted.disabled.focus, -.datepicker table tr td.active[disabled].focus, -.datepicker table tr td.active.highlighted[disabled].focus, -fieldset[disabled] .datepicker table tr td.active.focus, -fieldset[disabled] .datepicker table tr td.active.highlighted.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.datepicker table tr td span { - display: block; - width: 23%; - height: 54px; - line-height: 54px; - float: left; - margin: 1%; - cursor: pointer; - border-radius: 4px; -} -.datepicker table tr td span:hover, -.datepicker table tr td span.focused { - background: #eeeeee; -} -.datepicker table tr td span.disabled, -.datepicker table tr td span.disabled:hover { - background: none; - color: #777777; - cursor: default; -} -.datepicker table tr td span.active, -.datepicker table tr td span.active:hover, -.datepicker table tr td span.active.disabled, -.datepicker table tr td span.active.disabled:hover { - color: #ffffff; - background-color: #337ab7; - border-color: #2e6da4; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.datepicker table tr td span.active:focus, -.datepicker table tr td span.active:hover:focus, -.datepicker table tr td span.active.disabled:focus, -.datepicker table tr td span.active.disabled:hover:focus, -.datepicker table tr td span.active.focus, -.datepicker table tr td span.active:hover.focus, -.datepicker table tr td span.active.disabled.focus, -.datepicker table tr td span.active.disabled:hover.focus { - color: #ffffff; - background-color: #286090; - border-color: #122b40; -} -.datepicker table tr td span.active:hover, -.datepicker table tr td span.active:hover:hover, -.datepicker table tr td span.active.disabled:hover, -.datepicker table tr td span.active.disabled:hover:hover { - color: #ffffff; - background-color: #286090; - border-color: #204d74; -} -.datepicker table tr td span.active:active, -.datepicker table tr td span.active:hover:active, -.datepicker table tr td span.active.disabled:active, -.datepicker table tr td span.active.disabled:hover:active, -.datepicker table tr td span.active.active, -.datepicker table tr td span.active:hover.active, -.datepicker table tr td span.active.disabled.active, -.datepicker table tr td span.active.disabled:hover.active { - color: #ffffff; - background-color: #286090; - border-color: #204d74; -} -.datepicker table tr td span.active:active:hover, -.datepicker table tr td span.active:hover:active:hover, -.datepicker table tr td span.active.disabled:active:hover, -.datepicker table tr td span.active.disabled:hover:active:hover, -.datepicker table tr td span.active.active:hover, -.datepicker table tr td span.active:hover.active:hover, -.datepicker table tr td span.active.disabled.active:hover, -.datepicker table tr td span.active.disabled:hover.active:hover, -.datepicker table tr td span.active:active:focus, -.datepicker table tr td span.active:hover:active:focus, -.datepicker table tr td span.active.disabled:active:focus, -.datepicker table tr td span.active.disabled:hover:active:focus, -.datepicker table tr td span.active.active:focus, -.datepicker table tr td span.active:hover.active:focus, -.datepicker table tr td span.active.disabled.active:focus, -.datepicker table tr td span.active.disabled:hover.active:focus, -.datepicker table tr td span.active:active.focus, -.datepicker table tr td span.active:hover:active.focus, -.datepicker table tr td span.active.disabled:active.focus, -.datepicker table tr td span.active.disabled:hover:active.focus, -.datepicker table tr td span.active.active.focus, -.datepicker table tr td span.active:hover.active.focus, -.datepicker table tr td span.active.disabled.active.focus, -.datepicker table tr td span.active.disabled:hover.active.focus { - color: #ffffff; - background-color: #204d74; - border-color: #122b40; -} -.datepicker table tr td span.active.disabled:hover, -.datepicker table tr td span.active:hover.disabled:hover, -.datepicker table tr td span.active.disabled.disabled:hover, -.datepicker table tr td span.active.disabled:hover.disabled:hover, -.datepicker table tr td span.active[disabled]:hover, -.datepicker table tr td span.active:hover[disabled]:hover, -.datepicker table tr td span.active.disabled[disabled]:hover, -.datepicker table tr td span.active.disabled:hover[disabled]:hover, -fieldset[disabled] .datepicker table tr td span.active:hover, -fieldset[disabled] .datepicker table tr td span.active:hover:hover, -fieldset[disabled] .datepicker table tr td span.active.disabled:hover, -fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover, -.datepicker table tr td span.active.disabled:focus, -.datepicker table tr td span.active:hover.disabled:focus, -.datepicker table tr td span.active.disabled.disabled:focus, -.datepicker table tr td span.active.disabled:hover.disabled:focus, -.datepicker table tr td span.active[disabled]:focus, -.datepicker table tr td span.active:hover[disabled]:focus, -.datepicker table tr td span.active.disabled[disabled]:focus, -.datepicker table tr td span.active.disabled:hover[disabled]:focus, -fieldset[disabled] .datepicker table tr td span.active:focus, -fieldset[disabled] .datepicker table tr td span.active:hover:focus, -fieldset[disabled] .datepicker table tr td span.active.disabled:focus, -fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus, -.datepicker table tr td span.active.disabled.focus, -.datepicker table tr td span.active:hover.disabled.focus, -.datepicker table tr td span.active.disabled.disabled.focus, -.datepicker table tr td span.active.disabled:hover.disabled.focus, -.datepicker table tr td span.active[disabled].focus, -.datepicker table tr td span.active:hover[disabled].focus, -.datepicker table tr td span.active.disabled[disabled].focus, -.datepicker table tr td span.active.disabled:hover[disabled].focus, -fieldset[disabled] .datepicker table tr td span.active.focus, -fieldset[disabled] .datepicker table tr td span.active:hover.focus, -fieldset[disabled] .datepicker table tr td span.active.disabled.focus, -fieldset[disabled] .datepicker table tr td span.active.disabled:hover.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.datepicker table tr td span.old, -.datepicker table tr td span.new { - color: #777777; -} -.datepicker .datepicker-switch { - width: 145px; -} -.datepicker .datepicker-switch, -.datepicker .prev, -.datepicker .next, -.datepicker tfoot tr th { - cursor: pointer; -} -.datepicker .datepicker-switch:hover, -.datepicker .prev:hover, -.datepicker .next:hover, -.datepicker tfoot tr th:hover { - background: #eeeeee; -} -.datepicker .cw { - font-size: 10px; - width: 12px; - padding: 0 2px 0 5px; - vertical-align: middle; -} -.input-group.date .input-group-addon { - cursor: pointer; -} -.input-daterange { - width: 100%; -} -.input-daterange input { - text-align: center; -} -.input-daterange input:first-child { - border-radius: 3px 0 0 3px; -} -.input-daterange input:last-child { - border-radius: 0 3px 3px 0; -} -.input-daterange .input-group-addon { - width: auto; - min-width: 16px; - padding: 4px 5px; - line-height: 1.42857143; - text-shadow: 0 1px 0 #fff; - border-width: 1px 0; - margin-left: -5px; - margin-right: -5px; -} \ No newline at end of file diff --git a/vendor/assets/stylesheets/bootstrap-tagsinput-typeahead.css b/vendor/assets/stylesheets/bootstrap-tagsinput-typeahead.css deleted file mode 100644 index 55d845e..0000000 --- a/vendor/assets/stylesheets/bootstrap-tagsinput-typeahead.css +++ /dev/null @@ -1,54 +0,0 @@ -/* - * bootstrap-tagsinput v0.8.0 - * - */ - -.twitter-typeahead .tt-query, -.twitter-typeahead .tt-hint { - margin-bottom: 0; -} - -.twitter-typeahead .tt-hint -{ - display: none; -} - -.tt-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - font-size: 14px; - background-color: #ffffff; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - background-clip: padding-box; - cursor: pointer; -} - -.tt-suggestion { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.428571429; - color: #333333; - white-space: nowrap; -} - -.tt-suggestion:hover, -.tt-suggestion:focus { - color: #ffffff; - text-decoration: none; - outline: 0; - background-color: #428bca; -} diff --git a/vendor/assets/stylesheets/bootstrap-tagsinput.css b/vendor/assets/stylesheets/bootstrap-tagsinput.css deleted file mode 100644 index af98e99..0000000 --- a/vendor/assets/stylesheets/bootstrap-tagsinput.css +++ /dev/null @@ -1,60 +0,0 @@ -/* - * bootstrap-tagsinput v0.8.0 - * - */ - -.bootstrap-tagsinput { - background-color: #fff; - border: 1px solid #ccc; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - display: inline-block; - padding: 4px 6px; - color: #555; - vertical-align: middle; - border-radius: 4px; - max-width: 100%; - line-height: 22px; - cursor: text; -} -.bootstrap-tagsinput input { - border: none; - box-shadow: none; - outline: none; - background-color: transparent; - padding: 0 6px; - margin: 0; - width: auto; - max-width: inherit; -} -.bootstrap-tagsinput.form-control input::-moz-placeholder { - color: #777; - opacity: 1; -} -.bootstrap-tagsinput.form-control input:-ms-input-placeholder { - color: #777; -} -.bootstrap-tagsinput.form-control input::-webkit-input-placeholder { - color: #777; -} -.bootstrap-tagsinput input:focus { - border: none; - box-shadow: none; -} -.bootstrap-tagsinput .tag { - margin-right: 2px; - color: white; -} -.bootstrap-tagsinput .tag [data-role="remove"] { - margin-left: 8px; - cursor: pointer; -} -.bootstrap-tagsinput .tag [data-role="remove"]:after { - content: "x"; - padding: 0px 2px; -} -.bootstrap-tagsinput .tag [data-role="remove"]:hover { - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.bootstrap-tagsinput .tag [data-role="remove"]:hover:active { - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} diff --git a/vendor/assets/stylesheets/chosen.css b/vendor/assets/stylesheets/chosen.css deleted file mode 100644 index e7ea092..0000000 --- a/vendor/assets/stylesheets/chosen.css +++ /dev/null @@ -1,450 +0,0 @@ -/*! -Chosen, a Select Box Enhancer for jQuery and Prototype -by Patrick Filler for Harvest, http://getharvest.com - -Version 1.4.2 -Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011-2015 Harvest http://getharvest.com - -MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md -This file is generated by `grunt build`, do not edit it by hand. -*/ - -/* @group Base */ -.chosen-container { - position: relative; - display: inline-block; - vertical-align: middle; - font-size: 13px; - zoom: 1; - *display: inline; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} -.chosen-container * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.chosen-container .chosen-drop { - position: absolute; - top: 100%; - left: -9999px; - z-index: 1010; - width: 100%; - border: 1px solid #aaa; - border-top: 0; - background: #fff; - box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); -} -.chosen-container.chosen-with-drop .chosen-drop { - left: 0; -} -.chosen-container a { - cursor: pointer; -} -.chosen-container .search-choice .group-name, .chosen-container .chosen-single .group-name { - margin-right: 4px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-weight: normal; - color: #999999; -} -.chosen-container .search-choice .group-name:after, .chosen-container .chosen-single .group-name:after { - content: ":"; - padding-left: 2px; - vertical-align: top; -} - -/* @end */ -/* @group Single Chosen */ -.chosen-container-single .chosen-single { - position: relative; - display: block; - overflow: hidden; - padding: 0 0 0 8px; - height: 25px; - border: 1px solid #aaa; - border-radius: 5px; - background-color: #fff; - background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4)); - background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background-clip: padding-box; - box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1); - color: #444; - text-decoration: none; - white-space: nowrap; - line-height: 24px; -} -.chosen-container-single .chosen-default { - color: #999; -} -.chosen-container-single .chosen-single span { - display: block; - overflow: hidden; - margin-right: 26px; - text-overflow: ellipsis; - white-space: nowrap; -} -.chosen-container-single .chosen-single-with-deselect span { - margin-right: 38px; -} -.chosen-container-single .chosen-single abbr { - position: absolute; - top: 6px; - right: 26px; - display: block; - width: 12px; - height: 12px; - background: url('chosen-sprite.png') -42px 1px no-repeat; - font-size: 1px; -} -.chosen-container-single .chosen-single abbr:hover { - background-position: -42px -10px; -} -.chosen-container-single.chosen-disabled .chosen-single abbr:hover { - background-position: -42px -10px; -} -.chosen-container-single .chosen-single div { - position: absolute; - top: 0; - right: 0; - display: block; - width: 18px; - height: 100%; -} -.chosen-container-single .chosen-single div b { - display: block; - width: 100%; - height: 100%; - background: url('chosen-sprite.png') no-repeat 0px 2px; -} -.chosen-container-single .chosen-search { - position: relative; - z-index: 1010; - margin: 0; - padding: 3px 4px; - white-space: nowrap; -} -.chosen-container-single .chosen-search input[type="text"] { - margin: 1px 0; - padding: 4px 20px 4px 5px; - width: 100%; - height: auto; - outline: 0; - border: 1px solid #aaa; - background: white url('chosen-sprite.png') no-repeat 100% -20px; - background: url('chosen-sprite.png') no-repeat 100% -20px; - font-size: 1em; - font-family: sans-serif; - line-height: normal; - border-radius: 0; -} -.chosen-container-single .chosen-drop { - margin-top: -1px; - border-radius: 0 0 4px 4px; - background-clip: padding-box; -} -.chosen-container-single.chosen-container-single-nosearch .chosen-search { - position: absolute; - left: -9999px; -} - -/* @end */ -/* @group Results */ -.chosen-container .chosen-results { - color: #444; - position: relative; - overflow-x: hidden; - overflow-y: auto; - margin: 0 4px 4px 0; - padding: 0 0 0 4px; - max-height: 240px; - -webkit-overflow-scrolling: touch; -} -.chosen-container .chosen-results li { - display: none; - margin: 0; - padding: 5px 6px; - list-style: none; - line-height: 15px; - word-wrap: break-word; - -webkit-touch-callout: none; -} -.chosen-container .chosen-results li.active-result { - display: list-item; - cursor: pointer; -} -.chosen-container .chosen-results li.disabled-result { - display: list-item; - color: #ccc; - cursor: default; -} -.chosen-container .chosen-results li.highlighted { - background-color: #3875d7; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc)); - background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%); - background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%); - background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%); - background-image: linear-gradient(#3875d7 20%, #2a62bc 90%); - color: #fff; -} -.chosen-container .chosen-results li.no-results { - color: #777; - display: list-item; - background: #f4f4f4; -} -.chosen-container .chosen-results li.group-result { - display: list-item; - font-weight: bold; - cursor: default; -} -.chosen-container .chosen-results li.group-option { - padding-left: 15px; -} -.chosen-container .chosen-results li em { - font-style: normal; - text-decoration: underline; -} - -/* @end */ -/* @group Multi Chosen */ -.chosen-container-multi .chosen-choices { - position: relative; - overflow: hidden; - margin: 0; - padding: 0 5px; - width: 100%; - height: auto !important; - height: 1%; - border: 1px solid #aaa; - background-color: #fff; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); - background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%); - background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%); - background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%); - background-image: linear-gradient(#eeeeee 1%, #ffffff 15%); - cursor: text; -} -.chosen-container-multi .chosen-choices li { - float: left; - list-style: none; -} -.chosen-container-multi .chosen-choices li.search-field { - margin: 0; - padding: 0; - white-space: nowrap; -} -.chosen-container-multi .chosen-choices li.search-field input[type="text"] { - margin: 1px 0; - padding: 0; - height: 25px; - outline: 0; - border: 0 !important; - background: transparent !important; - box-shadow: none; - color: #999; - font-size: 100%; - font-family: sans-serif; - line-height: normal; - border-radius: 0; -} -.chosen-container-multi .chosen-choices li.search-choice { - position: relative; - margin: 3px 5px 3px 0; - padding: 3px 20px 3px 5px; - border: 1px solid #aaa; - max-width: 100%; - border-radius: 3px; - background-color: #eeeeee; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); - background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-size: 100% 19px; - background-repeat: repeat-x; - background-clip: padding-box; - box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05); - color: #333; - line-height: 13px; - cursor: default; -} -.chosen-container-multi .chosen-choices li.search-choice span { - word-wrap: break-word; -} -.chosen-container-multi .chosen-choices li.search-choice .search-choice-close { - position: absolute; - top: 4px; - right: 3px; - display: block; - width: 12px; - height: 12px; - background: url('chosen-sprite.png') -42px 1px no-repeat; - font-size: 1px; -} -.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover { - background-position: -42px -10px; -} -.chosen-container-multi .chosen-choices li.search-choice-disabled { - padding-right: 5px; - border: 1px solid #ccc; - background-color: #e4e4e4; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); - background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - color: #666; -} -.chosen-container-multi .chosen-choices li.search-choice-focus { - background: #d4d4d4; -} -.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close { - background-position: -42px -10px; -} -.chosen-container-multi .chosen-results { - margin: 0; - padding: 0; -} -.chosen-container-multi .chosen-drop .result-selected { - display: list-item; - color: #ccc; - cursor: default; -} - -/* @end */ -/* @group Active */ -.chosen-container-active .chosen-single { - border: 1px solid #5897fb; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); -} -.chosen-container-active.chosen-with-drop .chosen-single { - border: 1px solid #aaa; - -moz-border-radius-bottomright: 0; - border-bottom-right-radius: 0; - -moz-border-radius-bottomleft: 0; - border-bottom-left-radius: 0; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff)); - background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%); - background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%); - background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%); - background-image: linear-gradient(#eeeeee 20%, #ffffff 80%); - box-shadow: 0 1px 0 #fff inset; -} -.chosen-container-active.chosen-with-drop .chosen-single div { - border-left: none; - background: transparent; -} -.chosen-container-active.chosen-with-drop .chosen-single div b { - background-position: -18px 2px; -} -.chosen-container-active .chosen-choices { - border: 1px solid #5897fb; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); -} -.chosen-container-active .chosen-choices li.search-field input[type="text"] { - color: #222 !important; -} - -/* @end */ -/* @group Disabled Support */ -.chosen-disabled { - opacity: 0.5 !important; - cursor: default; -} -.chosen-disabled .chosen-single { - cursor: default; -} -.chosen-disabled .chosen-choices .search-choice .search-choice-close { - cursor: default; -} - -/* @end */ -/* @group Right to Left */ -.chosen-rtl { - text-align: right; -} -.chosen-rtl .chosen-single { - overflow: visible; - padding: 0 8px 0 0; -} -.chosen-rtl .chosen-single span { - margin-right: 0; - margin-left: 26px; - direction: rtl; -} -.chosen-rtl .chosen-single-with-deselect span { - margin-left: 38px; -} -.chosen-rtl .chosen-single div { - right: auto; - left: 3px; -} -.chosen-rtl .chosen-single abbr { - right: auto; - left: 26px; -} -.chosen-rtl .chosen-choices li { - float: right; -} -.chosen-rtl .chosen-choices li.search-field input[type="text"] { - direction: rtl; -} -.chosen-rtl .chosen-choices li.search-choice { - margin: 3px 5px 3px 0; - padding: 3px 5px 3px 19px; -} -.chosen-rtl .chosen-choices li.search-choice .search-choice-close { - right: auto; - left: 4px; -} -.chosen-rtl.chosen-container-single-nosearch .chosen-search, -.chosen-rtl .chosen-drop { - left: 9999px; -} -.chosen-rtl.chosen-container-single .chosen-results { - margin: 0 0 4px 4px; - padding: 0 4px 0 0; -} -.chosen-rtl .chosen-results li.group-option { - padding-right: 15px; - padding-left: 0; -} -.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { - border-right: none; -} -.chosen-rtl .chosen-search input[type="text"] { - padding: 4px 5px 4px 20px; - background: white url('chosen-sprite.png') no-repeat -30px -20px; - background: url('chosen-sprite.png') no-repeat -30px -20px; - direction: rtl; -} -.chosen-rtl.chosen-container-single .chosen-single div b { - background-position: 6px 2px; -} -.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b { - background-position: -12px 2px; -} - -/* @end */ -/* @group Retina compatibility */ -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) { - .chosen-rtl .chosen-search input[type="text"], - .chosen-container-single .chosen-single abbr, - .chosen-container-single .chosen-single div b, - .chosen-container-single .chosen-search input[type="text"], - .chosen-container-multi .chosen-choices .search-choice .search-choice-close, - .chosen-container .chosen-results-scroll-down span, - .chosen-container .chosen-results-scroll-up span { - background-image: url('chosen-sprite@2x.png') !important; - background-size: 52px 37px !important; - background-repeat: no-repeat !important; - } -} -/* @end */ diff --git a/vendor/assets/stylesheets/codemirror.css b/vendor/assets/stylesheets/codemirror.css deleted file mode 100644 index b962b38..0000000 --- a/vendor/assets/stylesheets/codemirror.css +++ /dev/null @@ -1,340 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; - color: black; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - white-space: nowrap; -} - -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } - -/* CURSOR */ - -.CodeMirror-cursor { - border-left: 1px solid black; - border-right: none; - width: 0; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.cm-fat-cursor .CodeMirror-cursor { - width: auto; - border: 0 !important; - background: #7e7; -} -.cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; -} - -.cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; - background-color: #7e7; -} -@-moz-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@-webkit-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} - -/* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror-overwrite .CodeMirror-cursor {} - -.cm-tab { display: inline-block; text-decoration: inherit; } - -.CodeMirror-rulers { - position: absolute; - left: 0; right: 0; top: -50px; bottom: -20px; - overflow: hidden; -} -.CodeMirror-ruler { - border-left: 1px solid #ccc; - top: 0; bottom: 0; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable, -.cm-s-default .cm-punctuation, -.cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3 {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -.CodeMirror-composing { border-bottom: 2px solid; } - -/* Default styles for common addons */ - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - position: relative; - overflow: hidden; - background: white; -} - -.CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; -} -.CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actual scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - min-height: 100%; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - display: inline-block; - vertical-align: top; - margin-bottom: -30px; -} -.CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - background: none !important; - border: none !important; -} -.CodeMirror-gutter-background { - position: absolute; - top: 0; bottom: 0; - z-index: 4; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} -.CodeMirror-gutter-wrapper ::selection { background-color: transparent } -.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } - -.CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ -} -.CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; - -webkit-tap-highlight-color: transparent; - -webkit-font-variant-ligatures: contextual; - font-variant-ligatures: contextual; -} -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - overflow: auto; -} - -.CodeMirror-widget {} - -.CodeMirror-rtl pre { direction: rtl; } - -.CodeMirror-code { - outline: none; -} - -/* Force content-box sizing for the elements where we expect it */ -.CodeMirror-scroll, -.CodeMirror-sizer, -.CodeMirror-gutter, -.CodeMirror-gutters, -.CodeMirror-linenumber { - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} - -.CodeMirror-cursor { - position: absolute; - pointer-events: none; -} -.CodeMirror-measure pre { position: static; } - -div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; -} -div.CodeMirror-dragcursors { - visibility: visible; -} - -.CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } -.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } - -.cm-searching { - background: #ffa; - background: rgba(255, 255, 0, .4); -} - -/* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } -} - -/* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } - -/* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } diff --git a/vendor/assets/stylesheets/journal/_bootswatch.scss b/vendor/assets/stylesheets/journal/_bootswatch.scss deleted file mode 100644 index e8fc579..0000000 --- a/vendor/assets/stylesheets/journal/_bootswatch.scss +++ /dev/null @@ -1,145 +0,0 @@ -// Journal 3.3.5 -// Bootswatch -// ----------------------------------------------------- - -//$web-font-path: "https://fonts.googleapis.com/css?family=News+Cycle:400,700" !default; -//@import url($web-font-path); - -// Navbar ===================================================================== - -.navbar { - font-size: 18px; - font-family: $font-family-sans-serif; - font-weight: $headings-font-weight; - - &-default { - - .badge { - background-color: #000; - color: #fff; - } - } - - &-inverse { - - .badge { - background-color: #fff; - color: $navbar-inverse-bg; - } - } -} - -.navbar-brand { - font-size: inherit; - font-weight: $headings-font-weight; - text-transform: uppercase; -} - -// Buttons ==================================================================== - -// Typography ================================================================= - -// Tables ===================================================================== - -// Forms ====================================================================== - -.has-warning { - .help-block, - .control-label, - .radio, - .checkbox, - .radio-inline, - .checkbox-inline, - &.radio label, - &.checkbox label, - &.radio-inline label, - &.checkbox-inline label, - .form-control-feedback { - color: $brand-danger; - } - - .form-control, - .form-control:focus { - border-color: $brand-danger; - } -} - -.has-error { - .help-block, - .control-label, - .radio, - .checkbox, - .radio-inline, - .checkbox-inline, - &.radio label, - &.checkbox label, - &.radio-inline label, - &.checkbox-inline label, - .form-control-feedback { - color: $brand-primary; - } - - .form-control, - .form-control:focus { - border-color: $brand-primary; - } -} - -.has-success { - .help-block, - .control-label, - .radio, - .checkbox, - .radio-inline, - .checkbox-inline, - &.radio label, - &.checkbox label, - &.radio-inline label, - &.checkbox-inline label, - .form-control-feedback { - color: $brand-success; - } - - .form-control, - .form-control:focus { - border-color: $brand-success; - } -} - -// Navs ======================================================================= - -// Indicators ================================================================= - -.badge { - padding-bottom: 4px; - vertical-align: 3px; - font-size: 10px; -} - -// Progress bars ============================================================== - -// Containers ================================================================= - -.jumbotron { - - h1, h2, h3, h4, h5, h6 { - font-family: $font-family-sans-serif; - font-weight: $headings-font-weight; - color: #000; - } -} - -.panel { - - &-primary, - &-success, - &-warning, - &-danger, - &-info { - .panel-title { - color: #fff; - } - } - - -} diff --git a/vendor/assets/stylesheets/journal/_variables.scss b/vendor/assets/stylesheets/journal/_variables.scss deleted file mode 100644 index 6257e4e..0000000 --- a/vendor/assets/stylesheets/journal/_variables.scss +++ /dev/null @@ -1,870 +0,0 @@ -$bootstrap-sass-asset-helper: false !default; -// Journal 3.3.6 -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -$gray-base: #000 !default; -$gray-darker: lighten($gray-base, 13.5%) !default; // #222 -$gray-dark: lighten($gray-base, 20%) !default; // #333 -$gray: #777 !default; // #555 -$gray-light: lighten($gray-base, 60%) !default; // #999 -$gray-lighter: lighten($gray-base, 93.5%) !default; // #eee - -$brand-primary: #EB6864 !default; -$brand-success: #22B24C !default; -$brand-info: #369 !default; -$brand-warning: #F5E625 !default; -$brand-danger: #F57A00 !default; - - -//== Scaffolding -// -//## Settings for some of the most global styles. - -//** Background color for ``. -$body-bg: #fff !default; -//** Global text color on ``. -$text-color: $gray !default; - -//** Global textual link color. -$link-color: $brand-primary !default; -//** Link hover color set via `darken()` function. -$link-hover-color: darken($link-color, 15%) !default; -//** Link hover decoration. -$link-hover-decoration: underline !default; - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -$font-family-sans-serif: "News Cycle", "Arial Narrow Bold", sans-serif !default; -$font-family-serif: Georgia, "Times New Roman", Times, serif !default; -//** Default monospace fonts for ``, ``, and `
      `.
      -$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
      -$font-family-base:        $font-family-serif !default;
      -
      -$font-size-base:          15px !default;
      -$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
      -$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
      -$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
      -$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-h5:            $font-size-base !default;
      -$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -//** Unit-less `line-height` for use in components like buttons.
      -$line-height-base:        1.428571429 !default; // 20/14
      -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
      -$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
      -
      -//** By default, this inherits from the ``.
      -$headings-font-family:    $font-family-sans-serif !default;
      -$headings-font-weight:    700 !default;
      -$headings-line-height:    1.1 !default;
      -$headings-color:          #000 !default;
      -
      -
      -//== Iconography
      -//
      -//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
      -
      -//** Load fonts from this directory.
      -$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
      -//** File name for all font files.
      -$icon-font-name:          "glyphicons-halflings-regular" !default;
      -//** Element ID within SVG icon file.
      -$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
      -
      -
      -//== Components
      -//
      -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
      -
      -$padding-base-vertical:     8px !default;
      -$padding-base-horizontal:   12px !default;
      -
      -$padding-large-vertical:    14px !default;
      -$padding-large-horizontal:  16px !default;
      -
      -$padding-small-vertical:    5px !default;
      -$padding-small-horizontal:  10px !default;
      -
      -$padding-xs-vertical:       1px !default;
      -$padding-xs-horizontal:     5px !default;
      -
      -$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
      -$line-height-small:         1.5 !default;
      -
      -$border-radius-base:        4px !default;
      -$border-radius-large:       6px !default;
      -$border-radius-small:       3px !default;
      -
      -//** Global color for active items (e.g., navs or dropdowns).
      -$component-active-color:    #fff !default;
      -//** Global background color for active items (e.g., navs or dropdowns).
      -$component-active-bg:       $brand-primary !default;
      -
      -//** Width of the `border` for generating carets that indicator dropdowns.
      -$caret-width-base:          4px !default;
      -//** Carets increase slightly in size for larger components.
      -$caret-width-large:         5px !default;
      -
      -
      -//== Tables
      -//
      -//## Customizes the `.table` component with basic values, each used across all table variations.
      -
      -//** Padding for ``s and ``s.
      -$table-cell-padding:            8px !default;
      -//** Padding for cells in `.table-condensed`.
      -$table-condensed-cell-padding:  5px !default;
      -
      -//** Default background color used for all tables.
      -$table-bg:                      transparent !default;
      -//** Background color used for `.table-striped`.
      -$table-bg-accent:               #f9f9f9 !default;
      -//** Background color used for `.table-hover`.
      -$table-bg-hover:                #f5f5f5 !default;
      -$table-bg-active:               $table-bg-hover !default;
      -
      -//** Border color for table and cell borders.
      -$table-border-color:            #ddd !default;
      -
      -
      -//== Buttons
      -//
      -//## For each of Bootstrap's buttons, define text, background and border color.
      -
      -$btn-font-weight:                normal !default;
      -
      -$btn-default-color:              #fff !default;
      -$btn-default-bg:                 $gray-light !default;
      -$btn-default-border:             $btn-default-bg !default;
      -
      -$btn-primary-color:              $btn-default-color !default;
      -$btn-primary-bg:                 $brand-primary !default;
      -$btn-primary-border:             $btn-primary-bg !default;
      -
      -$btn-success-color:              $btn-default-color !default;
      -$btn-success-bg:                 $brand-success !default;
      -$btn-success-border:             $btn-success-bg !default;
      -
      -$btn-info-color:                 $btn-default-color !default;
      -$btn-info-bg:                    $brand-info !default;
      -$btn-info-border:                $btn-info-bg !default;
      -
      -$btn-warning-color:              $btn-default-color !default;
      -$btn-warning-bg:                 $brand-warning !default;
      -$btn-warning-border:             $btn-warning-bg !default;
      -
      -$btn-danger-color:               $btn-default-color !default;
      -$btn-danger-bg:                  $brand-danger !default;
      -$btn-danger-border:              $btn-danger-bg !default;
      -
      -$btn-link-disabled-color:        $gray-light !default;
      -
      -// Allows for customizing button radius independently from global border radius
      -$btn-border-radius-base:         $border-radius-base !default;
      -$btn-border-radius-large:        $border-radius-large !default;
      -$btn-border-radius-small:        $border-radius-small !default;
      -
      -
      -//== Forms
      -//
      -//##
      -
      -//** `` background color
      -$input-bg:                       #fff !default;
      -//** `` background color
      -$input-bg-disabled:              $gray-lighter !default;
      -
      -//** Text color for ``s
      -$input-color:                    $text-color !default;
      -//** `` border color
      -$input-border:                   #ccc !default;
      -
      -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
      -//** Default `.form-control` border radius
      -// This has no effect on ``s in CSS.
      -$input-border-radius:            $border-radius-base !default;
      -//** Large `.form-control` border radius
      -$input-border-radius-large:      $border-radius-large !default;
      -//** Small `.form-control` border radius
      -$input-border-radius-small:      $border-radius-small !default;
      -
      -//** Border color for inputs on focus
      -$input-border-focus:             #66afe9 !default;
      -
      -//** Placeholder text color
      -$input-color-placeholder:        $gray-light !default;
      -
      -//** Default `.form-control` height
      -$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
      -//** Large `.form-control` height
      -$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
      -//** Small `.form-control` height
      -$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
      -
      -//** `.form-group` margin
      -$form-group-margin-bottom:       15px !default;
      -
      -$legend-color:                   $text-color !default;
      -$legend-border-color:            #e5e5e5 !default;
      -
      -//** Background color for textual input addons
      -$input-group-addon-bg:           $gray-lighter !default;
      -//** Border color for textual input addons
      -$input-group-addon-border-color: $input-border !default;
      -
      -//** Disabled cursor for form controls and buttons.
      -$cursor-disabled:                not-allowed !default;
      -
      -
      -//== Dropdowns
      -//
      -//## Dropdown menu container and contents.
      -
      -//** Background for the dropdown menu.
      -$dropdown-bg:                    #fff !default;
      -//** Dropdown menu `border-color`.
      -$dropdown-border:                rgba(0,0,0,.15) !default;
      -//** Dropdown menu `border-color` **for IE8**.
      -$dropdown-fallback-border:       #ccc !default;
      -//** Divider color for between dropdown items.
      -$dropdown-divider-bg:            #e5e5e5 !default;
      -
      -//** Dropdown link text color.
      -$dropdown-link-color:            $gray-dark !default;
      -//** Hover color for dropdown links.
      -$dropdown-link-hover-color:      #fff !default;
      -//** Hover background for dropdown links.
      -$dropdown-link-hover-bg:         $component-active-bg !default;
      -
      -//** Active dropdown menu item text color.
      -$dropdown-link-active-color:     #fff !default;
      -//** Active dropdown menu item background color.
      -$dropdown-link-active-bg:        $component-active-bg !default;
      -
      -//** Disabled dropdown menu item background color.
      -$dropdown-link-disabled-color:   $gray-light !default;
      -
      -//** Text color for headers within dropdown menus.
      -$dropdown-header-color:          $gray-light !default;
      -
      -//** Deprecated `$dropdown-caret-color` as of v3.1.0
      -$dropdown-caret-color:           #000 !default;
      -
      -
      -//-- Z-index master list
      -//
      -// Warning: Avoid customizing these values. They're used for a bird's eye view
      -// of components dependent on the z-axis and are designed to all work together.
      -//
      -// Note: These variables are not generated into the Customizer.
      -
      -$zindex-navbar:            1000 !default;
      -$zindex-dropdown:          1000 !default;
      -$zindex-popover:           1060 !default;
      -$zindex-tooltip:           1070 !default;
      -$zindex-navbar-fixed:      1030 !default;
      -$zindex-modal-background:  1040 !default;
      -$zindex-modal:             1050 !default;
      -
      -
      -//== Media queries breakpoints
      -//
      -//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
      -
      -// Extra small screen / phone
      -//** Deprecated `$screen-xs` as of v3.0.1
      -$screen-xs:                  480px !default;
      -//** Deprecated `$screen-xs-min` as of v3.2.0
      -$screen-xs-min:              $screen-xs !default;
      -//** Deprecated `$screen-phone` as of v3.0.1
      -$screen-phone:               $screen-xs-min !default;
      -
      -// Small screen / tablet
      -//** Deprecated `$screen-sm` as of v3.0.1
      -$screen-sm:                  768px !default;
      -$screen-sm-min:              $screen-sm !default;
      -//** Deprecated `$screen-tablet` as of v3.0.1
      -$screen-tablet:              $screen-sm-min !default;
      -
      -// Medium screen / desktop
      -//** Deprecated `$screen-md` as of v3.0.1
      -$screen-md:                  992px !default;
      -$screen-md-min:              $screen-md !default;
      -//** Deprecated `$screen-desktop` as of v3.0.1
      -$screen-desktop:             $screen-md-min !default;
      -
      -// Large screen / wide desktop
      -//** Deprecated `$screen-lg` as of v3.0.1
      -$screen-lg:                  1200px !default;
      -$screen-lg-min:              $screen-lg !default;
      -//** Deprecated `$screen-lg-desktop` as of v3.0.1
      -$screen-lg-desktop:          $screen-lg-min !default;
      -
      -// So media queries don't overlap when required, provide a maximum
      -$screen-xs-max:              ($screen-sm-min - 1) !default;
      -$screen-sm-max:              ($screen-md-min - 1) !default;
      -$screen-md-max:              ($screen-lg-min - 1) !default;
      -
      -
      -//== Grid system
      -//
      -//## Define your custom responsive grid.
      -
      -//** Number of columns in the grid.
      -$grid-columns:              12 !default;
      -//** Padding between columns. Gets divided in half for the left and right.
      -$grid-gutter-width:         30px !default;
      -// Navbar collapse
      -//** Point at which the navbar becomes uncollapsed.
      -$grid-float-breakpoint:     $screen-sm-min !default;
      -//** Point at which the navbar begins collapsing.
      -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
      -
      -
      -//== Container sizes
      -//
      -//## Define the maximum width of `.container` for different screen sizes.
      -
      -// Small screen / tablet
      -$container-tablet:             (720px + $grid-gutter-width) !default;
      -//** For `$screen-sm-min` and up.
      -$container-sm:                 $container-tablet !default;
      -
      -// Medium screen / desktop
      -$container-desktop:            (940px + $grid-gutter-width) !default;
      -//** For `$screen-md-min` and up.
      -$container-md:                 $container-desktop !default;
      -
      -// Large screen / wide desktop
      -$container-large-desktop:      (1140px + $grid-gutter-width) !default;
      -//** For `$screen-lg-min` and up.
      -$container-lg:                 $container-large-desktop !default;
      -
      -
      -//== Navbar
      -//
      -//##
      -
      -// Basics of a navbar
      -$navbar-height:                    60px !default;
      -$navbar-margin-bottom:             $line-height-computed !default;
      -$navbar-border-radius:             $border-radius-base !default;
      -$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
      -$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
      -$navbar-collapse-max-height:       340px !default;
      -
      -$navbar-default-color:             #000 !default;
      -$navbar-default-bg:                #fff !default;
      -$navbar-default-border:            darken($navbar-default-bg, 6.5%) !default;
      -
      -// Navbar links
      -$navbar-default-link-color:                #000 !default;
      -$navbar-default-link-hover-color:          #000 !default;
      -$navbar-default-link-hover-bg:             darken($navbar-default-bg, 6.5%) !default;
      -$navbar-default-link-active-color:         #000 !default;
      -$navbar-default-link-active-bg:            darken($navbar-default-bg, 6.5%) !default;
      -$navbar-default-link-disabled-color:       #ccc !default;
      -$navbar-default-link-disabled-bg:          transparent !default;
      -
      -// Navbar brand label
      -$navbar-default-brand-color:               $navbar-default-link-color !default;
      -$navbar-default-brand-hover-color:         $navbar-default-link-hover-color !default;
      -$navbar-default-brand-hover-bg:            darken($navbar-default-bg, 6.5%) !default;
      -
      -// Navbar toggle
      -$navbar-default-toggle-hover-bg:           #ddd !default;
      -$navbar-default-toggle-icon-bar-bg:        #ccc !default;
      -$navbar-default-toggle-border-color:       #ddd !default;
      -
      -
      -//=== Inverted navbar
      -// Reset inverted navbar basics
      -$navbar-inverse-color:                      #fff !default;
      -$navbar-inverse-bg:                         $brand-primary !default;
      -$navbar-inverse-border:                     darken($navbar-inverse-bg, 10%) !default;
      -
      -// Inverted navbar links
      -$navbar-inverse-link-color:                 #fff !default;
      -$navbar-inverse-link-hover-color:           #fff !default;
      -$navbar-inverse-link-hover-bg:              darken($navbar-inverse-bg, 6.5%) !default;
      -$navbar-inverse-link-active-color:          #fff !default;
      -$navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 6.5%) !default;
      -$navbar-inverse-link-disabled-color:        #444 !default;
      -$navbar-inverse-link-disabled-bg:           transparent !default;
      -
      -// Inverted navbar brand label
      -$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;
      -$navbar-inverse-brand-hover-color:          #fff !default;
      -$navbar-inverse-brand-hover-bg:             darken($navbar-inverse-bg, 6.5%) !default;
      -
      -// Inverted navbar toggle
      -$navbar-inverse-toggle-hover-bg:            darken($navbar-inverse-bg, 10%) !default;
      -$navbar-inverse-toggle-icon-bar-bg:         #fff !default;
      -$navbar-inverse-toggle-border-color:        darken($navbar-inverse-bg, 10%) !default;
      -
      -
      -//== Navs
      -//
      -//##
      -
      -//=== Shared nav styles
      -$nav-link-padding:                          10px 15px !default;
      -$nav-link-hover-bg:                         $gray-lighter !default;
      -
      -$nav-disabled-link-color:                   $gray-light !default;
      -$nav-disabled-link-hover-color:             $gray-light !default;
      -
      -//== Tabs
      -$nav-tabs-border-color:                     #ddd !default;
      -
      -$nav-tabs-link-hover-border-color:          $gray-lighter !default;
      -
      -$nav-tabs-active-link-hover-bg:             $body-bg !default;
      -$nav-tabs-active-link-hover-color:          $gray !default;
      -$nav-tabs-active-link-hover-border-color:   #ddd !default;
      -
      -$nav-tabs-justified-link-border-color:            #ddd !default;
      -$nav-tabs-justified-active-link-border-color:     $body-bg !default;
      -
      -//== Pills
      -$nav-pills-border-radius:                   $border-radius-base !default;
      -$nav-pills-active-link-hover-bg:            $component-active-bg !default;
      -$nav-pills-active-link-hover-color:         $component-active-color !default;
      -
      -
      -//== Pagination
      -//
      -//##
      -
      -$pagination-color:                     $link-color !default;
      -$pagination-bg:                        #fff !default;
      -$pagination-border:                    #ddd !default;
      -
      -$pagination-hover-color:               $link-hover-color !default;
      -$pagination-hover-bg:                  $gray-lighter !default;
      -$pagination-hover-border:              #ddd !default;
      -
      -$pagination-active-color:              $gray-light !default;
      -$pagination-active-bg:                 #f5f5f5 !default;
      -$pagination-active-border:             #ddd !default;
      -
      -$pagination-disabled-color:            $gray-light !default;
      -$pagination-disabled-bg:               #fff !default;
      -$pagination-disabled-border:           #ddd !default;
      -
      -
      -//== Pager
      -//
      -//##
      -
      -$pager-bg:                             $pagination-bg !default;
      -$pager-border:                         $pagination-border !default;
      -$pager-border-radius:                  15px !default;
      -
      -$pager-hover-bg:                       $pagination-hover-bg !default;
      -
      -$pager-active-bg:                      $pagination-active-bg !default;
      -$pager-active-color:                   $pagination-active-color !default;
      -
      -$pager-disabled-color:                 $gray-light !default;
      -
      -
      -//== Jumbotron
      -//
      -//##
      -
      -$jumbotron-padding:              30px !default;
      -$jumbotron-color:                inherit !default;
      -$jumbotron-bg:                   $gray-lighter !default;
      -$jumbotron-heading-color:        inherit !default;
      -$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
      -$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
      -
      -
      -//== Form states and alerts
      -//
      -//## Define colors for form feedback states and, by default, alerts.
      -
      -$state-success-text:             #468847 !default;
      -$state-success-bg:               #dff0d8 !default;
      -$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
      -
      -$state-info-text:                #3a87ad !default;
      -$state-info-bg:                  #d9edf7 !default;
      -$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
      -
      -$state-warning-text:             #c09853 !default;
      -$state-warning-bg:               #fcf8e3 !default;
      -$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 3%) !default;
      -
      -$state-danger-text:              #b94a48 !default;
      -$state-danger-bg:                #f2dede !default;
      -$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 3%) !default;
      -
      -
      -//== Tooltips
      -//
      -//##
      -
      -//** Tooltip max width
      -$tooltip-max-width:           200px !default;
      -//** Tooltip text color
      -$tooltip-color:               #fff !default;
      -//** Tooltip background color
      -$tooltip-bg:                  #000 !default;
      -$tooltip-opacity:             .9 !default;
      -
      -//** Tooltip arrow width
      -$tooltip-arrow-width:         5px !default;
      -//** Tooltip arrow color
      -$tooltip-arrow-color:         $tooltip-bg !default;
      -
      -
      -//== Popovers
      -//
      -//##
      -
      -//** Popover body background color
      -$popover-bg:                          #fff !default;
      -//** Popover maximum width
      -$popover-max-width:                   276px !default;
      -//** Popover border color
      -$popover-border-color:                rgba(0,0,0,.2) !default;
      -//** Popover fallback border color
      -$popover-fallback-border-color:       #ccc !default;
      -
      -//** Popover title background color
      -$popover-title-bg:                    darken($popover-bg, 3%) !default;
      -
      -//** Popover arrow width
      -$popover-arrow-width:                 10px !default;
      -//** Popover arrow color
      -$popover-arrow-color:                 $popover-bg !default;
      -
      -//** Popover outer arrow width
      -$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
      -//** Popover outer arrow color
      -$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
      -//** Popover outer arrow fallback color
      -$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
      -
      -
      -//== Labels
      -//
      -//##
      -
      -//** Default label background color
      -$label-default-bg:            $btn-default-bg !default;
      -//** Primary label background color
      -$label-primary-bg:            $brand-primary !default;
      -//** Success label background color
      -$label-success-bg:            $brand-success !default;
      -//** Info label background color
      -$label-info-bg:               $brand-info !default;
      -//** Warning label background color
      -$label-warning-bg:            $brand-warning !default;
      -//** Danger label background color
      -$label-danger-bg:             $brand-danger !default;
      -
      -//** Default label text color
      -$label-color:                 #fff !default;
      -//** Default text color of a linked label
      -$label-link-hover-color:      #fff !default;
      -
      -
      -//== Modals
      -//
      -//##
      -
      -//** Padding applied to the modal body
      -$modal-inner-padding:         20px !default;
      -
      -//** Padding applied to the modal title
      -$modal-title-padding:         15px !default;
      -//** Modal title line-height
      -$modal-title-line-height:     $line-height-base !default;
      -
      -//** Background color of modal content area
      -$modal-content-bg:                             #fff !default;
      -//** Modal content border color
      -$modal-content-border-color:                   rgba(0,0,0,.2) !default;
      -//** Modal content border color **for IE8**
      -$modal-content-fallback-border-color:          #999 !default;
      -
      -//** Modal backdrop background color
      -$modal-backdrop-bg:           #000 !default;
      -//** Modal backdrop opacity
      -$modal-backdrop-opacity:      .5 !default;
      -//** Modal header border color
      -$modal-header-border-color:   #e5e5e5 !default;
      -//** Modal footer border color
      -$modal-footer-border-color:   $modal-header-border-color !default;
      -
      -$modal-lg:                    900px !default;
      -$modal-md:                    600px !default;
      -$modal-sm:                    300px !default;
      -
      -
      -//== Alerts
      -//
      -//## Define alert colors, border radius, and padding.
      -
      -$alert-padding:               15px !default;
      -$alert-border-radius:         $border-radius-base !default;
      -$alert-link-font-weight:      bold !default;
      -
      -$alert-success-bg:            $state-success-bg !default;
      -$alert-success-text:          $state-success-text !default;
      -$alert-success-border:        $state-success-border !default;
      -
      -$alert-info-bg:               $state-info-bg !default;
      -$alert-info-text:             $state-info-text !default;
      -$alert-info-border:           $state-info-border !default;
      -
      -$alert-warning-bg:            $state-warning-bg !default;
      -$alert-warning-text:          $state-warning-text !default;
      -$alert-warning-border:        $state-warning-border !default;
      -
      -$alert-danger-bg:             $state-danger-bg !default;
      -$alert-danger-text:           $state-danger-text !default;
      -$alert-danger-border:         $state-danger-border !default;
      -
      -
      -//== Progress bars
      -//
      -//##
      -
      -//** Background color of the whole progress component
      -$progress-bg:                 #f5f5f5 !default;
      -//** Progress bar text color
      -$progress-bar-color:          #fff !default;
      -//** Variable for setting rounded corners on progress bar.
      -$progress-border-radius:      $border-radius-base !default;
      -
      -//** Default progress bar color
      -$progress-bar-bg:             $brand-primary !default;
      -//** Success progress bar color
      -$progress-bar-success-bg:     $brand-success !default;
      -//** Warning progress bar color
      -$progress-bar-warning-bg:     $brand-warning !default;
      -//** Danger progress bar color
      -$progress-bar-danger-bg:      $brand-danger !default;
      -//** Info progress bar color
      -$progress-bar-info-bg:        $brand-info !default;
      -
      -
      -//== List group
      -//
      -//##
      -
      -//** Background color on `.list-group-item`
      -$list-group-bg:                 #fff !default;
      -//** `.list-group-item` border color
      -$list-group-border:             #ddd !default;
      -//** List group border radius
      -$list-group-border-radius:      $border-radius-base !default;
      -
      -//** Background color of single list items on hover
      -$list-group-hover-bg:           #f5f5f5 !default;
      -//** Text color of active list items
      -$list-group-active-color:       $component-active-color !default;
      -//** Background color of active list items
      -$list-group-active-bg:          $component-active-bg !default;
      -//** Border color of active list elements
      -$list-group-active-border:      $list-group-active-bg !default;
      -//** Text color for content within active list items
      -$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
      -
      -//** Text color of disabled list items
      -$list-group-disabled-color:      $gray-light !default;
      -//** Background color of disabled list items
      -$list-group-disabled-bg:         $gray-lighter !default;
      -//** Text color for content within disabled list items
      -$list-group-disabled-text-color: $list-group-disabled-color !default;
      -
      -$list-group-link-color:         #555 !default;
      -$list-group-link-hover-color:   $list-group-link-color !default;
      -$list-group-link-heading-color: #333 !default;
      -
      -
      -//== Panels
      -//
      -//##
      -
      -$panel-bg:                    #fff !default;
      -$panel-body-padding:          15px !default;
      -$panel-heading-padding:       10px 15px !default;
      -$panel-footer-padding:        $panel-heading-padding !default;
      -$panel-border-radius:         $border-radius-base !default;
      -
      -//** Border color for elements within panels
      -$panel-inner-border:          #ddd !default;
      -$panel-footer-bg:             #f5f5f5 !default;
      -
      -$panel-default-text:          $text-color !default;
      -$panel-default-border:        #ddd !default;
      -$panel-default-heading-bg:    #f5f5f5 !default;
      -
      -$panel-primary-text:          #fff !default;
      -$panel-primary-border:        $brand-primary !default;
      -$panel-primary-heading-bg:    $brand-primary !default;
      -
      -$panel-success-text:          $state-success-text !default;
      -$panel-success-border:        $brand-success !default;
      -$panel-success-heading-bg:    $brand-success !default;
      -
      -$panel-info-text:             $state-info-text !default;
      -$panel-info-border:           $brand-info !default;
      -$panel-info-heading-bg:       $brand-info !default;
      -
      -$panel-warning-text:          $state-warning-text !default;
      -$panel-warning-border:        $brand-warning !default;
      -$panel-warning-heading-bg:    $brand-warning !default;
      -
      -$panel-danger-text:           $state-danger-text !default;
      -$panel-danger-border:         $brand-danger !default;
      -$panel-danger-heading-bg:     $brand-danger !default;
      -
      -
      -//== Thumbnails
      -//
      -//##
      -
      -//** Padding around the thumbnail image
      -$thumbnail-padding:           4px !default;
      -//** Thumbnail background color
      -$thumbnail-bg:                $body-bg !default;
      -//** Thumbnail border color
      -$thumbnail-border:            #ddd !default;
      -//** Thumbnail border radius
      -$thumbnail-border-radius:     $border-radius-base !default;
      -
      -//** Custom text color for thumbnail captions
      -$thumbnail-caption-color:     $text-color !default;
      -//** Padding around the thumbnail caption
      -$thumbnail-caption-padding:   9px !default;
      -
      -
      -//== Wells
      -//
      -//##
      -
      -$well-bg:                     #f5f5f5 !default;
      -$well-border:                 darken($well-bg, 7%) !default;
      -
      -
      -//== Badges
      -//
      -//##
      -
      -$badge-color:                 #fff !default;
      -//** Linked badge text color on hover
      -$badge-link-hover-color:      #fff !default;
      -$badge-bg:                    $link-color !default;
      -
      -//** Badge text color in active nav link
      -$badge-active-color:          $link-color !default;
      -//** Badge background color in active nav link
      -$badge-active-bg:             #fff !default;
      -
      -$badge-font-weight:           bold !default;
      -$badge-line-height:           1 !default;
      -$badge-border-radius:         10px !default;
      -
      -
      -//== Breadcrumbs
      -//
      -//##
      -
      -$breadcrumb-padding-vertical:   8px !default;
      -$breadcrumb-padding-horizontal: 15px !default;
      -//** Breadcrumb background color
      -$breadcrumb-bg:                 #f5f5f5 !default;
      -//** Breadcrumb text color
      -$breadcrumb-color:              #ccc !default;
      -//** Text color of current page in the breadcrumb
      -$breadcrumb-active-color:       $gray-light !default;
      -//** Textual separator for between breadcrumb elements
      -$breadcrumb-separator:          "/" !default;
      -
      -
      -//== Carousel
      -//
      -//##
      -
      -$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
      -
      -$carousel-control-color:                      #fff !default;
      -$carousel-control-width:                      15% !default;
      -$carousel-control-opacity:                    .5 !default;
      -$carousel-control-font-size:                  20px !default;
      -
      -$carousel-indicator-active-bg:                #fff !default;
      -$carousel-indicator-border-color:             #fff !default;
      -
      -$carousel-caption-color:                      #fff !default;
      -
      -
      -//== Close
      -//
      -//##
      -
      -$close-font-weight:           bold !default;
      -$close-color:                 #000 !default;
      -$close-text-shadow:           0 1px 0 #fff !default;
      -
      -
      -//== Code
      -//
      -//##
      -
      -$code-color:                  #c7254e !default;
      -$code-bg:                     #f9f2f4 !default;
      -
      -$kbd-color:                   #fff !default;
      -$kbd-bg:                      #333 !default;
      -
      -$pre-bg:                      #f5f5f5 !default;
      -$pre-color:                   $gray-dark !default;
      -$pre-border-color:            #ccc !default;
      -$pre-scrollable-max-height:   340px !default;
      -
      -
      -//== Type
      -//
      -//##
      -
      -//** Horizontal offset for forms and lists.
      -$component-offset-horizontal: 180px !default;
      -//** Text muted color
      -$text-muted:                  $gray-light !default;
      -//** Abbreviations and acronyms border color
      -$abbr-border-color:           $gray-light !default;
      -//** Headings small color
      -$headings-small-color:        $gray-light !default;
      -//** Blockquote small color
      -$blockquote-small-color:      $gray-light !default;
      -//** Blockquote font size
      -$blockquote-font-size:        ($font-size-base * 1.25) !default;
      -//** Blockquote border color
      -$blockquote-border-color:     $gray-lighter !default;
      -//** Page header border color
      -$page-header-border-color:    $gray-lighter !default;
      -//** Width of horizontal description list titles
      -$dl-horizontal-offset:        $component-offset-horizontal !default;
      -//** Point at which .dl-horizontal becomes horizontal
      -$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
      -//** Horizontal line color.
      -$hr-border:                   $gray-lighter !default;
      diff --git a/vendor/assets/stylesheets/paper/_bootswatch.scss b/vendor/assets/stylesheets/paper/_bootswatch.scss
      deleted file mode 100644
      index af3dc4a..0000000
      --- a/vendor/assets/stylesheets/paper/_bootswatch.scss
      +++ /dev/null
      @@ -1,611 +0,0 @@
      -// Paper 3.3.5
      -// Bootswatch
      -// -----------------------------------------------------
      -
      -//$web-font-path: "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" !default;
      -//@import url($web-font-path);
      -
      -// Navbar =====================================================================
      -
      -.navbar {
      -  border: none;
      -  @include box-shadow(0 1px 2px rgba(0,0,0,.3));
      -
      -  &-brand {
      -    font-size: 24px;
      -  }
      -
      -  &-inverse {
      -    .navbar-form {
      -
      -      input[type=text],
      -      input[type=password] {
      -        color: #fff;
      -        @include box-shadow(inset 0 -1px 0 $navbar-inverse-link-color);
      -        @include placeholder($navbar-inverse-link-color);
      -
      -        &:focus {
      -          @include box-shadow(inset 0 -2px 0 #fff);
      -        }
      -      }
      -    }
      -  }
      -}
      -
      -// Buttons ====================================================================
      -
      -@mixin btn($class,$bg){
      -  .btn-#{$class} {
      -    background-size: 200%;
      -    background-position: 50%;
      -
      -    &:focus {
      -      background-color: $bg;
      -    }
      -
      -    &:hover,
      -    &:active:hover {
      -      background-color: darken($bg, 6%);
      -    }
      -
      -    &:active {
      -      background-color: darken($bg, 12%);
      -      @include gradient-radial(darken($bg, 12%) 10%, $bg 11%);
      -      background-size: 1000%;
      -      @include box-shadow(2px 2px 4px rgba(0,0,0,.4));
      -    }
      -  }
      -}
      -
      -@include btn(default,$btn-default-bg);
      -@include btn(primary,$btn-primary-bg);
      -@include btn(success,$btn-success-bg);
      -@include btn(info,$btn-info-bg);
      -@include btn(warning,$btn-warning-bg);
      -@include btn(danger,$btn-danger-bg);
      -@include btn(link,#fff);
      -
      -.btn {
      -  text-transform: uppercase;
      -  border: none;
      -  @include box-shadow(1px 1px 4px rgba(0,0,0,.4));
      -  @include transition(all 0.4s);
      -
      -  &-link {
      -    border-radius: $btn-border-radius-base;
      -    @include box-shadow(none);
      -    color: $btn-default-color;
      -
      -    &:hover,
      -    &:focus {
      -      @include box-shadow(none);
      -      color: $btn-default-color;
      -      text-decoration: none;
      -    }
      -  }
      -
      -  &-default {
      -
      -    &.disabled {
      -      background-color: rgba(0, 0, 0, 0.1);
      -      color: rgba(0, 0, 0, 0.4);
      -      opacity: 1;
      -    }
      -  }
      -}
      -
      -.btn-group {
      -  .btn + .btn,
      -  .btn + .btn-group,
      -  .btn-group + .btn,
      -  .btn-group + .btn-group {
      -    margin-left: 0;
      -  }
      -
      -  &-vertical {
      -    > .btn + .btn,
      -    > .btn + .btn-group,
      -    > .btn-group + .btn,
      -    > .btn-group + .btn-group {
      -      margin-top: 0;
      -    }
      -  }
      -}
      -
      -// Typography =================================================================
      -
      -body {
      -  -webkit-font-smoothing: antialiased;
      -  letter-spacing: .1px;
      -}
      -
      -p {
      -  margin: 0 0 1em;
      -}
      -
      -input,
      -button {
      -  -webkit-font-smoothing: antialiased;
      -  letter-spacing: .1px;
      -}
      -
      -a {
      -  @include transition(all 0.2s);
      -}
      -
      -// Tables =====================================================================
      -
      -.table-hover {
      -  > tbody > tr,
      -  > tbody > tr > th,
      -  > tbody > tr > td {
      -    @include transition(all 0.2s);
      -  }
      -}
      -
      -// Forms ======================================================================
      -
      -label {
      -  font-weight: normal;
      -}
      -
      -textarea,
      -textarea.form-control,
      -input.form-control,
      -input[type=text],
      -input[type=password],
      -input[type=email],
      -input[type=number],
      -[type=text].form-control,
      -[type=password].form-control,
      -[type=email].form-control,
      -[type=tel].form-control,
      -[contenteditable].form-control {
      -  padding: 0;
      -  border: none;
      -  border-radius: 0;
      -  -webkit-appearance: none;
      -  @include box-shadow(inset 0 -1px 0 #ddd);
      -  font-size: 16px;
      -
      -  &:focus {
      -    @include box-shadow(inset 0 -2px 0 $brand-primary);
      -  }
      -
      -  &[disabled],
      -  &[readonly] {
      -    @include box-shadow(none);
      -    border-bottom: 1px dotted #ddd;
      -  }
      -
      -  &.input {
      -    &-sm {
      -      font-size: $font-size-small;
      -    }
      -
      -    &-lg {
      -      font-size: $font-size-large;
      -    }
      -  }
      -}
      -
      -select,
      -select.form-control {
      -  border: 0;
      -  border-radius: 0;
      -  -webkit-appearance: none;
      -  -moz-appearance: none;
      -  appearance: none;
      -  padding-left: 0;
      -  padding-right: 0\9; // remove padding for < ie9 since default arrow can't be removed
      -  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmaP/QSjAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
      -  background-size: 13px;
      -  background-repeat: no-repeat;
      -  background-position: right center;
      -  @include box-shadow(inset 0 -1px 0 #ddd);
      -  font-size: 16px;
      -  line-height: 1.5;
      -
      -  &::-ms-expand {
      -    display: none;
      -  }
      -
      -  &.input {
      -    &-sm {
      -      font-size: $font-size-small;
      -    }
      -
      -    &-lg {
      -      font-size: $font-size-large;
      -    }
      -  }
      -
      -  &:focus {
      -    @include box-shadow(inset 0 -2px 0 $brand-primary);
      -    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEUhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF8S9ewAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
      -  }
      -
      -  &[multiple] {
      -    background: none;
      -  }
      -}
      -
      -.radio,
      -.radio-inline,
      -.checkbox,
      -.checkbox-inline {
      -  label {
      -    padding-left: 25px;
      -  }
      -
      -  input[type="radio"],
      -  input[type="checkbox"] {
      -    margin-left: -25px;
      -  }
      -}
      -
      -input[type="radio"],
      -.radio input[type="radio"],
      -.radio-inline input[type="radio"] {
      -  position: relative;
      -  margin-top: 6px;
      -  margin-right: 4px;
      -  vertical-align: top;
      -  border: none;
      -  background-color: transparent;
      -  -webkit-appearance: none;
      -  appearance: none;
      -  cursor: pointer;
      -
      -  &:focus {
      -    outline: none;
      -  }
      -
      -  &:before,
      -  &:after {
      -    content: "";
      -    display: block;
      -    width: 18px;
      -    height: 18px;
      -    border-radius: 50%;
      -    @include transition(240ms);
      -  }
      -
      -  &:before {
      -    position: absolute;
      -    left: 0;
      -    top: -3px;
      -    background-color: $brand-primary;
      -    @include scale(0);
      -  }
      -
      -  &:after {
      -    position: relative;
      -    top: -3px;
      -    border: 2px solid $gray;
      -  }
      -
      -  &:checked:before {
      -    @include scale(0.5);
      -  }
      -
      -  &:disabled:checked:before {
      -    background-color: $gray-light;
      -  }
      -
      -  &:checked:after {
      -    border-color: $brand-primary;
      -  }
      -
      -  &:disabled:after,
      -  &:disabled:checked:after {
      -    border-color: $gray-light;
      -  }
      -}
      -
      -input[type="checkbox"],
      -.checkbox input[type="checkbox"],
      -.checkbox-inline input[type="checkbox"] {
      -  position: relative;
      -  border: none;
      -  margin-bottom: -4px;
      -  -webkit-appearance: none;
      -  appearance: none;
      -  cursor: pointer;
      -
      -  &:focus {
      -    outline: none;
      -  }
      -
      -  &:focus:after {
      -    border-color: $brand-primary;
      -  }
      -
      -  &:after {
      -    content: "";
      -    display: block;
      -    width: 18px;
      -    height: 18px;
      -    margin-top: -2px;
      -    margin-right: 5px;
      -    border: 2px solid $gray;
      -    border-radius: 2px;
      -    @include transition(240ms);
      -  }
      -
      -  &:checked:before {
      -    content: "";
      -    position: absolute;
      -    top: 0;
      -    left: 6px;
      -    display: table;
      -    width: 6px;
      -    height: 12px;
      -    border: 2px solid #fff;
      -    border-top-width: 0;
      -    border-left-width: 0;
      -    @include rotate(45deg);
      -  }
      -
      -  &:checked:after {
      -    background-color: $brand-primary;
      -    border-color: $brand-primary;
      -  }
      -
      -  &:disabled:after {
      -    border-color: $gray-light;
      -  }
      -
      -  &:disabled:checked:after {
      -    background-color: $gray-light;
      -    border-color: transparent;
      -  }
      -}
      -
      -.has-warning {
      -  input:not([type=checkbox]),
      -  .form-control,
      -  input.form-control[readonly],
      -  input[type=text][readonly],
      -  [type=text].form-control[readonly],
      -  input:not([type=checkbox]):focus,
      -  .form-control:focus {
      -    border-bottom: none;
      -    @include box-shadow(inset 0 -2px 0 $brand-warning);
      -  }
      -}
      -
      -.has-error {
      -  input:not([type=checkbox]),
      -  .form-control,
      -  input.form-control[readonly],
      -  input[type=text][readonly],
      -  [type=text].form-control[readonly],
      -  input:not([type=checkbox]):focus,
      -  .form-control:focus {
      -    border-bottom: none;
      -    @include box-shadow(inset 0 -2px 0 $brand-danger);
      -  }
      -}
      -
      -.has-success {
      -  input:not([type=checkbox]),
      -  .form-control,
      -  input.form-control[readonly],
      -  input[type=text][readonly],
      -  [type=text].form-control[readonly],
      -  input:not([type=checkbox]):focus,
      -  .form-control:focus {
      -    border-bottom: none;
      -    @include box-shadow(inset 0 -2px 0 $brand-success);
      -  }
      -}
      -
      -// Remove the Bootstrap feedback styles for input addons
      -.input-group-addon {
      -  .has-warning &, .has-error &, .has-success & {
      -    color: $input-color;
      -    border-color: $input-group-addon-border-color;
      -    background-color: $input-group-addon-bg;
      -  }
      -}
      -
      -// Navs =======================================================================
      -
      -.nav-tabs {
      -  > li > a,
      -  > li > a:focus {
      -    margin-right: 0;
      -    background-color: transparent;
      -    border: none;
      -    color: $navbar-default-link-color;
      -    @include box-shadow(inset 0 -1px 0 #ddd);
      -    @include transition(all 0.2s);
      -
      -    &:hover {
      -      background-color: transparent;
      -      @include box-shadow(inset 0 -2px 0 $brand-primary);
      -      color: $brand-primary;
      -    }
      -  }
      -
      -  & > li.active > a,
      -  & > li.active > a:focus {
      -    border: none;
      -    @include box-shadow(inset 0 -2px 0 $brand-primary);
      -    color: $brand-primary;
      -
      -    &:hover {
      -      border: none;
      -      color: $brand-primary;
      -    }
      -  }
      -
      -  & > li.disabled > a {
      -    @include box-shadow(inset 0 -1px 0 #ddd);
      -  }
      -
      -  &.nav-justified {
      -
      -    & > li > a,
      -    & > li > a:hover,
      -    & > li > a:focus,
      -    & > .active > a,
      -    & > .active > a:hover,
      -    & > .active > a:focus {
      -      border: none;
      -    }
      -  }
      -
      -  .dropdown-menu {
      -    margin-top: 0;
      -  }
      -}
      -
      -.dropdown-menu {
      -  margin-top: 0;
      -  border: none;
      -  @include box-shadow(0 1px 4px rgba(0,0,0,.3));
      -}
      -
      -// Indicators =================================================================
      -
      -.alert {
      -  border: none;
      -  color: #fff;
      -
      -  &-success {
      -    background-color: $brand-success;
      -  }
      -
      -  &-info {
      -    background-color: $brand-info;
      -  }
      -
      -  &-warning {
      -    background-color: $brand-warning;
      -  }
      -
      -  &-danger {
      -    background-color: $brand-danger;
      -  }
      -
      -  a:not(.close),
      -  .alert-link {
      -    color: #fff;
      -    font-weight: bold;
      -  }
      -
      -  .close {
      -    color: #fff;
      -  }
      -}
      -
      -.badge {
      -  padding: 4px 6px 4px;
      -}
      -
      -.progress {
      -  position: relative;
      -  z-index: 1;
      -  height: 6px;
      -  border-radius: 0;
      -
      -  @include box-shadow(none);
      -
      -  &-bar {
      -    @include box-shadow(none);
      -
      -    &:last-child {
      -      border-radius: 0 3px 3px 0;
      -    }
      -
      -    &:last-child {
      -      &:before {
      -        display: block;
      -        content: "";
      -        position: absolute;
      -        width: 100%;
      -        height: 100%;
      -        left: 0;
      -        right: 0;
      -        z-index: -1;
      -        background-color: lighten($progress-bar-bg, 35%);
      -      }
      -    }
      -
      -    &-success:last-child.progress-bar:before {
      -      background-color: lighten($brand-success, 35%);
      -    }
      -
      -    &-info:last-child.progress-bar:before {
      -      background-color: lighten($brand-info, 45%);
      -    }
      -    &-warning:last-child.progress-bar:before {
      -      background-color: lighten($brand-warning, 35%);
      -    }
      -
      -    &-danger:last-child.progress-bar:before {
      -      background-color: lighten($brand-danger, 25%);
      -    }
      -  }
      -}
      -
      -// Progress bars ==============================================================
      -
      -// Containers =================================================================
      -
      -.close {
      -  font-size: 34px;
      -  font-weight: 300;
      -  line-height: 24px;
      -  opacity: 0.6;
      -  @include transition(all 0.2s);
      -
      -  &:hover {
      -    opacity: 1;
      -  }
      -}
      -
      -.list-group {
      -
      -  &-item {
      -    padding: 15px;
      -  }
      -
      -  &-item-text {
      -    color: $gray-light;
      -  }
      -}
      -
      -.well {
      -  border-radius: 0;
      -  @include box-shadow(none);
      -}
      -
      -.panel {
      -  border: none;
      -  border-radius: 2px;
      -  @include box-shadow(0 1px 4px rgba(0,0,0,.3));
      -
      -  &-heading {
      -    border-bottom: none;
      -  }
      -
      -  &-footer {
      -    border-top: none;
      -  }
      -}
      -
      -.popover {
      -  border: none;
      -  @include box-shadow(0 1px 4px rgba(0,0,0,.3));
      -}
      -
      -.carousel {
      -  &-caption {
      -    h1, h2, h3, h4, h5, h6 {
      -      color: inherit;
      -    }
      -  }
      -}
      diff --git a/vendor/assets/stylesheets/paper/_variables.scss b/vendor/assets/stylesheets/paper/_variables.scss
      deleted file mode 100644
      index 337712d..0000000
      --- a/vendor/assets/stylesheets/paper/_variables.scss
      +++ /dev/null
      @@ -1,870 +0,0 @@
      -$bootstrap-sass-asset-helper: false !default;
      -// Paper 3.3.6
      -// Variables
      -// --------------------------------------------------
      -
      -
      -//== Colors
      -//
      -//## Gray and brand colors for use across Bootstrap.
      -
      -$gray-base:              #000 !default;
      -$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
      -$gray-dark:              #212121 !default;
      -$gray:                   #666 !default;
      -$gray-light:             #bbb !default;
      -$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
      -
      -$brand-primary:         #2196F3 !default;
      -$brand-success:         #4CAF50 !default;
      -$brand-info:            #9C27B0 !default;
      -$brand-warning:         #ff9800 !default;
      -$brand-danger:          #e51c23 !default;
      -
      -
      -//== Scaffolding
      -//
      -//## Settings for some of the most global styles.
      -
      -//** Background color for ``.
      -$body-bg:               #fff !default;
      -//** Global text color on ``.
      -$text-color:            $gray !default;
      -
      -//** Global textual link color.
      -$link-color:            $brand-primary !default;
      -//** Link hover color set via `darken()` function.
      -$link-hover-color:      darken($link-color, 15%) !default;
      -//** Link hover decoration.
      -$link-hover-decoration: underline !default;
      -
      -
      -//== Typography
      -//
      -//## Font, line-height, and color for body text, headings, and more.
      -
      -$font-family-sans-serif:  "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
      -$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
      -//** Default monospace fonts for ``, ``, and `
      `.
      -$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
      -$font-family-base:        $font-family-sans-serif !default;
      -
      -$font-size-base:          13px !default;
      -$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -$font-size-h1:            56px !default;
      -$font-size-h2:            45px !default;
      -$font-size-h3:            34px !default;
      -$font-size-h4:            24px !default;
      -$font-size-h5:            20px !default;
      -$font-size-h6:            14px !default;
      -
      -//** Unit-less `line-height` for use in components like buttons.
      -$line-height-base:        1.846 !default; // 20/14
      -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
      -$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
      -
      -//** By default, this inherits from the ``.
      -$headings-font-family:    inherit !default;
      -$headings-font-weight:    400 !default;
      -$headings-line-height:    1.1 !default;
      -$headings-color:          #444 !default;
      -
      -
      -//== Iconography
      -//
      -//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
      -
      -//** Load fonts from this directory.
      -$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
      -//** File name for all font files.
      -$icon-font-name:          "glyphicons-halflings-regular" !default;
      -//** Element ID within SVG icon file.
      -$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
      -
      -
      -//== Components
      -//
      -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
      -
      -$padding-base-vertical:     6px !default;
      -$padding-base-horizontal:   16px !default;
      -
      -$padding-large-vertical:    10px !default;
      -$padding-large-horizontal:  16px !default;
      -
      -$padding-small-vertical:    5px !default;
      -$padding-small-horizontal:  10px !default;
      -
      -$padding-xs-vertical:       1px !default;
      -$padding-xs-horizontal:     5px !default;
      -
      -$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
      -$line-height-small:         1.5 !default;
      -
      -$border-radius-base:        3px !default;
      -$border-radius-large:       3px !default;
      -$border-radius-small:       3px !default;
      -
      -//** Global color for active items (e.g., navs or dropdowns).
      -$component-active-color:    #fff !default;
      -//** Global background color for active items (e.g., navs or dropdowns).
      -$component-active-bg:       $brand-primary !default;
      -
      -//** Width of the `border` for generating carets that indicator dropdowns.
      -$caret-width-base:          4px !default;
      -//** Carets increase slightly in size for larger components.
      -$caret-width-large:         5px !default;
      -
      -
      -//== Tables
      -//
      -//## Customizes the `.table` component with basic values, each used across all table variations.
      -
      -//** Padding for ``s and ``s.
      -$table-cell-padding:            8px !default;
      -//** Padding for cells in `.table-condensed`.
      -$table-condensed-cell-padding:  5px !default;
      -
      -//** Default background color used for all tables.
      -$table-bg:                      transparent !default;
      -//** Background color used for `.table-striped`.
      -$table-bg-accent:               #f9f9f9 !default;
      -//** Background color used for `.table-hover`.
      -$table-bg-hover:                #f5f5f5 !default;
      -$table-bg-active:               $table-bg-hover !default;
      -
      -//** Border color for table and cell borders.
      -$table-border-color:            #ddd !default;
      -
      -
      -//== Buttons
      -//
      -//## For each of Bootstrap's buttons, define text, background and border color.
      -
      -$btn-font-weight:                normal !default;
      -
      -$btn-default-color:              #444 !default;
      -$btn-default-bg:                 #fff !default;
      -$btn-default-border:             transparent !default;
      -
      -$btn-primary-color:              #fff !default;
      -$btn-primary-bg:                 $brand-primary !default;
      -$btn-primary-border:             transparent !default;
      -
      -$btn-success-color:              #fff !default;
      -$btn-success-bg:                 $brand-success !default;
      -$btn-success-border:             transparent !default;
      -
      -$btn-info-color:                 #fff !default;
      -$btn-info-bg:                    $brand-info !default;
      -$btn-info-border:                transparent !default;
      -
      -$btn-warning-color:              #fff !default;
      -$btn-warning-bg:                 $brand-warning !default;
      -$btn-warning-border:             transparent !default;
      -
      -$btn-danger-color:               #fff !default;
      -$btn-danger-bg:                  $brand-danger !default;
      -$btn-danger-border:              transparent !default;
      -
      -$btn-link-disabled-color:        $gray-light !default;
      -
      -// Allows for customizing button radius independently from global border radius
      -$btn-border-radius-base:         $border-radius-base !default;
      -$btn-border-radius-large:        $border-radius-large !default;
      -$btn-border-radius-small:        $border-radius-small !default;
      -
      -
      -//== Forms
      -//
      -//##
      -
      -//** `` background color
      -$input-bg:                       transparent !default;
      -//** `` background color
      -$input-bg-disabled:              transparent !default;
      -
      -//** Text color for ``s
      -$input-color:                    $gray !default;
      -//** `` border color
      -$input-border:                   transparent !default;
      -
      -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
      -//** Default `.form-control` border radius
      -// This has no effect on ``s in CSS.
      -$input-border-radius:            $border-radius-base !default;
      -//** Large `.form-control` border radius
      -$input-border-radius-large:      $border-radius-large !default;
      -//** Small `.form-control` border radius
      -$input-border-radius-small:      $border-radius-small !default;
      -
      -//** Border color for inputs on focus
      -$input-border-focus:             #66afe9 !default;
      -
      -//** Placeholder text color
      -$input-color-placeholder:        $gray-light !default;
      -
      -//** Default `.form-control` height
      -$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
      -//** Large `.form-control` height
      -$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
      -//** Small `.form-control` height
      -$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
      -
      -//** `.form-group` margin
      -$form-group-margin-bottom:       15px !default;
      -
      -$legend-color:                   $gray-dark !default;
      -$legend-border-color:            #e5e5e5 !default;
      -
      -//** Background color for textual input addons
      -$input-group-addon-bg:           transparent !default;
      -//** Border color for textual input addons
      -$input-group-addon-border-color: $input-border !default;
      -
      -//** Disabled cursor for form controls and buttons.
      -$cursor-disabled:                not-allowed !default;
      -
      -
      -//== Dropdowns
      -//
      -//## Dropdown menu container and contents.
      -
      -//** Background for the dropdown menu.
      -$dropdown-bg:                    #fff !default;
      -//** Dropdown menu `border-color`.
      -$dropdown-border:                rgba(0,0,0,.15) !default;
      -//** Dropdown menu `border-color` **for IE8**.
      -$dropdown-fallback-border:       #ccc !default;
      -//** Divider color for between dropdown items.
      -$dropdown-divider-bg:            #e5e5e5 !default;
      -
      -//** Dropdown link text color.
      -$dropdown-link-color:            $text-color !default;
      -//** Hover color for dropdown links.
      -$dropdown-link-hover-color:      darken($gray-dark, 5%) !default;
      -//** Hover background for dropdown links.
      -$dropdown-link-hover-bg:         $gray-lighter !default;
      -
      -//** Active dropdown menu item text color.
      -$dropdown-link-active-color:     $component-active-color !default;
      -//** Active dropdown menu item background color.
      -$dropdown-link-active-bg:        $component-active-bg !default;
      -
      -//** Disabled dropdown menu item background color.
      -$dropdown-link-disabled-color:   $gray-light !default;
      -
      -//** Text color for headers within dropdown menus.
      -$dropdown-header-color:          $gray-light !default;
      -
      -//** Deprecated `$dropdown-caret-color` as of v3.1.0
      -$dropdown-caret-color:           $gray-light !default;
      -
      -
      -//-- Z-index master list
      -//
      -// Warning: Avoid customizing these values. They're used for a bird's eye view
      -// of components dependent on the z-axis and are designed to all work together.
      -//
      -// Note: These variables are not generated into the Customizer.
      -
      -$zindex-navbar:            1000 !default;
      -$zindex-dropdown:          1000 !default;
      -$zindex-popover:           1060 !default;
      -$zindex-tooltip:           1070 !default;
      -$zindex-navbar-fixed:      1030 !default;
      -$zindex-modal-background:  1040 !default;
      -$zindex-modal:             1050 !default;
      -
      -
      -//== Media queries breakpoints
      -//
      -//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
      -
      -// Extra small screen / phone
      -//** Deprecated `$screen-xs` as of v3.0.1
      -$screen-xs:                  480px !default;
      -//** Deprecated `$screen-xs-min` as of v3.2.0
      -$screen-xs-min:              $screen-xs !default;
      -//** Deprecated `$screen-phone` as of v3.0.1
      -$screen-phone:               $screen-xs-min !default;
      -
      -// Small screen / tablet
      -//** Deprecated `$screen-sm` as of v3.0.1
      -$screen-sm:                  768px !default;
      -$screen-sm-min:              $screen-sm !default;
      -//** Deprecated `$screen-tablet` as of v3.0.1
      -$screen-tablet:              $screen-sm-min !default;
      -
      -// Medium screen / desktop
      -//** Deprecated `$screen-md` as of v3.0.1
      -$screen-md:                  992px !default;
      -$screen-md-min:              $screen-md !default;
      -//** Deprecated `$screen-desktop` as of v3.0.1
      -$screen-desktop:             $screen-md-min !default;
      -
      -// Large screen / wide desktop
      -//** Deprecated `$screen-lg` as of v3.0.1
      -$screen-lg:                  1200px !default;
      -$screen-lg-min:              $screen-lg !default;
      -//** Deprecated `$screen-lg-desktop` as of v3.0.1
      -$screen-lg-desktop:          $screen-lg-min !default;
      -
      -// So media queries don't overlap when required, provide a maximum
      -$screen-xs-max:              ($screen-sm-min - 1) !default;
      -$screen-sm-max:              ($screen-md-min - 1) !default;
      -$screen-md-max:              ($screen-lg-min - 1) !default;
      -
      -
      -//== Grid system
      -//
      -//## Define your custom responsive grid.
      -
      -//** Number of columns in the grid.
      -$grid-columns:              12 !default;
      -//** Padding between columns. Gets divided in half for the left and right.
      -$grid-gutter-width:         30px !default;
      -// Navbar collapse
      -//** Point at which the navbar becomes uncollapsed.
      -$grid-float-breakpoint:     $screen-sm-min !default;
      -//** Point at which the navbar begins collapsing.
      -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
      -
      -
      -//== Container sizes
      -//
      -//## Define the maximum width of `.container` for different screen sizes.
      -
      -// Small screen / tablet
      -$container-tablet:             (720px + $grid-gutter-width) !default;
      -//** For `$screen-sm-min` and up.
      -$container-sm:                 $container-tablet !default;
      -
      -// Medium screen / desktop
      -$container-desktop:            (940px + $grid-gutter-width) !default;
      -//** For `$screen-md-min` and up.
      -$container-md:                 $container-desktop !default;
      -
      -// Large screen / wide desktop
      -$container-large-desktop:      (1140px + $grid-gutter-width) !default;
      -//** For `$screen-lg-min` and up.
      -$container-lg:                 $container-large-desktop !default;
      -
      -
      -//== Navbar
      -//
      -//##
      -
      -// Basics of a navbar
      -$navbar-height:                    64px !default;
      -$navbar-margin-bottom:             $line-height-computed !default;
      -$navbar-border-radius:             $border-radius-base !default;
      -$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
      -$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
      -$navbar-collapse-max-height:       340px !default;
      -
      -$navbar-default-color:             $gray-light !default;
      -$navbar-default-bg:                #fff !default;
      -$navbar-default-border:            transparent !default;
      -
      -// Navbar links
      -$navbar-default-link-color:                $gray !default;
      -$navbar-default-link-hover-color:          $gray-dark !default;
      -$navbar-default-link-hover-bg:             transparent !default;
      -$navbar-default-link-active-color:         $gray-dark !default;
      -$navbar-default-link-active-bg:            darken($navbar-default-bg, 6.5%) !default;
      -$navbar-default-link-disabled-color:       #ccc !default;
      -$navbar-default-link-disabled-bg:          transparent !default;
      -
      -// Navbar brand label
      -$navbar-default-brand-color:               $navbar-default-link-color !default;
      -$navbar-default-brand-hover-color:         $navbar-default-link-hover-color !default;
      -$navbar-default-brand-hover-bg:            transparent !default;
      -
      -// Navbar toggle
      -$navbar-default-toggle-hover-bg:           transparent !default;
      -$navbar-default-toggle-icon-bar-bg:        rgba(0,0,0,0.5) !default;
      -$navbar-default-toggle-border-color:       transparent !default;
      -
      -
      -//=== Inverted navbar
      -// Reset inverted navbar basics
      -$navbar-inverse-color:                      $gray-light !default;
      -$navbar-inverse-bg:                         $brand-primary !default;
      -$navbar-inverse-border:                     transparent !default;
      -
      -// Inverted navbar links
      -$navbar-inverse-link-color:                 lighten($brand-primary, 30%) !default;
      -$navbar-inverse-link-hover-color:           #fff !default;
      -$navbar-inverse-link-hover-bg:              transparent !default;
      -$navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color !default;
      -$navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 10%) !default;
      -$navbar-inverse-link-disabled-color:        #444 !default;
      -$navbar-inverse-link-disabled-bg:           transparent !default;
      -
      -// Inverted navbar brand label
      -$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;
      -$navbar-inverse-brand-hover-color:          #fff !default;
      -$navbar-inverse-brand-hover-bg:             transparent !default;
      -
      -// Inverted navbar toggle\
      -$navbar-inverse-toggle-hover-bg:            transparent !default;
      -$navbar-inverse-toggle-icon-bar-bg:         rgba(0,0,0,0.5) !default;
      -$navbar-inverse-toggle-border-color:        transparent !default;
      -
      -
      -//== Navs
      -//
      -//##
      -
      -//=== Shared nav styles
      -$nav-link-padding:                          10px 15px !default;
      -$nav-link-hover-bg:                         $gray-lighter !default;
      -
      -$nav-disabled-link-color:                   $gray-light !default;
      -$nav-disabled-link-hover-color:             $gray-light !default;
      -
      -//== Tabs
      -$nav-tabs-border-color:                     transparent !default;
      -
      -$nav-tabs-link-hover-border-color:          $gray-lighter !default;
      -
      -$nav-tabs-active-link-hover-bg:             transparent !default;
      -$nav-tabs-active-link-hover-color:          $gray !default;
      -$nav-tabs-active-link-hover-border-color:   transparent !default;
      -
      -$nav-tabs-justified-link-border-color:            $nav-tabs-border-color !default;
      -$nav-tabs-justified-active-link-border-color:     $body-bg !default;
      -
      -//== Pills
      -$nav-pills-border-radius:                   $border-radius-base !default;
      -$nav-pills-active-link-hover-bg:            $component-active-bg !default;
      -$nav-pills-active-link-hover-color:         $component-active-color !default;
      -
      -
      -//== Pagination
      -//
      -//##
      -
      -$pagination-color:                     $link-color !default;
      -$pagination-bg:                        #fff !default;
      -$pagination-border:                    #ddd !default;
      -
      -$pagination-hover-color:               $link-hover-color !default;
      -$pagination-hover-bg:                  $gray-lighter !default;
      -$pagination-hover-border:              #ddd !default;
      -
      -$pagination-active-color:              #fff !default;
      -$pagination-active-bg:                 $brand-primary !default;
      -$pagination-active-border:             $brand-primary !default;
      -
      -$pagination-disabled-color:            $gray-light !default;
      -$pagination-disabled-bg:               #fff !default;
      -$pagination-disabled-border:           #ddd !default;
      -
      -
      -//== Pager
      -//
      -//##
      -
      -$pager-bg:                             $pagination-bg !default;
      -$pager-border:                         $pagination-border !default;
      -$pager-border-radius:                  15px !default;
      -
      -$pager-hover-bg:                       $pagination-hover-bg !default;
      -
      -$pager-active-bg:                      $pagination-active-bg !default;
      -$pager-active-color:                   $pagination-active-color !default;
      -
      -$pager-disabled-color:                 $pagination-disabled-color !default;
      -
      -
      -//== Jumbotron
      -//
      -//##
      -
      -$jumbotron-padding:              30px !default;
      -$jumbotron-color:                inherit !default;
      -$jumbotron-bg:                   #f9f9f9 !default;
      -$jumbotron-heading-color:        $headings-color !default;
      -$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
      -$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
      -
      -
      -//== Form states and alerts
      -//
      -//## Define colors for form feedback states and, by default, alerts.
      -
      -$state-success-text:             $brand-success !default;
      -$state-success-bg:               #dff0d8 !default;
      -$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
      -
      -$state-info-text:                $brand-info !default;
      -$state-info-bg:                  #e1bee7 !default;
      -$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
      -
      -$state-warning-text:             $brand-warning !default;
      -$state-warning-bg:               #ffe0b2 !default;
      -$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%) !default;
      -
      -$state-danger-text:              $brand-danger !default;
      -$state-danger-bg:                #f9bdbb !default;
      -$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%) !default;
      -
      -
      -//== Tooltips
      -//
      -//##
      -
      -//** Tooltip max width
      -$tooltip-max-width:           200px !default;
      -//** Tooltip text color
      -$tooltip-color:               #fff !default;
      -//** Tooltip background color
      -$tooltip-bg:                  #727272 !default;
      -$tooltip-opacity:             .9 !default;
      -
      -//** Tooltip arrow width
      -$tooltip-arrow-width:         5px !default;
      -//** Tooltip arrow color
      -$tooltip-arrow-color:         $tooltip-bg !default;
      -
      -
      -//== Popovers
      -//
      -//##
      -
      -//** Popover body background color
      -$popover-bg:                          #fff !default;
      -//** Popover maximum width
      -$popover-max-width:                   276px !default;
      -//** Popover border color
      -$popover-border-color:                transparent !default;
      -//** Popover fallback border color
      -$popover-fallback-border-color:       transparent !default;
      -
      -//** Popover title background color
      -$popover-title-bg:                    darken($popover-bg, 3%) !default;
      -
      -//** Popover arrow width
      -$popover-arrow-width:                 10px !default;
      -//** Popover arrow color
      -$popover-arrow-color:                 $popover-bg !default;
      -
      -//** Popover outer arrow width
      -$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
      -//** Popover outer arrow color
      -$popover-arrow-outer-color:           fadein($popover-border-color, 7.5%) !default;
      -//** Popover outer arrow fallback color
      -$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
      -
      -
      -//== Labels
      -//
      -//##
      -
      -//** Default label background color
      -$label-default-bg:            $gray-light !default;
      -//** Primary label background color
      -$label-primary-bg:            $brand-primary !default;
      -//** Success label background color
      -$label-success-bg:            $brand-success !default;
      -//** Info label background color
      -$label-info-bg:               $brand-info !default;
      -//** Warning label background color
      -$label-warning-bg:            $brand-warning !default;
      -//** Danger label background color
      -$label-danger-bg:             $brand-danger !default;
      -
      -//** Default label text color
      -$label-color:                 #fff !default;
      -//** Default text color of a linked label
      -$label-link-hover-color:      #fff !default;
      -
      -
      -//== Modals
      -//
      -//##
      -
      -//** Padding applied to the modal body
      -$modal-inner-padding:         15px !default;
      -
      -//** Padding applied to the modal title
      -$modal-title-padding:         15px !default;
      -//** Modal title line-height
      -$modal-title-line-height:     $line-height-base !default;
      -
      -//** Background color of modal content area
      -$modal-content-bg:                             #fff !default;
      -//** Modal content border color
      -$modal-content-border-color:                   transparent !default;
      -//** Modal content border color **for IE8**
      -$modal-content-fallback-border-color:          #999 !default;
      -
      -//** Modal backdrop background color
      -$modal-backdrop-bg:           #000 !default;
      -//** Modal backdrop opacity
      -$modal-backdrop-opacity:      .5 !default;
      -//** Modal header border color
      -$modal-header-border-color:   transparent !default;
      -//** Modal footer border color
      -$modal-footer-border-color:   $modal-header-border-color !default;
      -
      -$modal-lg:                    900px !default;
      -$modal-md:                    600px !default;
      -$modal-sm:                    300px !default;
      -
      -
      -//== Alerts
      -//
      -//## Define alert colors, border radius, and padding.
      -
      -$alert-padding:               15px !default;
      -$alert-border-radius:         $border-radius-base !default;
      -$alert-link-font-weight:      bold !default;
      -
      -$alert-success-bg:            $state-success-bg !default;
      -$alert-success-text:          $state-success-text !default;
      -$alert-success-border:        $state-success-border !default;
      -
      -$alert-info-bg:               $state-info-bg !default;
      -$alert-info-text:             $state-info-text !default;
      -$alert-info-border:           $state-info-border !default;
      -
      -$alert-warning-bg:            $state-warning-bg !default;
      -$alert-warning-text:          $state-warning-text !default;
      -$alert-warning-border:        $state-warning-border !default;
      -
      -$alert-danger-bg:             $state-danger-bg !default;
      -$alert-danger-text:           $state-danger-text !default;
      -$alert-danger-border:         $state-danger-border !default;
      -
      -
      -//== Progress bars
      -//
      -//##
      -
      -//** Background color of the whole progress component
      -$progress-bg:                 #f5f5f5 !default;
      -//** Progress bar text color
      -$progress-bar-color:          #fff !default;
      -//** Variable for setting rounded corners on progress bar.
      -$progress-border-radius:      $border-radius-base !default;
      -
      -//** Default progress bar color
      -$progress-bar-bg:             $brand-primary !default;
      -//** Success progress bar color
      -$progress-bar-success-bg:     $brand-success !default;
      -//** Warning progress bar color
      -$progress-bar-warning-bg:     $brand-warning !default;
      -//** Danger progress bar color
      -$progress-bar-danger-bg:      $brand-danger !default;
      -//** Info progress bar color
      -$progress-bar-info-bg:        $brand-info !default;
      -
      -
      -//== List group
      -//
      -//##
      -
      -//** Background color on `.list-group-item`
      -$list-group-bg:                 #fff !default;
      -//** `.list-group-item` border color
      -$list-group-border:             #ddd !default;
      -//** List group border radius
      -$list-group-border-radius:      $border-radius-base !default;
      -
      -//** Background color of single list items on hover
      -$list-group-hover-bg:           #f5f5f5 !default;
      -//** Text color of active list items
      -$list-group-active-color:       $component-active-color !default;
      -//** Background color of active list items
      -$list-group-active-bg:          $component-active-bg !default;
      -//** Border color of active list elements
      -$list-group-active-border:      $list-group-active-bg !default;
      -//** Text color for content within active list items
      -$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
      -
      -//** Text color of disabled list items
      -$list-group-disabled-color:      $gray-light !default;
      -//** Background color of disabled list items
      -$list-group-disabled-bg:         $gray-lighter !default;
      -//** Text color for content within disabled list items
      -$list-group-disabled-text-color: $list-group-disabled-color !default;
      -
      -$list-group-link-color:         #555 !default;
      -$list-group-link-hover-color:   $list-group-link-color !default;
      -$list-group-link-heading-color: #333 !default;
      -
      -
      -//== Panels
      -//
      -//##
      -
      -$panel-bg:                    #fff !default;
      -$panel-body-padding:          15px !default;
      -$panel-heading-padding:       10px 15px !default;
      -$panel-footer-padding:        $panel-heading-padding !default;
      -$panel-border-radius:         $border-radius-base !default;
      -
      -//** Border color for elements within panels
      -$panel-inner-border:          #ddd !default;
      -$panel-footer-bg:             #f5f5f5 !default;
      -
      -$panel-default-text:          $gray-dark !default;
      -$panel-default-border:        #ddd !default;
      -$panel-default-heading-bg:    #f5f5f5 !default;
      -
      -$panel-primary-text:          #fff !default;
      -$panel-primary-border:        $brand-primary !default;
      -$panel-primary-heading-bg:    $brand-primary !default;
      -
      -$panel-success-text:          #fff !default;
      -$panel-success-border:        $state-success-border !default;
      -$panel-success-heading-bg:    $brand-success !default;
      -
      -$panel-info-text:             #fff !default;
      -$panel-info-border:           $state-info-border !default;
      -$panel-info-heading-bg:       $brand-info !default;
      -
      -$panel-warning-text:          #fff !default;
      -$panel-warning-border:        $state-warning-border !default;
      -$panel-warning-heading-bg:    $brand-warning !default;
      -
      -$panel-danger-text:           #fff !default;
      -$panel-danger-border:         $state-danger-border !default;
      -$panel-danger-heading-bg:     $brand-danger !default;
      -
      -
      -//== Thumbnails
      -//
      -//##
      -
      -//** Padding around the thumbnail image
      -$thumbnail-padding:           4px !default;
      -//** Thumbnail background color
      -$thumbnail-bg:                $body-bg !default;
      -//** Thumbnail border color
      -$thumbnail-border:            #ddd !default;
      -//** Thumbnail border radius
      -$thumbnail-border-radius:     $border-radius-base !default;
      -
      -//** Custom text color for thumbnail captions
      -$thumbnail-caption-color:     $text-color !default;
      -//** Padding around the thumbnail caption
      -$thumbnail-caption-padding:   9px !default;
      -
      -
      -//== Wells
      -//
      -//##
      -
      -$well-bg:                     #f9f9f9 !default;
      -$well-border:                 transparent !default;
      -
      -
      -//== Badges
      -//
      -//##
      -
      -$badge-color:                 #fff !default;
      -//** Linked badge text color on hover
      -$badge-link-hover-color:      #fff !default;
      -$badge-bg:                    $gray-light !default;
      -
      -//** Badge text color in active nav link
      -$badge-active-color:          $link-color !default;
      -//** Badge background color in active nav link
      -$badge-active-bg:             #fff !default;
      -
      -$badge-font-weight:           normal !default;
      -$badge-line-height:           1 !default;
      -$badge-border-radius:         10px !default;
      -
      -
      -//== Breadcrumbs
      -//
      -//##
      -
      -$breadcrumb-padding-vertical:   8px !default;
      -$breadcrumb-padding-horizontal: 15px !default;
      -//** Breadcrumb background color
      -$breadcrumb-bg:                 #f5f5f5 !default;
      -//** Breadcrumb text color
      -$breadcrumb-color:              #ccc !default;
      -//** Text color of current page in the breadcrumb
      -$breadcrumb-active-color:       $gray-light !default;
      -//** Textual separator for between breadcrumb elements
      -$breadcrumb-separator:          "/" !default;
      -
      -
      -//== Carousel
      -//
      -//##
      -
      -$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
      -
      -$carousel-control-color:                      #fff !default;
      -$carousel-control-width:                      15% !default;
      -$carousel-control-opacity:                    .5 !default;
      -$carousel-control-font-size:                  20px !default;
      -
      -$carousel-indicator-active-bg:                #fff !default;
      -$carousel-indicator-border-color:             #fff !default;
      -
      -$carousel-caption-color:                      #fff !default;
      -
      -
      -//== Close
      -//
      -//##
      -
      -$close-font-weight:           normal !default;
      -$close-color:                 #000 !default;
      -$close-text-shadow:           none !default;
      -
      -
      -//== Code
      -//
      -//##
      -
      -$code-color:                  #c7254e !default;
      -$code-bg:                     #f9f2f4 !default;
      -
      -$kbd-color:                   #fff !default;
      -$kbd-bg:                      #333 !default;
      -
      -$pre-bg:                      #f5f5f5 !default;
      -$pre-color:                   $gray-dark !default;
      -$pre-border-color:            #ccc !default;
      -$pre-scrollable-max-height:   340px !default;
      -
      -
      -//== Type
      -//
      -//##
      -
      -//** Horizontal offset for forms and lists.
      -$component-offset-horizontal: 180px !default;
      -//** Text muted color
      -$text-muted:                  $gray-light !default;
      -//** Abbreviations and acronyms border color
      -$abbr-border-color:           $gray-light !default;
      -//** Headings small color
      -$headings-small-color:        $gray-light !default;
      -//** Blockquote small color
      -$blockquote-small-color:      $gray-light !default;
      -//** Blockquote font size
      -$blockquote-font-size:        ($font-size-base * 1.25) !default;
      -//** Blockquote border color
      -$blockquote-border-color:     $gray-lighter !default;
      -//** Page header border color
      -$page-header-border-color:    $gray-lighter !default;
      -//** Width of horizontal description list titles
      -$dl-horizontal-offset:        $component-offset-horizontal !default;
      -//** Point at which .dl-horizontal becomes horizontal
      -$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
      -//** Horizontal line color.
      -$hr-border:                   $gray-lighter !default;
      \ No newline at end of file
      diff --git a/vendor/assets/stylesheets/readable/_bootswatch.scss b/vendor/assets/stylesheets/readable/_bootswatch.scss
      deleted file mode 100644
      index eec2e00..0000000
      --- a/vendor/assets/stylesheets/readable/_bootswatch.scss
      +++ /dev/null
      @@ -1,183 +0,0 @@
      -// Readable 3.3.5
      -// Bootswatch
      -// -----------------------------------------------------
      -
      -//$web-font-path: "https://fonts.googleapis.com/css?family=Raleway:400,700" !default;
      -//@import url($web-font-path);
      -
      -// Navbar =====================================================================
      -
      -.navbar {
      -  font-family: $headings-font-family;
      -
      -  &-nav,
      -  &-form {
      -    margin-left: 0;
      -    margin-right: 0;
      -  }
      -
      -  &-nav > li > a {
      -    $margin-vertical: (($navbar-height - 2*$padding-base-vertical - $line-height-computed - 2px) / 2);
      -    margin: $margin-vertical 6px;
      -    padding: $padding-base-vertical $padding-base-horizontal;
      -    border: 1px solid transparent;
      -    border-radius: $border-radius-base;
      -
      -    &:hover {
      -      border: 1px solid #ddd;
      -    }
      -  }
      -
      -  &-nav > .active > a,
      -  &-nav > .active > a:hover {
      -    border: 1px solid #ddd;
      -  }
      -
      -  &-default .navbar-nav > .active > a:hover {
      -    color: $navbar-default-link-hover-color;
      -  }
      -
      -  &-inverse .navbar-nav > .active > a:hover {
      -    color: $navbar-inverse-link-hover-color;
      -  }
      -
      -  &-brand {
      -    padding-top: (($navbar-height - 2*$font-size-large) / 2);
      -    padding-bottom: (($navbar-height - 2*$font-size-large) / 2);
      -    line-height: 1.9;
      -  }
      -}
      -
      -@media (min-width: $grid-float-breakpoint) {
      -  .navbar {
      -    .navbar-nav > li > a {
      -      padding: $padding-base-vertical $padding-base-horizontal;
      -    }
      -  }
      -}
      -
      -@media (max-width: ($grid-float-breakpoint - 1)) {
      -  .navbar {
      -    .navbar-nav > li > a {
      -      margin: 0;
      -    }
      -  }
      -}
      -
      -// Buttons ====================================================================
      -
      -.btn {
      -  font-family: $headings-font-family;
      -}
      -
      -// Typography =================================================================
      -
      -// Tables =====================================================================
      -
      -// Forms ======================================================================
      -
      -legend {
      -  font-family: $headings-font-family;
      -}
      -
      -.input-group-addon {
      -  font-family: $font-family-sans-serif;
      -}
      -
      -// Navs =======================================================================
      -
      -.nav {
      -  .open > a,
      -  .open > a:hover,
      -  .open > a:focus {
      -    border: 1px solid #ddd;
      -  }
      -}
      -
      -.pagination {
      -
      -  font-family: $headings-font-family;
      -
      -  &-lg > li > a,
      -  &-lg > li > span {
      -    padding: 14px 24px;
      -  }
      -}
      -
      -.pager {
      -
      -  font-family: $headings-font-family;
      -
      -  a {
      -    color: $text-color;
      -  }
      -
      -  a:hover {
      -    border-color: transparent;
      -    color: #fff;
      -  }
      -
      -  .disabled a {
      -    border-color: $pager-border;
      -  }
      -}
      -
      -// Indicators =================================================================
      -
      -.close {
      -  color: #fff;
      -  text-decoration: none;
      -  text-shadow: none;
      -  opacity: 0.4;
      -
      -  &:hover,
      -  &:focus {
      -    color: #fff;
      -    opacity: 1;
      -  }
      -}
      -
      -.alert {
      -  .alert-link {
      -    color: $alert-success-text;
      -    text-decoration: underline;
      -  }
      -}
      -
      -.label {
      -  font-family: $headings-font-family;
      -  font-weight: normal;
      -
      -  &-default {
      -    border: 1px solid #ddd;
      -    color: $text-color;
      -  }
      -
      -}
      -
      -.badge {
      -  padding: 1px 7px 5px;
      -  vertical-align: 2px;
      -  font-family: $headings-font-family;
      -  font-weight: normal;
      -}
      -
      -// Progress bars ==============================================================
      -
      -// Containers =================================================================
      -
      -.panel {
      -  @include box-shadow(none);
      -
      -  &-default {
      -    .close {
      -      color: $text-color;
      -    }
      -  }
      -}
      -
      -.modal {
      -  .close {
      -    color: $text-color;
      -  }
      -}
      diff --git a/vendor/assets/stylesheets/readable/_variables.scss b/vendor/assets/stylesheets/readable/_variables.scss
      deleted file mode 100644
      index 66551a7..0000000
      --- a/vendor/assets/stylesheets/readable/_variables.scss
      +++ /dev/null
      @@ -1,870 +0,0 @@
      -$bootstrap-sass-asset-helper: false !default;
      -// Readable 3.3.6
      -// Variables
      -// --------------------------------------------------
      -
      -
      -//== Colors
      -//
      -//## Gray and brand colors for use across Bootstrap.
      -
      -$gray-base:              #000 !default;
      -$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
      -$gray-dark:              lighten($gray-base, 20%) !default;   // #333
      -$gray:                   lighten($gray-base, 33.5%) !default; // #555
      -$gray-light:             lighten($gray-base, 70%) !default;   // #999
      -$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
      -
      -$brand-primary:         #4582EC !default;
      -$brand-success:         #3FAD46 !default;
      -$brand-info:            #5bc0de !default;
      -$brand-warning:         #f0ad4e !default;
      -$brand-danger:          #d9534f !default;
      -
      -
      -//== Scaffolding
      -//
      -//## Settings for some of the most global styles.
      -
      -//** Background color for ``.
      -$body-bg:               #fff !default;
      -//** Global text color on ``.
      -$text-color:            $gray-dark !default;
      -
      -//** Global textual link color.
      -$link-color:            $brand-primary !default;
      -//** Link hover color set via `darken()` function.
      -$link-hover-color:      darken($link-color, 20%) !default;
      -//** Link hover decoration.
      -$link-hover-decoration: underline !default;
      -
      -
      -//== Typography
      -//
      -//## Font, line-height, and color for body text, headings, and more.
      -
      -$font-family-sans-serif:  "Raleway", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
      -$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
      -//** Default monospace fonts for ``, ``, and `
      `.
      -$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
      -$font-family-base:        $font-family-serif !default;
      -
      -$font-size-base:          16px !default;
      -$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
      -$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
      -$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
      -$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-h5:            $font-size-base !default;
      -$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -//** Unit-less `line-height` for use in components like buttons.
      -$line-height-base:        1.428571429 !default; // 20/14
      -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
      -$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
      -
      -//** By default, this inherits from the ``.
      -$headings-font-family:    $font-family-sans-serif !default;
      -$headings-font-weight:    bold !default;
      -$headings-line-height:    1.1 !default;
      -$headings-color:          inherit !default;
      -
      -
      -//== Iconography
      -//
      -//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
      -
      -//** Load fonts from this directory.
      -$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
      -//** File name for all font files.
      -$icon-font-name:          "glyphicons-halflings-regular" !default;
      -//** Element ID within SVG icon file.
      -$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
      -
      -
      -//== Components
      -//
      -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
      -
      -$padding-base-vertical:     8px !default;
      -$padding-base-horizontal:   12px !default;
      -
      -$padding-large-vertical:    14px !default;
      -$padding-large-horizontal:  16px !default;
      -
      -$padding-small-vertical:    5px !default;
      -$padding-small-horizontal:  10px !default;
      -
      -$padding-xs-vertical:       1px !default;
      -$padding-xs-horizontal:     5px !default;
      -
      -$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
      -$line-height-small:         1.5 !default;
      -
      -$border-radius-base:        4px !default;
      -$border-radius-large:       6px !default;
      -$border-radius-small:       3px !default;
      -
      -//** Global color for active items (e.g., navs or dropdowns).
      -$component-active-color:    #fff !default;
      -//** Global background color for active items (e.g., navs or dropdowns).
      -$component-active-bg:       $brand-primary !default;
      -
      -//** Width of the `border` for generating carets that indicator dropdowns.
      -$caret-width-base:          4px !default;
      -//** Carets increase slightly in size for larger components.
      -$caret-width-large:         5px !default;
      -
      -
      -//== Tables
      -//
      -//## Customizes the `.table` component with basic values, each used across all table variations.
      -
      -//** Padding for ``s and ``s.
      -$table-cell-padding:            8px !default;
      -//** Padding for cells in `.table-condensed`.
      -$table-condensed-cell-padding:  5px !default;
      -
      -//** Default background color used for all tables.
      -$table-bg:                      transparent !default;
      -//** Background color used for `.table-striped`.
      -$table-bg-accent:               #f9f9f9 !default;
      -//** Background color used for `.table-hover`.
      -$table-bg-hover:                #f5f5f5 !default;
      -$table-bg-active:               $table-bg-hover !default;
      -
      -//** Border color for table and cell borders.
      -$table-border-color:            #ddd !default;
      -
      -
      -//== Buttons
      -//
      -//## For each of Bootstrap's buttons, define text, background and border color.
      -
      -$btn-font-weight:                normal !default;
      -
      -$btn-default-color:              $text-color !default;
      -$btn-default-bg:                 #fff !default;
      -$btn-default-border:             #ddd !default;
      -
      -$btn-primary-color:              #fff !default;
      -$btn-primary-bg:                 $brand-primary !default;
      -$btn-primary-border:             $btn-primary-bg !default;
      -
      -$btn-success-color:              #fff !default;
      -$btn-success-bg:                 $brand-success !default;
      -$btn-success-border:             $btn-success-bg !default;
      -
      -$btn-info-color:                 #fff !default;
      -$btn-info-bg:                    $brand-info !default;
      -$btn-info-border:                $btn-info-bg !default;
      -
      -$btn-warning-color:              #fff !default;
      -$btn-warning-bg:                 $brand-warning !default;
      -$btn-warning-border:             $btn-warning-bg !default;
      -
      -$btn-danger-color:               #fff !default;
      -$btn-danger-bg:                  $brand-danger !default;
      -$btn-danger-border:              $btn-danger-bg !default;
      -
      -$btn-link-disabled-color:        $gray-light !default;
      -
      -// Allows for customizing button radius independently from global border radius
      -$btn-border-radius-base:         $border-radius-base !default;
      -$btn-border-radius-large:        $border-radius-large !default;
      -$btn-border-radius-small:        $border-radius-small !default;
      -
      -
      -//== Forms
      -//
      -//##
      -
      -//** `` background color
      -$input-bg:                       #fff !default;
      -//** `` background color
      -$input-bg-disabled:              $gray-lighter !default;
      -
      -//** Text color for ``s
      -$input-color:                    $text-color !default;
      -//** `` border color
      -$input-border:                   #ddd !default;
      -
      -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
      -//** Default `.form-control` border radius
      -// This has no effect on ``s in CSS.
      -$input-border-radius:            $border-radius-base !default;
      -//** Large `.form-control` border radius
      -$input-border-radius-large:      $border-radius-large !default;
      -//** Small `.form-control` border radius
      -$input-border-radius-small:      $border-radius-small !default;
      -
      -//** Border color for inputs on focus
      -$input-border-focus:             #66afe9 !default;
      -
      -//** Placeholder text color
      -$input-color-placeholder:        $gray-light !default;
      -
      -//** Default `.form-control` height
      -$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
      -//** Large `.form-control` height
      -$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
      -//** Small `.form-control` height
      -$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
      -
      -//** `.form-group` margin
      -$form-group-margin-bottom:       15px !default;
      -
      -$legend-color:                   $text-color !default;
      -$legend-border-color:            #e5e5e5 !default;
      -
      -//** Background color for textual input addons
      -$input-group-addon-bg:           $gray-lighter !default;
      -//** Border color for textual input addons
      -$input-group-addon-border-color: $input-border !default;
      -
      -//** Disabled cursor for form controls and buttons.
      -$cursor-disabled:                not-allowed !default;
      -
      -
      -//== Dropdowns
      -//
      -//## Dropdown menu container and contents.
      -
      -//** Background for the dropdown menu.
      -$dropdown-bg:                    #fff !default;
      -//** Dropdown menu `border-color`.
      -$dropdown-border:                rgba(0,0,0,.15) !default;
      -//** Dropdown menu `border-color` **for IE8**.
      -$dropdown-fallback-border:       #ccc !default;
      -//** Divider color for between dropdown items.
      -$dropdown-divider-bg:            #e5e5e5 !default;
      -
      -//** Dropdown link text color.
      -$dropdown-link-color:            $gray-dark !default;
      -//** Hover color for dropdown links.
      -$dropdown-link-hover-color:      #fff !default;
      -//** Hover background for dropdown links.
      -$dropdown-link-hover-bg:         $component-active-bg !default;
      -
      -//** Active dropdown menu item text color.
      -$dropdown-link-active-color:     #fff !default;
      -//** Active dropdown menu item background color.
      -$dropdown-link-active-bg:        $component-active-bg !default;
      -
      -//** Disabled dropdown menu item background color.
      -$dropdown-link-disabled-color:   $gray-light !default;
      -
      -//** Text color for headers within dropdown menus.
      -$dropdown-header-color:          $gray-light !default;
      -
      -//** Deprecated `$dropdown-caret-color` as of v3.1.0
      -$dropdown-caret-color:           #000 !default;
      -
      -
      -//-- Z-index master list
      -//
      -// Warning: Avoid customizing these values. They're used for a bird's eye view
      -// of components dependent on the z-axis and are designed to all work together.
      -//
      -// Note: These variables are not generated into the Customizer.
      -
      -$zindex-navbar:            1000 !default;
      -$zindex-dropdown:          1000 !default;
      -$zindex-popover:           1060 !default;
      -$zindex-tooltip:           1070 !default;
      -$zindex-navbar-fixed:      1030 !default;
      -$zindex-modal-background:  1040 !default;
      -$zindex-modal:             1050 !default;
      -
      -
      -//== Media queries breakpoints
      -//
      -//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
      -
      -// Extra small screen / phone
      -//** Deprecated `$screen-xs` as of v3.0.1
      -$screen-xs:                  480px !default;
      -//** Deprecated `$screen-xs-min` as of v3.2.0
      -$screen-xs-min:              $screen-xs !default;
      -//** Deprecated `$screen-phone` as of v3.0.1
      -$screen-phone:               $screen-xs-min !default;
      -
      -// Small screen / tablet
      -//** Deprecated `$screen-sm` as of v3.0.1
      -$screen-sm:                  768px !default;
      -$screen-sm-min:              $screen-sm !default;
      -//** Deprecated `$screen-tablet` as of v3.0.1
      -$screen-tablet:              $screen-sm-min !default;
      -
      -// Medium screen / desktop
      -//** Deprecated `$screen-md` as of v3.0.1
      -$screen-md:                  992px !default;
      -$screen-md-min:              $screen-md !default;
      -//** Deprecated `$screen-desktop` as of v3.0.1
      -$screen-desktop:             $screen-md-min !default;
      -
      -// Large screen / wide desktop
      -//** Deprecated `$screen-lg` as of v3.0.1
      -$screen-lg:                  1200px !default;
      -$screen-lg-min:              $screen-lg !default;
      -//** Deprecated `$screen-lg-desktop` as of v3.0.1
      -$screen-lg-desktop:          $screen-lg-min !default;
      -
      -// So media queries don't overlap when required, provide a maximum
      -$screen-xs-max:              ($screen-sm-min - 1) !default;
      -$screen-sm-max:              ($screen-md-min - 1) !default;
      -$screen-md-max:              ($screen-lg-min - 1) !default;
      -
      -
      -//== Grid system
      -//
      -//## Define your custom responsive grid.
      -
      -//** Number of columns in the grid.
      -$grid-columns:              12 !default;
      -//** Padding between columns. Gets divided in half for the left and right.
      -$grid-gutter-width:         30px !default;
      -// Navbar collapse
      -//** Point at which the navbar becomes uncollapsed.
      -$grid-float-breakpoint:     $screen-sm-min !default;
      -//** Point at which the navbar begins collapsing.
      -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
      -
      -
      -//== Container sizes
      -//
      -//## Define the maximum width of `.container` for different screen sizes.
      -
      -// Small screen / tablet
      -$container-tablet:             (720px + $grid-gutter-width) !default;
      -//** For `$screen-sm-min` and up.
      -$container-sm:                 $container-tablet !default;
      -
      -// Medium screen / desktop
      -$container-desktop:            (940px + $grid-gutter-width) !default;
      -//** For `$screen-md-min` and up.
      -$container-md:                 $container-desktop !default;
      -
      -// Large screen / wide desktop
      -$container-large-desktop:      (1140px + $grid-gutter-width) !default;
      -//** For `$screen-lg-min` and up.
      -$container-lg:                 $container-large-desktop !default;
      -
      -
      -//== Navbar
      -//
      -//##
      -
      -// Basics of a navbar
      -$navbar-height:                    65px !default;
      -$navbar-margin-bottom:             $line-height-computed !default;
      -$navbar-border-radius:             $border-radius-base !default;
      -$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
      -$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
      -$navbar-collapse-max-height:       340px !default;
      -
      -$navbar-default-color:             $text-color !default;
      -$navbar-default-bg:                $body-bg !default;
      -$navbar-default-border:            #ddd !default;
      -
      -// Navbar links
      -$navbar-default-link-color:                $link-color !default;
      -$navbar-default-link-hover-color:          $link-color !default;
      -$navbar-default-link-hover-bg:             transparent !default;
      -$navbar-default-link-active-color:         $navbar-default-link-color !default;
      -$navbar-default-link-active-bg:            transparent !default;
      -$navbar-default-link-disabled-color:       #333 !default;
      -$navbar-default-link-disabled-bg:          transparent !default;
      -
      -// Navbar brand label
      -$navbar-default-brand-color:               $navbar-default-link-color !default;
      -$navbar-default-brand-hover-color:         $navbar-default-link-hover-color !default;
      -$navbar-default-brand-hover-bg:            transparent !default;
      -
      -// Navbar toggle
      -$navbar-default-toggle-hover-bg:           #ddd !default;
      -$navbar-default-toggle-icon-bar-bg:        #ccc !default;
      -$navbar-default-toggle-border-color:       #ddd !default;
      -
      -
      -//=== Inverted navbar
      -// Reset inverted navbar basics
      -$navbar-inverse-color:                      $text-color !default;
      -$navbar-inverse-bg:                         $body-bg !default;
      -$navbar-inverse-border:                     #ddd !default;
      -
      -// Inverted navbar links
      -$navbar-inverse-link-color:                 $text-color !default;
      -$navbar-inverse-link-hover-color:           $text-color !default;
      -$navbar-inverse-link-hover-bg:              transparent !default;
      -$navbar-inverse-link-active-color:          $text-color !default;
      -$navbar-inverse-link-active-bg:             transparent !default;
      -$navbar-inverse-link-disabled-color:        #ccc !default;
      -$navbar-inverse-link-disabled-bg:           transparent !default;
      -
      -// Inverted navbar brand label
      -$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;
      -$navbar-inverse-brand-hover-color:          $navbar-inverse-link-hover-color !default;
      -$navbar-inverse-brand-hover-bg:             transparent !default;
      -
      -// Inverted navbar toggle
      -$navbar-inverse-toggle-hover-bg:            #ddd !default;
      -$navbar-inverse-toggle-icon-bar-bg:         #ccc !default;
      -$navbar-inverse-toggle-border-color:        #ddd !default;
      -
      -
      -//== Navs
      -//
      -//##
      -
      -//=== Shared nav styles
      -$nav-link-padding:                          10px 15px !default;
      -$nav-link-hover-bg:                         $gray-lighter !default;
      -
      -$nav-disabled-link-color:                   $gray-light !default;
      -$nav-disabled-link-hover-color:             $gray-light !default;
      -
      -//== Tabs
      -$nav-tabs-border-color:                     #ddd !default;
      -
      -$nav-tabs-link-hover-border-color:          $gray-lighter !default;
      -
      -$nav-tabs-active-link-hover-bg:             $body-bg !default;
      -$nav-tabs-active-link-hover-color:          $gray !default;
      -$nav-tabs-active-link-hover-border-color:   #ddd !default;
      -
      -$nav-tabs-justified-link-border-color:            #ddd !default;
      -$nav-tabs-justified-active-link-border-color:     $body-bg !default;
      -
      -//== Pills
      -$nav-pills-border-radius:                   $border-radius-base !default;
      -$nav-pills-active-link-hover-bg:            $component-active-bg !default;
      -$nav-pills-active-link-hover-color:         $component-active-color !default;
      -
      -
      -//== Pagination
      -//
      -//##
      -
      -$pagination-color:                     $text-color !default;
      -$pagination-bg:                        #fff !default;
      -$pagination-border:                    #ddd !default;
      -
      -$pagination-hover-color:               #fff !default;
      -$pagination-hover-bg:                  $brand-primary !default;
      -$pagination-hover-border:              $brand-primary !default;
      -
      -$pagination-active-color:              #fff !default;
      -$pagination-active-bg:                 $brand-primary !default;
      -$pagination-active-border:             $brand-primary !default;
      -
      -$pagination-disabled-color:            $gray-light !default;
      -$pagination-disabled-bg:               #fff !default;
      -$pagination-disabled-border:           #ddd !default;
      -
      -
      -//== Pager
      -//
      -//##
      -
      -$pager-bg:                             $pagination-bg !default;
      -$pager-border:                         $pagination-border !default;
      -$pager-border-radius:                  15px !default;
      -
      -$pager-hover-bg:                       $pagination-hover-bg !default;
      -
      -$pager-active-bg:                      $pagination-active-bg !default;
      -$pager-active-color:                   $pagination-active-color !default;
      -
      -$pager-disabled-color:                 $gray-light !default;
      -
      -
      -//== Jumbotron
      -//
      -//##
      -
      -$jumbotron-padding:              30px !default;
      -$jumbotron-color:                inherit !default;
      -$jumbotron-bg:                   darken($body-bg, 3%) !default;
      -$jumbotron-heading-color:        inherit !default;
      -$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
      -$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
      -
      -
      -//== Form states and alerts
      -//
      -//## Define colors for form feedback states and, by default, alerts.
      -
      -$state-success-text:             $brand-success !default;
      -$state-success-bg:               #dff0d8 !default;
      -$state-success-border:           $brand-success !default;
      -
      -$state-info-text:                $brand-info !default;
      -$state-info-bg:                  #d9edf7 !default;
      -$state-info-border:              $brand-info !default;
      -
      -$state-warning-text:             $brand-warning !default;
      -$state-warning-bg:               #fcf8e3 !default;
      -$state-warning-border:           $brand-warning !default;
      -
      -$state-danger-text:              $brand-danger !default;
      -$state-danger-bg:                #f2dede !default;
      -$state-danger-border:            $brand-danger !default;
      -
      -
      -//== Tooltips
      -//
      -//##
      -
      -//** Tooltip max width
      -$tooltip-max-width:           200px !default;
      -//** Tooltip text color
      -$tooltip-color:               #fff !default;
      -//** Tooltip background color
      -$tooltip-bg:                  #000 !default;
      -$tooltip-opacity:             .9 !default;
      -
      -//** Tooltip arrow width
      -$tooltip-arrow-width:         5px !default;
      -//** Tooltip arrow color
      -$tooltip-arrow-color:         $tooltip-bg !default;
      -
      -
      -//== Popovers
      -//
      -//##
      -
      -//** Popover body background color
      -$popover-bg:                          #fff !default;
      -//** Popover maximum width
      -$popover-max-width:                   276px !default;
      -//** Popover border color
      -$popover-border-color:                rgba(0,0,0,.2) !default;
      -//** Popover fallback border color
      -$popover-fallback-border-color:       #ccc !default;
      -
      -//** Popover title background color
      -$popover-title-bg:                    darken($popover-bg, 3%) !default;
      -
      -//** Popover arrow width
      -$popover-arrow-width:                 10px !default;
      -//** Popover arrow color
      -$popover-arrow-color:                 $popover-bg !default;
      -
      -//** Popover outer arrow width
      -$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
      -//** Popover outer arrow color
      -$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
      -//** Popover outer arrow fallback color
      -$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
      -
      -
      -//== Labels
      -//
      -//##
      -
      -//** Default label background color
      -$label-default-bg:            $btn-default-bg !default;
      -//** Primary label background color
      -$label-primary-bg:            $brand-primary !default;
      -//** Success label background color
      -$label-success-bg:            $brand-success !default;
      -//** Info label background color
      -$label-info-bg:               $brand-info !default;
      -//** Warning label background color
      -$label-warning-bg:            $brand-warning !default;
      -//** Danger label background color
      -$label-danger-bg:             $brand-danger !default;
      -
      -//** Default label text color
      -$label-color:                 #fff !default;
      -//** Default text color of a linked label
      -$label-link-hover-color:      #fff !default;
      -
      -
      -//== Modals
      -//
      -//##
      -
      -//** Padding applied to the modal body
      -$modal-inner-padding:         20px !default;
      -
      -//** Padding applied to the modal title
      -$modal-title-padding:         15px !default;
      -//** Modal title line-height
      -$modal-title-line-height:     $line-height-base !default;
      -
      -//** Background color of modal content area
      -$modal-content-bg:                             #fff !default;
      -//** Modal content border color
      -$modal-content-border-color:                   rgba(0,0,0,.2) !default;
      -//** Modal content border color **for IE8**
      -$modal-content-fallback-border-color:          #999 !default;
      -
      -//** Modal backdrop background color
      -$modal-backdrop-bg:           #000 !default;
      -//** Modal backdrop opacity
      -$modal-backdrop-opacity:      .5 !default;
      -//** Modal header border color
      -$modal-header-border-color:   #e5e5e5 !default;
      -//** Modal footer border color
      -$modal-footer-border-color:   $modal-header-border-color !default;
      -
      -$modal-lg:                    900px !default;
      -$modal-md:                    600px !default;
      -$modal-sm:                    300px !default;
      -
      -
      -//== Alerts
      -//
      -//## Define alert colors, border radius, and padding.
      -
      -$alert-padding:               15px !default;
      -$alert-border-radius:         $border-radius-base !default;
      -$alert-link-font-weight:      bold !default;
      -
      -$alert-success-bg:            $state-success-border !default;
      -$alert-success-text:          #fff !default;
      -$alert-success-border:        $state-success-border !default;
      -
      -$alert-info-bg:               $state-info-border !default;
      -$alert-info-text:             #fff !default;
      -$alert-info-border:           $state-info-border !default;
      -
      -$alert-warning-bg:            $state-warning-border !default;
      -$alert-warning-text:          #fff !default;
      -$alert-warning-border:        $state-warning-border !default;
      -
      -$alert-danger-bg:             $state-danger-border !default;
      -$alert-danger-text:           #fff !default;
      -$alert-danger-border:         $state-danger-border !default;
      -
      -
      -//== Progress bars
      -//
      -//##
      -
      -//** Background color of the whole progress component
      -$progress-bg:                 #f5f5f5 !default;
      -//** Progress bar text color
      -$progress-bar-color:          #fff !default;
      -//** Variable for setting rounded corners on progress bar.
      -$progress-border-radius:      $border-radius-base !default;
      -
      -//** Default progress bar color
      -$progress-bar-bg:             $brand-primary !default;
      -//** Success progress bar color
      -$progress-bar-success-bg:     $brand-success !default;
      -//** Warning progress bar color
      -$progress-bar-warning-bg:     $brand-warning !default;
      -//** Danger progress bar color
      -$progress-bar-danger-bg:      $brand-danger !default;
      -//** Info progress bar color
      -$progress-bar-info-bg:        $brand-info !default;
      -
      -
      -//== List group
      -//
      -//##
      -
      -//** Background color on `.list-group-item`
      -$list-group-bg:                 #fff !default;
      -//** `.list-group-item` border color
      -$list-group-border:             #ddd !default;
      -//** List group border radius
      -$list-group-border-radius:      $border-radius-base !default;
      -
      -//** Background color of single list items on hover
      -$list-group-hover-bg:           #f5f5f5 !default;
      -//** Text color of active list items
      -$list-group-active-color:       $component-active-color !default;
      -//** Background color of active list items
      -$list-group-active-bg:          $component-active-bg !default;
      -//** Border color of active list elements
      -$list-group-active-border:      $list-group-active-bg !default;
      -//** Text color for content within active list items
      -$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
      -
      -//** Text color of disabled list items
      -$list-group-disabled-color:      $gray-light !default;
      -//** Background color of disabled list items
      -$list-group-disabled-bg:         $gray-lighter !default;
      -//** Text color for content within disabled list items
      -$list-group-disabled-text-color: $list-group-disabled-color !default;
      -
      -$list-group-link-color:         #555 !default;
      -$list-group-link-hover-color:   $list-group-link-color !default;
      -$list-group-link-heading-color: #333 !default;
      -
      -
      -//== Panels
      -//
      -//##
      -
      -$panel-bg:                    #fff !default;
      -$panel-body-padding:          15px !default;
      -$panel-heading-padding:       10px 15px !default;
      -$panel-footer-padding:        $panel-heading-padding !default;
      -$panel-border-radius:         $border-radius-base !default;
      -
      -//** Border color for elements within panels
      -$panel-inner-border:          #ddd !default;
      -$panel-footer-bg:             #fff !default;
      -
      -$panel-default-text:          $gray-dark !default;
      -$panel-default-border:        #ddd !default;
      -$panel-default-heading-bg:    #f5f5f5 !default;
      -
      -$panel-primary-text:          #fff !default;
      -$panel-primary-border:        $brand-primary !default;
      -$panel-primary-heading-bg:    $brand-primary !default;
      -
      -$panel-success-text:          #fff !default;
      -$panel-success-border:        $state-success-border !default;
      -$panel-success-heading-bg:    $state-success-border !default;
      -
      -$panel-info-text:             #fff !default;
      -$panel-info-border:           $state-info-border !default;
      -$panel-info-heading-bg:       $state-info-border !default;
      -
      -$panel-warning-text:          #fff !default;
      -$panel-warning-border:        $state-warning-border !default;
      -$panel-warning-heading-bg:    $state-warning-border !default;
      -
      -$panel-danger-text:           #fff !default;
      -$panel-danger-border:         $state-danger-border !default;
      -$panel-danger-heading-bg:     $state-danger-border !default;
      -
      -
      -//== Thumbnails
      -//
      -//##
      -
      -//** Padding around the thumbnail image
      -$thumbnail-padding:           4px !default;
      -//** Thumbnail background color
      -$thumbnail-bg:                $body-bg !default;
      -//** Thumbnail border color
      -$thumbnail-border:            #ddd !default;
      -//** Thumbnail border radius
      -$thumbnail-border-radius:     $border-radius-base !default;
      -
      -//** Custom text color for thumbnail captions
      -$thumbnail-caption-color:     $text-color !default;
      -//** Padding around the thumbnail caption
      -$thumbnail-caption-padding:   9px !default;
      -
      -
      -//== Wells
      -//
      -//##
      -
      -$well-bg:                     darken($body-bg, 3%) !default;
      -$well-border:                 darken($well-bg, 7%) !default;
      -
      -
      -//== Badges
      -//
      -//##
      -
      -$badge-color:                 #fff !default;
      -//** Linked badge text color on hover
      -$badge-link-hover-color:      #fff !default;
      -$badge-bg:                    $brand-primary !default;
      -
      -//** Badge text color in active nav link
      -$badge-active-color:          $link-color !default;
      -//** Badge background color in active nav link
      -$badge-active-bg:             #fff !default;
      -
      -$badge-font-weight:           bold !default;
      -$badge-line-height:           1 !default;
      -$badge-border-radius:         10px !default;
      -
      -
      -//== Breadcrumbs
      -//
      -//##
      -
      -$breadcrumb-padding-vertical:   8px !default;
      -$breadcrumb-padding-horizontal: 15px !default;
      -//** Breadcrumb background color
      -$breadcrumb-bg:                 #f5f5f5 !default;
      -//** Breadcrumb text color
      -$breadcrumb-color:              #ccc !default;
      -//** Text color of current page in the breadcrumb
      -$breadcrumb-active-color:       $gray-light !default;
      -//** Textual separator for between breadcrumb elements
      -$breadcrumb-separator:          "/" !default;
      -
      -
      -//== Carousel
      -//
      -//##
      -
      -$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
      -
      -$carousel-control-color:                      #fff !default;
      -$carousel-control-width:                      15% !default;
      -$carousel-control-opacity:                    .5 !default;
      -$carousel-control-font-size:                  20px !default;
      -
      -$carousel-indicator-active-bg:                #fff !default;
      -$carousel-indicator-border-color:             #fff !default;
      -
      -$carousel-caption-color:                      #fff !default;
      -
      -
      -//== Close
      -//
      -//##
      -
      -$close-font-weight:           bold !default;
      -$close-color:                 #fff !default;
      -$close-text-shadow:           0 1px 0 #fff !default;
      -
      -
      -//== Code
      -//
      -//##
      -
      -$code-color:                  #c7254e !default;
      -$code-bg:                     #f9f2f4 !default;
      -
      -$kbd-color:                   #fff !default;
      -$kbd-bg:                      #333 !default;
      -
      -$pre-bg:                      #f5f5f5 !default;
      -$pre-color:                   $gray-dark !default;
      -$pre-border-color:            #ccc !default;
      -$pre-scrollable-max-height:   340px !default;
      -
      -
      -//== Type
      -//
      -//##
      -
      -//** Horizontal offset for forms and lists.
      -$component-offset-horizontal: 180px !default;
      -//** Text muted color
      -$text-muted:                  $gray-light !default;
      -//** Abbreviations and acronyms border color
      -$abbr-border-color:           $gray-light !default;
      -//** Headings small color
      -$headings-small-color:        $gray-light !default;
      -//** Blockquote small color
      -$blockquote-small-color:      $text-color !default;
      -//** Blockquote font size
      -$blockquote-font-size:        ($font-size-base * 1.25) !default;
      -//** Blockquote border color
      -$blockquote-border-color:     $brand-primary !default;
      -//** Page header border color
      -$page-header-border-color:    #ddd !default;
      -//** Width of horizontal description list titles
      -$dl-horizontal-offset:        $component-offset-horizontal !default;
      -//** Point at which .dl-horizontal becomes horizontal
      -$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
      -//** Horizontal line color.
      -$hr-border:                   $gray-lighter !default;
      diff --git a/vendor/assets/stylesheets/sandstone/_bootswatch.scss b/vendor/assets/stylesheets/sandstone/_bootswatch.scss
      deleted file mode 100644
      index 894cca1..0000000
      --- a/vendor/assets/stylesheets/sandstone/_bootswatch.scss
      +++ /dev/null
      @@ -1,195 +0,0 @@
      -// Sandstone 3.3.5
      -// Bootswatch
      -// -----------------------------------------------------
      -
      -//$web-font-path: "https://fonts.googleapis.com/css?family=Roboto:400,500" !default;
      -//@import url($web-font-path);
      -
      -// Navbar =====================================================================
      -
      -.sandstone {
      -  font-size: 11px;
      -  line-height: 22px;
      -  font-weight: 500;
      -  text-transform: uppercase;
      -}
      -
      -.navbar {
      -  .nav > li > a {
      -    @extend .sandstone;
      -  }
      -
      -  &-form input,
      -  &-form .form-control {
      -    border: none;
      -  }
      -}
      -
      -// Buttons ====================================================================
      -
      -.btn {
      -  border: none;
      -  @extend .sandstone;
      -
      -  &:hover {
      -    border-color: transparent;
      -  }
      -
      -  &-lg {
      -    line-height: 26px;
      -  }
      -
      -  &-default {
      -    &:hover {
      -      background-color: $navbar-default-link-active-bg;
      -    }
      -  }
      -}
      -
      -// Typography =================================================================
      -
      -// Tables =====================================================================
      -
      -// Forms ======================================================================
      -
      -input,
      -.form-control {
      -  @include box-shadow(none);
      -
      -  &:focus {
      -    border-color: $input-border;
      -    @include box-shadow(none);
      -  }
      -}
      -
      -// Navs =======================================================================
      -
      -.nav {
      -  @extend .sandstone;
      -
      -  .open > a,
      -  .open > a:hover,
      -  .open > a:focus {
      -    border-color: $gray-light;
      -  }
      -}
      -
      -.nav-tabs {
      -
      -  & > li > a {
      -    background-color: $gray-lighter;
      -    border-color: $nav-tabs-border-color;
      -    color: $gray;
      -  }
      -
      -  > li.disabled > a:hover {
      -    background-color: $gray-lighter;
      -  }
      -}
      -
      -.nav-pills {
      -  a {
      -    color: $gray;
      -  }
      -
      -  li > a {
      -    border: 1px solid transparent;
      -  }
      -
      -  li.active > a,
      -  li > a:hover {
      -    border-color: $gray-light;
      -  }
      -
      -  li.disabled > a {
      -    border-color: transparent;
      -  }
      -}
      -
      -.breadcrumb {
      -  @extend .sandstone;
      -
      -  border: 1px solid $gray-light;
      -
      -  a {
      -    color: $gray;
      -  }
      -}
      -
      -.pagination {
      -  @extend .sandstone;
      -}
      -
      -.pager {
      -  @extend .sandstone;
      -
      -  li > a {
      -    color: $gray;
      -  }
      -}
      -
      -.dropdown-menu {
      -  & > li > a {
      -    @extend .sandstone;
      -  }
      -}
      -
      -// Indicators =================================================================
      -
      -.alert {
      -
      -  a,
      -  .alert-link {
      -    color: #fff;
      -  }
      -}
      -
      -.tooltip {
      -  @extend .sandstone;
      -}
      -
      -// Progress bars ==============================================================
      -
      -.progress {
      -  border-radius: 10px;
      -  background-color: $gray-light;
      -  @include box-shadow(none);
      -
      -  &-bar {
      -    @include box-shadow(none);
      -  }
      -}
      -
      -// Containers =================================================================
      -
      -.list-group {
      -  &-item {
      -    padding: 16px 24px;
      -  }
      -}
      -
      -.well {
      -  @include box-shadow(none);
      -}
      -
      -.panel {
      -  @include box-shadow(none);
      -
      -  .panel-heading,
      -  .panel-title {
      -    @extend .sandstone;
      -    color: #fff;
      -  }
      -
      -  .panel-footer {
      -    @extend .sandstone;
      -  }
      -
      -  &-default {
      -    .panel-heading,
      -    .panel-title,
      -    .panel-footer {
      -      color: $gray;
      -    }
      -  }
      -}
      diff --git a/vendor/assets/stylesheets/sandstone/_variables.scss b/vendor/assets/stylesheets/sandstone/_variables.scss
      deleted file mode 100644
      index 5c5847c..0000000
      --- a/vendor/assets/stylesheets/sandstone/_variables.scss
      +++ /dev/null
      @@ -1,870 +0,0 @@
      -$bootstrap-sass-asset-helper: false !default;
      -// Sandstone 3.3.6
      -// Variables
      -// --------------------------------------------------
      -
      -
      -//== Colors
      -//
      -//## Gray and brand colors for use across Bootstrap.
      -
      -$gray-base:              #000 !default;
      -$gray-darker:            #3E3F3A !default;
      -$gray-dark:              #8E8C84 !default;
      -$gray:                   #98978B !default;
      -$gray-light:             #DFD7CA !default;
      -$gray-lighter:           #F8F5F0 !default;
      -
      -$brand-primary:         #325D88 !default;
      -$brand-success:         #93C54B !default;
      -$brand-info:            #29ABE0 !default;
      -$brand-warning:         #F47C3C !default;
      -$brand-danger:          #d9534f !default;
      -
      -
      -//== Scaffolding
      -//
      -//## Settings for some of the most global styles.
      -
      -//** Background color for ``.
      -$body-bg:               #fff !default;
      -//** Global text color on ``.
      -$text-color:            #3E3F3A !default;
      -
      -//** Global textual link color.
      -$link-color:            $brand-success !default;
      -//** Link hover color set via `darken()` function.
      -$link-hover-color:      darken($link-color, 10%) !default;
      -//** Link hover decoration.
      -$link-hover-decoration: underline !default;
      -
      -
      -//== Typography
      -//
      -//## Font, line-height, and color for body text, headings, and more.
      -
      -$font-family-sans-serif:  "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
      -$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
      -//** Default monospace fonts for ``, ``, and `
      `.
      -$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
      -$font-family-base:        $font-family-sans-serif !default;
      -
      -$font-size-base:          14px !default;
      -$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
      -$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
      -$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
      -$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-h5:            $font-size-base !default;
      -$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -//** Unit-less `line-height` for use in components like buttons.
      -$line-height-base:        1.428571429 !default; // 20/14
      -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
      -$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
      -
      -//** By default, this inherits from the ``.
      -$headings-font-family:    inherit !default;
      -$headings-font-weight:    400 !default;
      -$headings-line-height:    1.1 !default;
      -$headings-color:          inherit !default;
      -
      -
      -//== Iconography
      -//
      -//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
      -
      -//** Load fonts from this directory.
      -$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
      -//** File name for all font files.
      -$icon-font-name:          "glyphicons-halflings-regular" !default;
      -//** Element ID within SVG icon file.
      -$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
      -
      -
      -//== Components
      -//
      -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
      -
      -$padding-base-vertical:     12px !default;
      -$padding-base-horizontal:   16px !default;
      -
      -$padding-large-vertical:    20px !default;
      -$padding-large-horizontal:  30px !default;
      -
      -$padding-small-vertical:    5px !default;
      -$padding-small-horizontal:  10px !default;
      -
      -$padding-xs-vertical:       1px !default;
      -$padding-xs-horizontal:     5px !default;
      -
      -$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
      -$line-height-small:         1.5 !default;
      -
      -$border-radius-base:        4px !default;
      -$border-radius-large:       6px !default;
      -$border-radius-small:       3px !default;
      -
      -//** Global color for active items (e.g., navs or dropdowns).
      -$component-active-color:    $gray !default;
      -//** Global background color for active items (e.g., navs or dropdowns).
      -$component-active-bg:       $gray-lighter !default;
      -
      -//** Width of the `border` for generating carets that indicator dropdowns.
      -$caret-width-base:          4px !default;
      -//** Carets increase slightly in size for larger components.
      -$caret-width-large:         5px !default;
      -
      -
      -//== Tables
      -//
      -//## Customizes the `.table` component with basic values, each used across all table variations.
      -
      -//** Padding for ``s and ``s.
      -$table-cell-padding:            8px !default;
      -//** Padding for cells in `.table-condensed`.
      -$table-condensed-cell-padding:  5px !default;
      -
      -//** Default background color used for all tables.
      -$table-bg:                      transparent !default;
      -//** Background color used for `.table-striped`.
      -$table-bg-accent:               $gray-lighter !default;
      -//** Background color used for `.table-hover`.
      -$table-bg-hover:                $gray-lighter !default;
      -$table-bg-active:               $table-bg-hover !default;
      -
      -//** Border color for table and cell borders.
      -$table-border-color:            $gray-light !default;
      -
      -
      -//== Buttons
      -//
      -//## For each of Bootstrap's buttons, define text, background and border color.
      -
      -$btn-font-weight:                normal !default;
      -
      -$btn-default-color:              #fff !default;
      -$btn-default-bg:                 $gray-darker !default;
      -$btn-default-border:             transparent !default;
      -
      -$btn-primary-color:              #fff !default;
      -$btn-primary-bg:                 $brand-primary !default;
      -$btn-primary-border:             transparent !default;
      -
      -$btn-success-color:              #fff !default;
      -$btn-success-bg:                 $brand-success !default;
      -$btn-success-border:             transparent !default;
      -
      -$btn-info-color:                 #fff !default;
      -$btn-info-bg:                    $brand-info !default;
      -$btn-info-border:                transparent !default;
      -
      -$btn-warning-color:              #fff !default;
      -$btn-warning-bg:                 $brand-warning !default;
      -$btn-warning-border:             transparent !default;
      -
      -$btn-danger-color:               #fff !default;
      -$btn-danger-bg:                  $brand-danger !default;
      -$btn-danger-border:              transparent !default;
      -
      -$btn-link-disabled-color:        $gray-light !default;
      -
      -// Allows for customizing button radius independently from global border radius
      -$btn-border-radius-base:         $border-radius-base !default;
      -$btn-border-radius-large:        $border-radius-large !default;
      -$btn-border-radius-small:        $border-radius-small !default;
      -
      -
      -//== Forms
      -//
      -//##
      -
      -//** `` background color
      -$input-bg:                       #fff !default;
      -//** `` background color
      -$input-bg-disabled:              $gray-lighter !default;
      -
      -//** Text color for ``s
      -$input-color:                    $text-color !default;
      -//** `` border color
      -$input-border:                   $gray-light !default;
      -
      -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
      -//** Default `.form-control` border radius
      -// This has no effect on ``s in CSS.
      -$input-border-radius:            $border-radius-base !default;
      -//** Large `.form-control` border radius
      -$input-border-radius-large:      $border-radius-large !default;
      -//** Small `.form-control` border radius
      -$input-border-radius-small:      $border-radius-small !default;
      -
      -//** Border color for inputs on focus
      -$input-border-focus:             transparent !default;
      -
      -//** Placeholder text color
      -$input-color-placeholder:        $gray-light !default;
      -
      -//** Default `.form-control` height
      -$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
      -//** Large `.form-control` height
      -$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
      -//** Small `.form-control` height
      -$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
      -
      -//** `.form-group` margin
      -$form-group-margin-bottom:       15px !default;
      -
      -$legend-color:                   $headings-color !default;
      -$legend-border-color:            transparent !default;
      -
      -//** Background color for textual input addons
      -$input-group-addon-bg:           $gray-lighter !default;
      -//** Border color for textual input addons
      -$input-group-addon-border-color: $input-border !default;
      -
      -//** Disabled cursor for form controls and buttons.
      -$cursor-disabled:                not-allowed !default;
      -
      -
      -//== Dropdowns
      -//
      -//## Dropdown menu container and contents.
      -
      -//** Background for the dropdown menu.
      -$dropdown-bg:                    #fff !default;
      -//** Dropdown menu `border-color`.
      -$dropdown-border:                $gray-light !default;
      -//** Dropdown menu `border-color` **for IE8**.
      -$dropdown-fallback-border:       $gray-light !default;
      -//** Divider color for between dropdown items.
      -$dropdown-divider-bg:            $gray-lighter !default;
      -
      -//** Dropdown link text color.
      -$dropdown-link-color:            $gray !default;
      -//** Hover color for dropdown links.
      -$dropdown-link-hover-color:      $dropdown-link-color !default;
      -//** Hover background for dropdown links.
      -$dropdown-link-hover-bg:         $gray-lighter !default;
      -
      -//** Active dropdown menu item text color.
      -$dropdown-link-active-color:     $component-active-color !default;
      -//** Active dropdown menu item background color.
      -$dropdown-link-active-bg:        $component-active-bg !default;
      -
      -//** Disabled dropdown menu item background color.
      -$dropdown-link-disabled-color:   $gray-light !default;
      -
      -//** Text color for headers within dropdown menus.
      -$dropdown-header-color:          $gray-light !default;
      -
      -//** Deprecated `$dropdown-caret-color` as of v3.1.0
      -$dropdown-caret-color:           #000 !default;
      -
      -
      -//-- Z-index master list
      -//
      -// Warning: Avoid customizing these values. They're used for a bird's eye view
      -// of components dependent on the z-axis and are designed to all work together.
      -//
      -// Note: These variables are not generated into the Customizer.
      -
      -$zindex-navbar:            1000 !default;
      -$zindex-dropdown:          1000 !default;
      -$zindex-popover:           1060 !default;
      -$zindex-tooltip:           1070 !default;
      -$zindex-navbar-fixed:      1030 !default;
      -$zindex-modal-background:  1040 !default;
      -$zindex-modal:             1050 !default;
      -
      -
      -//== Media queries breakpoints
      -//
      -//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
      -
      -// Extra small screen / phone
      -//** Deprecated `$screen-xs` as of v3.0.1
      -$screen-xs:                  480px !default;
      -//** Deprecated `$screen-xs-min` as of v3.2.0
      -$screen-xs-min:              $screen-xs !default;
      -//** Deprecated `$screen-phone` as of v3.0.1
      -$screen-phone:               $screen-xs-min !default;
      -
      -// Small screen / tablet
      -//** Deprecated `$screen-sm` as of v3.0.1
      -$screen-sm:                  768px !default;
      -$screen-sm-min:              $screen-sm !default;
      -//** Deprecated `$screen-tablet` as of v3.0.1
      -$screen-tablet:              $screen-sm-min !default;
      -
      -// Medium screen / desktop
      -//** Deprecated `$screen-md` as of v3.0.1
      -$screen-md:                  992px !default;
      -$screen-md-min:              $screen-md !default;
      -//** Deprecated `$screen-desktop` as of v3.0.1
      -$screen-desktop:             $screen-md-min !default;
      -
      -// Large screen / wide desktop
      -//** Deprecated `$screen-lg` as of v3.0.1
      -$screen-lg:                  1200px !default;
      -$screen-lg-min:              $screen-lg !default;
      -//** Deprecated `$screen-lg-desktop` as of v3.0.1
      -$screen-lg-desktop:          $screen-lg-min !default;
      -
      -// So media queries don't overlap when required, provide a maximum
      -$screen-xs-max:              ($screen-sm-min - 1) !default;
      -$screen-sm-max:              ($screen-md-min - 1) !default;
      -$screen-md-max:              ($screen-lg-min - 1) !default;
      -
      -
      -//== Grid system
      -//
      -//## Define your custom responsive grid.
      -
      -//** Number of columns in the grid.
      -$grid-columns:              12 !default;
      -//** Padding between columns. Gets divided in half for the left and right.
      -$grid-gutter-width:         30px !default;
      -// Navbar collapse
      -//** Point at which the navbar becomes uncollapsed.
      -$grid-float-breakpoint:     $screen-sm-min !default;
      -//** Point at which the navbar begins collapsing.
      -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
      -
      -
      -//== Container sizes
      -//
      -//## Define the maximum width of `.container` for different screen sizes.
      -
      -// Small screen / tablet
      -$container-tablet:             (720px + $grid-gutter-width) !default;
      -//** For `$screen-sm-min` and up.
      -$container-sm:                 $container-tablet !default;
      -
      -// Medium screen / desktop
      -$container-desktop:            (940px + $grid-gutter-width) !default;
      -//** For `$screen-md-min` and up.
      -$container-md:                 $container-desktop !default;
      -
      -// Large screen / wide desktop
      -$container-large-desktop:      (1140px + $grid-gutter-width) !default;
      -//** For `$screen-lg-min` and up.
      -$container-lg:                 $container-large-desktop !default;
      -
      -
      -//== Navbar
      -//
      -//##
      -
      -// Basics of a navbar
      -$navbar-height:                    60px !default;
      -$navbar-margin-bottom:             $line-height-computed !default;
      -$navbar-border-radius:             $border-radius-base !default;
      -$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
      -$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
      -$navbar-collapse-max-height:       340px !default;
      -
      -$navbar-default-color:             $gray-dark !default;
      -$navbar-default-bg:                $gray-darker !default;
      -$navbar-default-border:            $gray-darker !default;
      -
      -// Navbar links
      -$navbar-default-link-color:                $gray !default;
      -$navbar-default-link-hover-color:          #fff !default;
      -$navbar-default-link-hover-bg:             transparent !default;
      -$navbar-default-link-active-color:         #fff !default;
      -$navbar-default-link-active-bg:            darken($navbar-default-bg, 2%) !default;
      -$navbar-default-link-disabled-color:       #ccc !default;
      -$navbar-default-link-disabled-bg:          transparent !default;
      -
      -// Navbar brand label
      -$navbar-default-brand-color:               #fff !default;
      -$navbar-default-brand-hover-color:         #fff !default;
      -$navbar-default-brand-hover-bg:            transparent !default;
      -
      -// Navbar toggle
      -$navbar-default-toggle-hover-bg:           $navbar-default-link-active-bg !default;
      -$navbar-default-toggle-icon-bar-bg:        $navbar-default-link-color !default;
      -$navbar-default-toggle-border-color:       transparent !default;
      -
      -
      -//=== Inverted navbar
      -// Reset inverted navbar basics
      -$navbar-inverse-color:                      $gray-light !default;
      -$navbar-inverse-bg:                         $brand-success !default;
      -$navbar-inverse-border:                     $brand-success !default;
      -
      -// Inverted navbar links
      -$navbar-inverse-link-color:                 darken($brand-success, 15%) !default;
      -$navbar-inverse-link-hover-color:           #fff !default;
      -$navbar-inverse-link-hover-bg:              transparent !default;
      -$navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color !default;
      -$navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 4%) !default;
      -$navbar-inverse-link-disabled-color:        #444 !default;
      -$navbar-inverse-link-disabled-bg:           transparent !default;
      -
      -// Inverted navbar brand label
      -$navbar-inverse-brand-color:                #fff !default;
      -$navbar-inverse-brand-hover-color:          #fff !default;
      -$navbar-inverse-brand-hover-bg:             transparent !default;
      -
      -// Inverted navbar toggle
      -$navbar-inverse-toggle-hover-bg:            $navbar-inverse-link-active-bg !default;
      -$navbar-inverse-toggle-icon-bar-bg:         $navbar-inverse-link-color !default;
      -$navbar-inverse-toggle-border-color:        transparent !default;
      -
      -
      -//== Navs
      -//
      -//##
      -
      -//=== Shared nav styles
      -$nav-link-padding:                          10px 15px !default;
      -$nav-link-hover-bg:                         $gray-lighter !default;
      -
      -$nav-disabled-link-color:                   $gray-light !default;
      -$nav-disabled-link-hover-color:             $gray-light !default;
      -
      -//== Tabs
      -$nav-tabs-border-color:                     $gray-light !default;
      -
      -$nav-tabs-link-hover-border-color:          $gray-light !default;
      -
      -$nav-tabs-active-link-hover-bg:             $body-bg !default;
      -$nav-tabs-active-link-hover-color:          $gray !default;
      -$nav-tabs-active-link-hover-border-color:   $gray-light !default;
      -
      -$nav-tabs-justified-link-border-color:            $gray-light !default;
      -$nav-tabs-justified-active-link-border-color:     $body-bg !default;
      -
      -//== Pills
      -$nav-pills-border-radius:                   $border-radius-base !default;
      -$nav-pills-active-link-hover-bg:            $component-active-bg !default;
      -$nav-pills-active-link-hover-color:         $component-active-color !default;
      -
      -
      -//== Pagination
      -//
      -//##
      -
      -$pagination-color:                     $gray !default;
      -$pagination-bg:                        $gray-lighter !default;
      -$pagination-border:                    $gray-light !default;
      -
      -$pagination-hover-color:               $gray-dark !default;
      -$pagination-hover-bg:                  $gray-light !default;
      -$pagination-hover-border:              $pagination-border !default;
      -
      -$pagination-active-color:              $gray-dark !default;
      -$pagination-active-bg:                 $gray-light !default;
      -$pagination-active-border:             $gray-light !default;
      -
      -$pagination-disabled-color:            $gray-light !default;
      -$pagination-disabled-bg:               $gray-lighter !default;
      -$pagination-disabled-border:           $gray-light !default;
      -
      -
      -//== Pager
      -//
      -//##
      -
      -$pager-bg:                             $pagination-bg !default;
      -$pager-border:                         $pagination-border !default;
      -$pager-border-radius:                  15px !default;
      -
      -$pager-hover-bg:                       $pagination-hover-bg !default;
      -
      -$pager-active-bg:                      $pagination-active-bg !default;
      -$pager-active-color:                   $pagination-active-color !default;
      -
      -$pager-disabled-color:                 $pagination-disabled-color !default;
      -
      -
      -//== Jumbotron
      -//
      -//##
      -
      -$jumbotron-padding:              30px !default;
      -$jumbotron-color:                inherit !default;
      -$jumbotron-bg:                   $gray-lighter !default;
      -$jumbotron-heading-color:        inherit !default;
      -$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
      -$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
      -
      -
      -//== Form states and alerts
      -//
      -//## Define colors for form feedback states and, by default, alerts.
      -
      -$state-success-text:             $brand-success !default;
      -$state-success-bg:               #dff0d8 !default;
      -$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
      -
      -$state-info-text:                $brand-info !default;
      -$state-info-bg:                  #d9edf7 !default;
      -$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
      -
      -$state-warning-text:             $brand-warning !default;
      -$state-warning-bg:               #fcf8e3 !default;
      -$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%) !default;
      -
      -$state-danger-text:              $brand-danger !default;
      -$state-danger-bg:                #f2dede !default;
      -$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%) !default;
      -
      -
      -//== Tooltips
      -//
      -//##
      -
      -//** Tooltip max width
      -$tooltip-max-width:           200px !default;
      -//** Tooltip text color
      -$tooltip-color:               #fff !default;
      -//** Tooltip background color
      -$tooltip-bg:                  $navbar-default-bg !default;
      -$tooltip-opacity:             1 !default;
      -
      -//** Tooltip arrow width
      -$tooltip-arrow-width:         5px !default;
      -//** Tooltip arrow color
      -$tooltip-arrow-color:         $tooltip-bg !default;
      -
      -
      -//== Popovers
      -//
      -//##
      -
      -//** Popover body background color
      -$popover-bg:                          #fff !default;
      -//** Popover maximum width
      -$popover-max-width:                   276px !default;
      -//** Popover border color
      -$popover-border-color:                $gray-light !default;
      -//** Popover fallback border color
      -$popover-fallback-border-color:       $gray-light !default;
      -
      -//** Popover title background color
      -$popover-title-bg:                    $gray-lighter !default;
      -
      -//** Popover arrow width
      -$popover-arrow-width:                 10px !default;
      -//** Popover arrow color
      -$popover-arrow-color:                 $popover-bg !default;
      -
      -//** Popover outer arrow width
      -$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
      -//** Popover outer arrow color
      -$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
      -//** Popover outer arrow fallback color
      -$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
      -
      -
      -//== Labels
      -//
      -//##
      -
      -//** Default label background color
      -$label-default-bg:            $navbar-default-bg !default;
      -//** Primary label background color
      -$label-primary-bg:            $brand-primary !default;
      -//** Success label background color
      -$label-success-bg:            $brand-success !default;
      -//** Info label background color
      -$label-info-bg:               $brand-info !default;
      -//** Warning label background color
      -$label-warning-bg:            $brand-warning !default;
      -//** Danger label background color
      -$label-danger-bg:             $brand-danger !default;
      -
      -//** Default label text color
      -$label-color:                 #fff !default;
      -//** Default text color of a linked label
      -$label-link-hover-color:      #fff !default;
      -
      -
      -//== Modals
      -//
      -//##
      -
      -//** Padding applied to the modal body
      -$modal-inner-padding:         15px !default;
      -
      -//** Padding applied to the modal title
      -$modal-title-padding:         15px !default;
      -//** Modal title line-height
      -$modal-title-line-height:     $line-height-base !default;
      -
      -//** Background color of modal content area
      -$modal-content-bg:                             #fff !default;
      -//** Modal content border color
      -$modal-content-border-color:                   $gray-lighter !default;
      -//** Modal content border color **for IE8**
      -$modal-content-fallback-border-color:          $gray-lighter !default;
      -
      -//** Modal backdrop background color
      -$modal-backdrop-bg:           #000 !default;
      -//** Modal backdrop opacity
      -$modal-backdrop-opacity:      .5 !default;
      -//** Modal header border color
      -$modal-header-border-color:   $gray-lighter !default;
      -//** Modal footer border color
      -$modal-footer-border-color:   $modal-header-border-color !default;
      -
      -$modal-lg:                    900px !default;
      -$modal-md:                    600px !default;
      -$modal-sm:                    300px !default;
      -
      -
      -//== Alerts
      -//
      -//## Define alert colors, border radius, and padding.
      -
      -$alert-padding:               15px !default;
      -$alert-border-radius:         $border-radius-base !default;
      -$alert-link-font-weight:      bold !default;
      -
      -$alert-success-bg:            $brand-success !default;
      -$alert-success-text:          #fff !default;
      -$alert-success-border:        transparent !default;
      -
      -$alert-info-bg:               $brand-info !default;
      -$alert-info-text:             #fff !default;
      -$alert-info-border:           transparent !default;
      -
      -$alert-warning-bg:            $brand-warning !default;
      -$alert-warning-text:          #fff !default;
      -$alert-warning-border:        transparent !default;
      -
      -$alert-danger-bg:             $brand-danger !default;
      -$alert-danger-text:           #fff !default;
      -$alert-danger-border:         transparent !default;
      -
      -
      -//== Progress bars
      -//
      -//##
      -
      -//** Background color of the whole progress component
      -$progress-bg:                 #f5f5f5 !default;
      -//** Progress bar text color
      -$progress-bar-color:          #fff !default;
      -//** Variable for setting rounded corners on progress bar.
      -$progress-border-radius:      $border-radius-base !default;
      -
      -//** Default progress bar color
      -$progress-bar-bg:             $brand-primary !default;
      -//** Success progress bar color
      -$progress-bar-success-bg:     $brand-success !default;
      -//** Warning progress bar color
      -$progress-bar-warning-bg:     $brand-warning !default;
      -//** Danger progress bar color
      -$progress-bar-danger-bg:      $brand-danger !default;
      -//** Info progress bar color
      -$progress-bar-info-bg:        $brand-info !default;
      -
      -
      -//== List group
      -//
      -//##
      -
      -//** Background color on `.list-group-item`
      -$list-group-bg:                 #fff !default;
      -//** `.list-group-item` border color
      -$list-group-border:             $gray-light !default;
      -//** List group border radius
      -$list-group-border-radius:      $border-radius-base !default;
      -
      -//** Background color of single list items on hover
      -$list-group-hover-bg:           $gray-lighter !default;
      -//** Text color of active list items
      -$list-group-active-color:       $text-color !default;
      -//** Background color of active list items
      -$list-group-active-bg:          $component-active-bg !default;
      -//** Border color of active list elements
      -$list-group-active-border:      $list-group-border !default;
      -//** Text color for content within active list items
      -$list-group-active-text-color:  $text-color !default;
      -
      -//** Text color of disabled list items
      -$list-group-disabled-color:      $gray-light !default;
      -//** Background color of disabled list items
      -$list-group-disabled-bg:         $gray-lighter !default;
      -//** Text color for content within disabled list items
      -$list-group-disabled-text-color: $list-group-disabled-color !default;
      -
      -$list-group-link-color:         $text-color !default;
      -$list-group-link-hover-color:   $list-group-link-color !default;
      -$list-group-link-heading-color: $headings-color !default;
      -
      -
      -//== Panels
      -//
      -//##
      -
      -$panel-bg:                    #fff !default;
      -$panel-body-padding:          15px !default;
      -$panel-heading-padding:       10px 15px !default;
      -$panel-footer-padding:        $panel-heading-padding !default;
      -$panel-border-radius:         $border-radius-base !default;
      -
      -//** Border color for elements within panels
      -$panel-inner-border:          $gray-light !default;
      -$panel-footer-bg:             $gray-lighter !default;
      -
      -$panel-default-text:          $text-color !default;
      -$panel-default-border:        $gray-light !default;
      -$panel-default-heading-bg:    $gray-lighter !default;
      -
      -$panel-primary-text:          #fff !default;
      -$panel-primary-border:        $brand-primary !default;
      -$panel-primary-heading-bg:    $brand-primary !default;
      -
      -$panel-success-text:          $state-success-text !default;
      -$panel-success-border:        $state-success-border !default;
      -$panel-success-heading-bg:    $brand-success !default;
      -
      -$panel-info-text:             $state-info-text !default;
      -$panel-info-border:           $state-info-border !default;
      -$panel-info-heading-bg:       $brand-info !default;
      -
      -$panel-warning-text:          $state-warning-text !default;
      -$panel-warning-border:        $state-warning-border !default;
      -$panel-warning-heading-bg:    $brand-warning !default;
      -
      -$panel-danger-text:           $state-danger-text !default;
      -$panel-danger-border:         $state-danger-border !default;
      -$panel-danger-heading-bg:     $brand-danger !default;
      -
      -
      -//== Thumbnails
      -//
      -//##
      -
      -//** Padding around the thumbnail image
      -$thumbnail-padding:           4px !default;
      -//** Thumbnail background color
      -$thumbnail-bg:                $gray-lighter !default;
      -//** Thumbnail border color
      -$thumbnail-border:            $gray-light !default;
      -//** Thumbnail border radius
      -$thumbnail-border-radius:     $border-radius-base !default;
      -
      -//** Custom text color for thumbnail captions
      -$thumbnail-caption-color:     $text-color !default;
      -//** Padding around the thumbnail caption
      -$thumbnail-caption-padding:   9px !default;
      -
      -
      -//== Wells
      -//
      -//##
      -
      -$well-bg:                     $gray-lighter !default;
      -$well-border:                 transparent !default;
      -
      -
      -//== Badges
      -//
      -//##
      -
      -$badge-color:                 #fff !default;
      -//** Linked badge text color on hover
      -$badge-link-hover-color:      #fff !default;
      -$badge-bg:                    $brand-success !default;
      -
      -//** Badge text color in active nav link
      -$badge-active-color:          #fff !default;
      -//** Badge background color in active nav link
      -$badge-active-bg:             $brand-success !default;
      -
      -$badge-font-weight:           normal !default;
      -$badge-line-height:           1 !default;
      -$badge-border-radius:         10px !default;
      -
      -
      -//== Breadcrumbs
      -//
      -//##
      -
      -$breadcrumb-padding-vertical:   8px !default;
      -$breadcrumb-padding-horizontal: 15px !default;
      -//** Breadcrumb background color
      -$breadcrumb-bg:                 $gray-lighter !default;
      -//** Breadcrumb text color
      -$breadcrumb-color:              $gray-light !default;
      -//** Text color of current page in the breadcrumb
      -$breadcrumb-active-color:       $gray !default;
      -//** Textual separator for between breadcrumb elements
      -$breadcrumb-separator:          "/" !default;
      -
      -
      -//== Carousel
      -//
      -//##
      -
      -$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
      -
      -$carousel-control-color:                      #fff !default;
      -$carousel-control-width:                      15% !default;
      -$carousel-control-opacity:                    .5 !default;
      -$carousel-control-font-size:                  20px !default;
      -
      -$carousel-indicator-active-bg:                #fff !default;
      -$carousel-indicator-border-color:             #fff !default;
      -
      -$carousel-caption-color:                      #fff !default;
      -
      -
      -//== Close
      -//
      -//##
      -
      -$close-font-weight:           bold !default;
      -$close-color:                 #000 !default;
      -$close-text-shadow:           0 0 0 transparent !default;
      -
      -
      -//== Code
      -//
      -//##
      -
      -$code-color:                  #c7254e !default;
      -$code-bg:                     #f9f2f4 !default;
      -
      -$kbd-color:                   #fff !default;
      -$kbd-bg:                      #333 !default;
      -
      -$pre-bg:                      #f5f5f5 !default;
      -$pre-color:                   $gray-dark !default;
      -$pre-border-color:            #ccc !default;
      -$pre-scrollable-max-height:   340px !default;
      -
      -
      -//== Type
      -//
      -//##
      -
      -//** Horizontal offset for forms and lists.
      -$component-offset-horizontal: 180px !default;
      -//** Text muted color
      -$text-muted:                  $gray !default;
      -//** Abbreviations and acronyms border color
      -$abbr-border-color:           $gray !default;
      -//** Headings small color
      -$headings-small-color:        $gray !default;
      -//** Blockquote small color
      -$blockquote-small-color:      $text-color !default;
      -//** Blockquote font size
      -$blockquote-font-size:        ($font-size-base * 1.25) !default;
      -//** Blockquote border color
      -$blockquote-border-color:     $gray-light !default;
      -//** Page header border color
      -$page-header-border-color:    $gray-lighter !default;
      -//** Width of horizontal description list titles
      -$dl-horizontal-offset:        $component-offset-horizontal !default;
      -//** Point at which .dl-horizontal becomes horizontal
      -$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
      -//** Horizontal line color.
      -$hr-border:                   $gray-lighter !default;
      diff --git a/vendor/assets/stylesheets/spacelab/_bootswatch.scss b/vendor/assets/stylesheets/spacelab/_bootswatch.scss
      deleted file mode 100644
      index 92a4676..0000000
      --- a/vendor/assets/stylesheets/spacelab/_bootswatch.scss
      +++ /dev/null
      @@ -1,142 +0,0 @@
      -// Spacelab 3.3.5
      -// Bootswatch
      -// -----------------------------------------------------
      -
      -//$web-font-path: "https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700" !default;
      -//@import url($web-font-path);
      -
      -@mixin btn-shadow($color){
      -  @include gradient-vertical-three-colors(lighten($color, 15%), $color, 50%, darken($color, 4%));
      -  filter: none;
      -  border: 1px solid darken($color, 10%);
      -}
      -
      -// Navbar =====================================================================
      -
      -.navbar {
      -
      -  @include btn-shadow($navbar-default-bg);
      -  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.3);
      -
      -  &-inverse {
      -    @include btn-shadow($navbar-inverse-bg);
      -    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
      -
      -    .badge {
      -      background-color: #fff;
      -      color: $navbar-inverse-bg;
      -    }
      -  }
      -
      -  .badge {
      -    text-shadow: none;
      -  }
      -
      -  &-nav > li > a,
      -  &-nav > li > a:hover {
      -    padding-top: ($navbar-padding-vertical + 2px);
      -    padding-bottom: ($navbar-padding-vertical - 2px);
      -    @include transition(color ease-in-out .2s);
      -  }
      -  
      -  &-brand,
      -  &-brand:hover {
      -    @include transition(color ease-in-out .2s);
      -  }
      -
      -  .caret,
      -  .caret:hover {
      -    @include transition(border-color ease-in-out .2s);
      -  }
      -
      -  .dropdown-menu {
      -    text-shadow: none;
      -  }
      -}
      -
      -// Buttons ====================================================================
      -
      -.btn {
      -  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
      -
      -  &-default {
      -    @include btn-shadow($btn-default-bg);
      -
      -    &:hover {
      -      @include btn-shadow(darken($btn-default-bg, 4%));
      -    }
      -  }
      -
      -  &-primary {
      -    @include btn-shadow($btn-primary-bg);
      -
      -    &:hover {
      -      @include btn-shadow(darken($btn-primary-bg, 4%));
      -    }
      -  }
      -
      -  &-success {
      -    @include btn-shadow($btn-success-bg);
      -
      -    &:hover {
      -      @include btn-shadow(darken($btn-success-bg, 4%));
      -    }
      -  }
      -
      -  &-info {
      -    @include btn-shadow($btn-info-bg);
      -
      -    &:hover {
      -      @include btn-shadow(darken($btn-info-bg, 4%));
      -    }
      -  }
      -
      -  &-warning {
      -    @include btn-shadow($btn-warning-bg);
      -
      -    &:hover {
      -      @include btn-shadow(darken($btn-warning-bg, 4%));
      -    }
      -  }
      -
      -  &-danger {
      -    @include btn-shadow($btn-danger-bg);
      -
      -    &:hover {
      -      @include btn-shadow(darken($btn-danger-bg, 4%));
      -    }
      -  }
      -
      -  &-link {
      -    text-shadow: none;
      -  }
      -
      -  &:active,
      -  &.active {
      -    background-image: none;
      -    @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
      -  }
      -}
      -
      -// Typography =================================================================
      -
      -// Tables =====================================================================
      -
      -// Forms ======================================================================
      -
      -// Navs =======================================================================
      -
      -// Indicators =================================================================
      -
      -// Progress bars ==============================================================
      -
      -// Containers =================================================================
      -
      -.panel {
      -
      -  &-primary {
      -    .panel-title {
      -      color: #fff;
      -    }
      -  }
      -}
      \ No newline at end of file
      diff --git a/vendor/assets/stylesheets/spacelab/_variables.scss b/vendor/assets/stylesheets/spacelab/_variables.scss
      deleted file mode 100644
      index 7b85006..0000000
      --- a/vendor/assets/stylesheets/spacelab/_variables.scss
      +++ /dev/null
      @@ -1,870 +0,0 @@
      -$bootstrap-sass-asset-helper: false !default;
      -// Spacelab 3.3.6
      -// Variables
      -// --------------------------------------------------
      -
      -
      -//== Colors
      -//
      -//## Gray and brand colors for use across Bootstrap.
      -
      -$gray-base:              #000 !default;
      -$gray-darker:            #2d2d2d !default; // #222
      -$gray-dark:              lighten($gray-base, 20%) !default;   // #333
      -$gray:                   #666 !default; // #555
      -$gray-light:             lighten($gray-base, 60%) !default;   // #999
      -$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
      -
      -$brand-primary:         #446E9B !default;
      -$brand-success:         #3CB521 !default;
      -$brand-info:            #3399F3 !default;
      -$brand-warning:         #D47500 !default;
      -$brand-danger:          #CD0200 !default;
      -
      -
      -//== Scaffolding
      -//
      -//## Settings for some of the most global styles.
      -
      -//** Background color for ``.
      -$body-bg:               #fff !default;
      -//** Global text color on ``.
      -$text-color:            $gray !default;
      -
      -//** Global textual link color.
      -$link-color:            $brand-info !default;
      -//** Link hover color set via `darken()` function.
      -$link-hover-color:      $link-color !default;
      -//** Link hover decoration.
      -$link-hover-decoration: underline !default;
      -
      -
      -//== Typography
      -//
      -//## Font, line-height, and color for body text, headings, and more.
      -
      -$font-family-sans-serif:  "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
      -$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
      -//** Default monospace fonts for ``, ``, and `
      `.
      -$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
      -$font-family-base:        $font-family-sans-serif !default;
      -
      -$font-size-base:          14px !default;
      -$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
      -$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
      -$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
      -$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-h5:            $font-size-base !default;
      -$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -//** Unit-less `line-height` for use in components like buttons.
      -$line-height-base:        1.428571429 !default; // 20/14
      -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
      -$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
      -
      -//** By default, this inherits from the ``.
      -$headings-font-family:    $font-family-base !default;
      -$headings-font-weight:    500 !default;
      -$headings-line-height:    1.1 !default;
      -$headings-color:          $gray-darker !default;
      -
      -
      -//== Iconography
      -//
      -//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
      -
      -//** Load fonts from this directory.
      -$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
      -//** File name for all font files.
      -$icon-font-name:          "glyphicons-halflings-regular" !default;
      -//** Element ID within SVG icon file.
      -$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
      -
      -
      -//== Components
      -//
      -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
      -
      -$padding-base-vertical:     8px !default;
      -$padding-base-horizontal:   12px !default;
      -
      -$padding-large-vertical:    14px !default;
      -$padding-large-horizontal:  16px !default;
      -
      -$padding-small-vertical:    5px !default;
      -$padding-small-horizontal:  10px !default;
      -
      -$padding-xs-vertical:       1px !default;
      -$padding-xs-horizontal:     5px !default;
      -
      -$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
      -$line-height-small:         1.5 !default;
      -
      -$border-radius-base:        4px !default;
      -$border-radius-large:       6px !default;
      -$border-radius-small:       3px !default;
      -
      -//** Global color for active items (e.g., navs or dropdowns).
      -$component-active-color:    #fff !default;
      -//** Global background color for active items (e.g., navs or dropdowns).
      -$component-active-bg:       $brand-primary !default;
      -
      -//** Width of the `border` for generating carets that indicator dropdowns.
      -$caret-width-base:          4px !default;
      -//** Carets increase slightly in size for larger components.
      -$caret-width-large:         5px !default;
      -
      -
      -//== Tables
      -//
      -//## Customizes the `.table` component with basic values, each used across all table variations.
      -
      -//** Padding for ``s and ``s.
      -$table-cell-padding:            8px !default;
      -//** Padding for cells in `.table-condensed`.
      -$table-condensed-cell-padding:  5px !default;
      -
      -//** Default background color used for all tables.
      -$table-bg:                      transparent !default;
      -//** Background color used for `.table-striped`.
      -$table-bg-accent:               #f9f9f9 !default;
      -//** Background color used for `.table-hover`.
      -$table-bg-hover:                #f5f5f5 !default;
      -$table-bg-active:               $table-bg-hover !default;
      -
      -//** Border color for table and cell borders.
      -$table-border-color:            #ddd !default;
      -
      -
      -//== Buttons
      -//
      -//## For each of Bootstrap's buttons, define text, background and border color.
      -
      -$btn-font-weight:                normal !default;
      -
      -$btn-default-color:              #fff !default;
      -$btn-default-bg:                 #474949 !default;
      -$btn-default-border:             $btn-default-bg !default;
      -
      -$btn-primary-color:              $btn-default-color !default;
      -$btn-primary-bg:                 $brand-primary !default;
      -$btn-primary-border:             $btn-primary-bg !default;
      -
      -$btn-success-color:              $btn-default-color !default;
      -$btn-success-bg:                 $brand-success !default;
      -$btn-success-border:             $btn-success-bg !default;
      -
      -$btn-info-color:                 $btn-default-color !default;
      -$btn-info-bg:                    $brand-info !default;
      -$btn-info-border:                $btn-info-bg !default;
      -
      -$btn-warning-color:              $btn-default-color !default;
      -$btn-warning-bg:                 $brand-warning !default;
      -$btn-warning-border:             $btn-warning-bg !default;
      -
      -$btn-danger-color:               $btn-default-color !default;
      -$btn-danger-bg:                  $brand-danger !default;
      -$btn-danger-border:              $btn-danger-bg !default;
      -
      -$btn-link-disabled-color:        $gray-light !default;
      -
      -// Allows for customizing button radius independently from global border radius
      -$btn-border-radius-base:         $border-radius-base !default;
      -$btn-border-radius-large:        $border-radius-large !default;
      -$btn-border-radius-small:        $border-radius-small !default;
      -
      -
      -//== Forms
      -//
      -//##
      -
      -//** `` background color
      -$input-bg:                       #fff !default;
      -//** `` background color
      -$input-bg-disabled:              $gray-lighter !default;
      -
      -//** Text color for ``s
      -$input-color:                    $text-color !default;
      -//** `` border color
      -$input-border:                   #ccc !default;
      -
      -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
      -//** Default `.form-control` border radius
      -// This has no effect on ``s in CSS.
      -$input-border-radius:            $border-radius-base !default;
      -//** Large `.form-control` border radius
      -$input-border-radius-large:      $border-radius-large !default;
      -//** Small `.form-control` border radius
      -$input-border-radius-small:      $border-radius-small !default;
      -
      -//** Border color for inputs on focus
      -$input-border-focus:             #66afe9 !default;
      -
      -//** Placeholder text color
      -$input-color-placeholder:        $gray-light !default;
      -
      -//** Default `.form-control` height
      -$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
      -//** Large `.form-control` height
      -$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
      -//** Small `.form-control` height
      -$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
      -
      -//** `.form-group` margin
      -$form-group-margin-bottom:       15px !default;
      -
      -$legend-color:                   $text-color !default;
      -$legend-border-color:            #e5e5e5 !default;
      -
      -//** Background color for textual input addons
      -$input-group-addon-bg:           $gray-lighter !default;
      -//** Border color for textual input addons
      -$input-group-addon-border-color: $input-border !default;
      -
      -//** Disabled cursor for form controls and buttons.
      -$cursor-disabled:                not-allowed !default;
      -
      -
      -//== Dropdowns
      -//
      -//## Dropdown menu container and contents.
      -
      -//** Background for the dropdown menu.
      -$dropdown-bg:                    #fff !default;
      -//** Dropdown menu `border-color`.
      -$dropdown-border:                rgba(0,0,0,.15) !default;
      -//** Dropdown menu `border-color` **for IE8**.
      -$dropdown-fallback-border:       #ccc !default;
      -//** Divider color for between dropdown items.
      -$dropdown-divider-bg:            #e5e5e5 !default;
      -
      -//** Dropdown link text color.
      -$dropdown-link-color:            $gray-dark !default;
      -//** Hover color for dropdown links.
      -$dropdown-link-hover-color:      #fff !default;
      -//** Hover background for dropdown links.
      -$dropdown-link-hover-bg:         $component-active-bg !default;
      -
      -//** Active dropdown menu item text color.
      -$dropdown-link-active-color:     #fff !default;
      -//** Active dropdown menu item background color.
      -$dropdown-link-active-bg:        $component-active-bg !default;
      -
      -//** Disabled dropdown menu item background color.
      -$dropdown-link-disabled-color:   $gray-light !default;
      -
      -//** Text color for headers within dropdown menus.
      -$dropdown-header-color:          $gray-light !default;
      -
      -//** Deprecated `$dropdown-caret-color` as of v3.1.0
      -$dropdown-caret-color:           #000 !default;
      -
      -
      -//-- Z-index master list
      -//
      -// Warning: Avoid customizing these values. They're used for a bird's eye view
      -// of components dependent on the z-axis and are designed to all work together.
      -//
      -// Note: These variables are not generated into the Customizer.
      -
      -$zindex-navbar:            1000 !default;
      -$zindex-dropdown:          1000 !default;
      -$zindex-popover:           1060 !default;
      -$zindex-tooltip:           1070 !default;
      -$zindex-navbar-fixed:      1030 !default;
      -$zindex-modal-background:  1040 !default;
      -$zindex-modal:             1050 !default;
      -
      -
      -//== Media queries breakpoints
      -//
      -//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
      -
      -// Extra small screen / phone
      -//** Deprecated `$screen-xs` as of v3.0.1
      -$screen-xs:                  480px !default;
      -//** Deprecated `$screen-xs-min` as of v3.2.0
      -$screen-xs-min:              $screen-xs !default;
      -//** Deprecated `$screen-phone` as of v3.0.1
      -$screen-phone:               $screen-xs-min !default;
      -
      -// Small screen / tablet
      -//** Deprecated `$screen-sm` as of v3.0.1
      -$screen-sm:                  768px !default;
      -$screen-sm-min:              $screen-sm !default;
      -//** Deprecated `$screen-tablet` as of v3.0.1
      -$screen-tablet:              $screen-sm-min !default;
      -
      -// Medium screen / desktop
      -//** Deprecated `$screen-md` as of v3.0.1
      -$screen-md:                  992px !default;
      -$screen-md-min:              $screen-md !default;
      -//** Deprecated `$screen-desktop` as of v3.0.1
      -$screen-desktop:             $screen-md-min !default;
      -
      -// Large screen / wide desktop
      -//** Deprecated `$screen-lg` as of v3.0.1
      -$screen-lg:                  1200px !default;
      -$screen-lg-min:              $screen-lg !default;
      -//** Deprecated `$screen-lg-desktop` as of v3.0.1
      -$screen-lg-desktop:          $screen-lg-min !default;
      -
      -// So media queries don't overlap when required, provide a maximum
      -$screen-xs-max:              ($screen-sm-min - 1) !default;
      -$screen-sm-max:              ($screen-md-min - 1) !default;
      -$screen-md-max:              ($screen-lg-min - 1) !default;
      -
      -
      -//== Grid system
      -//
      -//## Define your custom responsive grid.
      -
      -//** Number of columns in the grid.
      -$grid-columns:              12 !default;
      -//** Padding between columns. Gets divided in half for the left and right.
      -$grid-gutter-width:         30px !default;
      -// Navbar collapse
      -//** Point at which the navbar becomes uncollapsed.
      -$grid-float-breakpoint:     $screen-sm-min !default;
      -//** Point at which the navbar begins collapsing.
      -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
      -
      -
      -//== Container sizes
      -//
      -//## Define the maximum width of `.container` for different screen sizes.
      -
      -// Small screen / tablet
      -$container-tablet:             (720px + $grid-gutter-width) !default;
      -//** For `$screen-sm-min` and up.
      -$container-sm:                 $container-tablet !default;
      -
      -// Medium screen / desktop
      -$container-desktop:            (940px + $grid-gutter-width) !default;
      -//** For `$screen-md-min` and up.
      -$container-md:                 $container-desktop !default;
      -
      -// Large screen / wide desktop
      -$container-large-desktop:      (1140px + $grid-gutter-width) !default;
      -//** For `$screen-lg-min` and up.
      -$container-lg:                 $container-large-desktop !default;
      -
      -
      -//== Navbar
      -//
      -//##
      -
      -// Basics of a navbar
      -$navbar-height:                    50px !default;
      -$navbar-margin-bottom:             $line-height-computed !default;
      -$navbar-border-radius:             $border-radius-base !default;
      -$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
      -$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
      -$navbar-collapse-max-height:       340px !default;
      -
      -$navbar-default-color:             #777 !default;
      -$navbar-default-bg:                #eee !default;
      -$navbar-default-border:            darken($navbar-default-bg, 6.5%) !default;
      -
      -// Navbar links
      -$navbar-default-link-color:                #777 !default;
      -$navbar-default-link-hover-color:          $brand-info !default;
      -$navbar-default-link-hover-bg:             transparent !default;
      -$navbar-default-link-active-color:         $navbar-default-link-hover-color !default;
      -$navbar-default-link-active-bg:            transparent !default;
      -$navbar-default-link-disabled-color:       #444 !default;
      -$navbar-default-link-disabled-bg:          transparent !default;
      -
      -// Navbar brand label
      -$navbar-default-brand-color:               $navbar-default-link-color !default;
      -$navbar-default-brand-hover-color:         $navbar-default-link-hover-color !default;
      -$navbar-default-brand-hover-bg:            transparent !default;
      -
      -// Navbar toggle
      -$navbar-default-toggle-hover-bg:           darken($navbar-default-bg, 6.5%) !default;
      -$navbar-default-toggle-icon-bar-bg:        #ccc !default;
      -$navbar-default-toggle-border-color:       darken($navbar-default-bg, 6.5%) !default;
      -
      -
      -//=== Inverted navbar
      -// Reset inverted navbar basics
      -$navbar-inverse-color:                      #ddd !default;
      -$navbar-inverse-bg:                         $brand-primary !default;
      -$navbar-inverse-border:                     darken($navbar-inverse-bg, 10%) !default;
      -
      -// Inverted navbar links
      -$navbar-inverse-link-color:                 #ddd !default;
      -$navbar-inverse-link-hover-color:           #fff !default;
      -$navbar-inverse-link-hover-bg:              transparent !default;
      -$navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color !default;
      -$navbar-inverse-link-active-bg:             transparent !default;
      -$navbar-inverse-link-disabled-color:        #ccc !default;
      -$navbar-inverse-link-disabled-bg:           transparent !default;
      -
      -// Inverted navbar brand label
      -$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;
      -$navbar-inverse-brand-hover-color:          #fff !default;
      -$navbar-inverse-brand-hover-bg:             transparent !default;
      -
      -// Inverted navbar toggle
      -$navbar-inverse-toggle-hover-bg:            darken($navbar-inverse-bg, 10%) !default;
      -$navbar-inverse-toggle-icon-bar-bg:         #fff !default;
      -$navbar-inverse-toggle-border-color:        darken($navbar-inverse-bg, 10%) !default;
      -
      -
      -//== Navs
      -//
      -//##
      -
      -//=== Shared nav styles
      -$nav-link-padding:                          10px 15px !default;
      -$nav-link-hover-bg:                         $gray-lighter !default;
      -
      -$nav-disabled-link-color:                   $gray-light !default;
      -$nav-disabled-link-hover-color:             $gray-light !default;
      -
      -//== Tabs
      -$nav-tabs-border-color:                     #ddd !default;
      -
      -$nav-tabs-link-hover-border-color:          $gray-lighter !default;
      -
      -$nav-tabs-active-link-hover-bg:             $body-bg !default;
      -$nav-tabs-active-link-hover-color:          $gray !default;
      -$nav-tabs-active-link-hover-border-color:   #ddd !default;
      -
      -$nav-tabs-justified-link-border-color:            #ddd !default;
      -$nav-tabs-justified-active-link-border-color:     $body-bg !default;
      -
      -//== Pills
      -$nav-pills-border-radius:                   $border-radius-base !default;
      -$nav-pills-active-link-hover-bg:            $component-active-bg !default;
      -$nav-pills-active-link-hover-color:         $component-active-color !default;
      -
      -
      -//== Pagination
      -//
      -//##
      -
      -$pagination-color:                     $link-color !default;
      -$pagination-bg:                        #fff !default;
      -$pagination-border:                    #ddd !default;
      -
      -$pagination-hover-color:               $link-hover-color !default;
      -$pagination-hover-bg:                  $gray-lighter !default;
      -$pagination-hover-border:              #ddd !default;
      -
      -$pagination-active-color:              $gray-light !default;
      -$pagination-active-bg:                 #f5f5f5 !default;
      -$pagination-active-border:             #ddd !default;
      -
      -$pagination-disabled-color:            $gray-light !default;
      -$pagination-disabled-bg:               #fff !default;
      -$pagination-disabled-border:           #ddd !default;
      -
      -
      -//== Pager
      -//
      -//##
      -
      -$pager-bg:                             $pagination-bg !default;
      -$pager-border:                         $pagination-border !default;
      -$pager-border-radius:                  15px !default;
      -
      -$pager-hover-bg:                       $pagination-hover-bg !default;
      -
      -$pager-active-bg:                      $pagination-active-bg !default;
      -$pager-active-color:                   $pagination-active-color !default;
      -
      -$pager-disabled-color:                 $gray-light !default;
      -
      -
      -//== Jumbotron
      -//
      -//##
      -
      -$jumbotron-padding:              30px !default;
      -$jumbotron-color:                inherit !default;
      -$jumbotron-bg:                   $gray-lighter !default;
      -$jumbotron-heading-color:        inherit !default;
      -$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
      -$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
      -
      -
      -//== Form states and alerts
      -//
      -//## Define colors for form feedback states and, by default, alerts.
      -
      -$state-success-text:             #468847 !default;
      -$state-success-bg:               #dff0d8 !default;
      -$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
      -
      -$state-info-text:                #3a87ad !default;
      -$state-info-bg:                  #d9edf7 !default;
      -$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
      -
      -$state-warning-text:             #c09853 !default;
      -$state-warning-bg:               #fcf8e3 !default;
      -$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 3%) !default;
      -
      -$state-danger-text:              #b94a48 !default;
      -$state-danger-bg:                #f2dede !default;
      -$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 3%) !default;
      -
      -
      -//== Tooltips
      -//
      -//##
      -
      -//** Tooltip max width
      -$tooltip-max-width:           200px !default;
      -//** Tooltip text color
      -$tooltip-color:               #fff !default;
      -//** Tooltip background color
      -$tooltip-bg:                  #000 !default;
      -$tooltip-opacity:             .9 !default;
      -
      -//** Tooltip arrow width
      -$tooltip-arrow-width:         5px !default;
      -//** Tooltip arrow color
      -$tooltip-arrow-color:         $tooltip-bg !default;
      -
      -
      -//== Popovers
      -//
      -//##
      -
      -//** Popover body background color
      -$popover-bg:                          #fff !default;
      -//** Popover maximum width
      -$popover-max-width:                   276px !default;
      -//** Popover border color
      -$popover-border-color:                rgba(0,0,0,.2) !default;
      -//** Popover fallback border color
      -$popover-fallback-border-color:       #ccc !default;
      -
      -//** Popover title background color
      -$popover-title-bg:                    darken($popover-bg, 3%) !default;
      -
      -//** Popover arrow width
      -$popover-arrow-width:                 10px !default;
      -//** Popover arrow color
      -$popover-arrow-color:                 $popover-bg !default;
      -
      -//** Popover outer arrow width
      -$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
      -//** Popover outer arrow color
      -$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
      -//** Popover outer arrow fallback color
      -$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
      -
      -
      -//== Labels
      -//
      -//##
      -
      -//** Default label background color
      -$label-default-bg:            $btn-default-bg !default;
      -//** Primary label background color
      -$label-primary-bg:            $brand-primary !default;
      -//** Success label background color
      -$label-success-bg:            $brand-success !default;
      -//** Info label background color
      -$label-info-bg:               $brand-info !default;
      -//** Warning label background color
      -$label-warning-bg:            $brand-warning !default;
      -//** Danger label background color
      -$label-danger-bg:             $brand-danger !default;
      -
      -//** Default label text color
      -$label-color:                 #fff !default;
      -//** Default text color of a linked label
      -$label-link-hover-color:      #fff !default;
      -
      -
      -//== Modals
      -//
      -//##
      -
      -//** Padding applied to the modal body
      -$modal-inner-padding:         20px !default;
      -
      -//** Padding applied to the modal title
      -$modal-title-padding:         15px !default;
      -//** Modal title line-height
      -$modal-title-line-height:     $line-height-base !default;
      -
      -//** Background color of modal content area
      -$modal-content-bg:                             #fff !default;
      -//** Modal content border color
      -$modal-content-border-color:                   rgba(0,0,0,.2) !default;
      -//** Modal content border color **for IE8**
      -$modal-content-fallback-border-color:          #999 !default;
      -
      -//** Modal backdrop background color
      -$modal-backdrop-bg:           #000 !default;
      -//** Modal backdrop opacity
      -$modal-backdrop-opacity:      .5 !default;
      -//** Modal header border color
      -$modal-header-border-color:   #e5e5e5 !default;
      -//** Modal footer border color
      -$modal-footer-border-color:   $modal-header-border-color !default;
      -
      -$modal-lg:                    900px !default;
      -$modal-md:                    600px !default;
      -$modal-sm:                    300px !default;
      -
      -
      -//== Alerts
      -//
      -//## Define alert colors, border radius, and padding.
      -
      -$alert-padding:               15px !default;
      -$alert-border-radius:         $border-radius-base !default;
      -$alert-link-font-weight:      bold !default;
      -
      -$alert-success-bg:            $state-success-bg !default;
      -$alert-success-text:          $state-success-text !default;
      -$alert-success-border:        $state-success-border !default;
      -
      -$alert-info-bg:               $state-info-bg !default;
      -$alert-info-text:             $state-info-text !default;
      -$alert-info-border:           $state-info-border !default;
      -
      -$alert-warning-bg:            $state-warning-bg !default;
      -$alert-warning-text:          $state-warning-text !default;
      -$alert-warning-border:        $state-warning-border !default;
      -
      -$alert-danger-bg:             $state-danger-bg !default;
      -$alert-danger-text:           $state-danger-text !default;
      -$alert-danger-border:         $state-danger-border !default;
      -
      -
      -//== Progress bars
      -//
      -//##
      -
      -//** Background color of the whole progress component
      -$progress-bg:                 #f5f5f5 !default;
      -//** Progress bar text color
      -$progress-bar-color:          #fff !default;
      -//** Variable for setting rounded corners on progress bar.
      -$progress-border-radius:      $border-radius-base !default;
      -
      -//** Default progress bar color
      -$progress-bar-bg:             $brand-primary !default;
      -//** Success progress bar color
      -$progress-bar-success-bg:     $brand-success !default;
      -//** Warning progress bar color
      -$progress-bar-warning-bg:     $brand-warning !default;
      -//** Danger progress bar color
      -$progress-bar-danger-bg:      $brand-danger !default;
      -//** Info progress bar color
      -$progress-bar-info-bg:        $brand-info !default;
      -
      -
      -//== List group
      -//
      -//##
      -
      -//** Background color on `.list-group-item`
      -$list-group-bg:                 #fff !default;
      -//** `.list-group-item` border color
      -$list-group-border:             #ddd !default;
      -//** List group border radius
      -$list-group-border-radius:      $border-radius-base !default;
      -
      -//** Background color of single list items on hover
      -$list-group-hover-bg:           #f5f5f5 !default;
      -//** Text color of active list items
      -$list-group-active-color:       $component-active-color !default;
      -//** Background color of active list items
      -$list-group-active-bg:          $component-active-bg !default;
      -//** Border color of active list elements
      -$list-group-active-border:      $list-group-active-bg !default;
      -//** Text color for content within active list items
      -$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
      -
      -//** Text color of disabled list items
      -$list-group-disabled-color:      $gray-light !default;
      -//** Background color of disabled list items
      -$list-group-disabled-bg:         $gray-lighter !default;
      -//** Text color for content within disabled list items
      -$list-group-disabled-text-color: $list-group-disabled-color !default;
      -
      -$list-group-link-color:         #555 !default;
      -$list-group-link-hover-color:   $list-group-link-color !default;
      -$list-group-link-heading-color: #333 !default;
      -
      -
      -//== Panels
      -//
      -//##
      -
      -$panel-bg:                    #fff !default;
      -$panel-body-padding:          15px !default;
      -$panel-heading-padding:       10px 15px !default;
      -$panel-footer-padding:        $panel-heading-padding !default;
      -$panel-border-radius:         $border-radius-base !default;
      -
      -//** Border color for elements within panels
      -$panel-inner-border:          #ddd !default;
      -$panel-footer-bg:             #f5f5f5 !default;
      -
      -$panel-default-text:          $gray-dark !default;
      -$panel-default-border:        #ddd !default;
      -$panel-default-heading-bg:    #f5f5f5 !default;
      -
      -$panel-primary-text:          #fff !default;
      -$panel-primary-border:        $brand-primary !default;
      -$panel-primary-heading-bg:    $brand-primary !default;
      -
      -$panel-success-text:          $state-success-text !default;
      -$panel-success-border:        $state-success-border !default;
      -$panel-success-heading-bg:    $state-success-bg !default;
      -
      -$panel-info-text:             $state-info-text !default;
      -$panel-info-border:           $state-info-border !default;
      -$panel-info-heading-bg:       $state-info-bg !default;
      -
      -$panel-warning-text:          $state-warning-text !default;
      -$panel-warning-border:        $state-warning-border !default;
      -$panel-warning-heading-bg:    $state-warning-bg !default;
      -
      -$panel-danger-text:           $state-danger-text !default;
      -$panel-danger-border:         $state-danger-border !default;
      -$panel-danger-heading-bg:     $state-danger-bg !default;
      -
      -
      -//== Thumbnails
      -//
      -//##
      -
      -//** Padding around the thumbnail image
      -$thumbnail-padding:           4px !default;
      -//** Thumbnail background color
      -$thumbnail-bg:                $body-bg !default;
      -//** Thumbnail border color
      -$thumbnail-border:            #ddd !default;
      -//** Thumbnail border radius
      -$thumbnail-border-radius:     $border-radius-base !default;
      -
      -//** Custom text color for thumbnail captions
      -$thumbnail-caption-color:     $text-color !default;
      -//** Padding around the thumbnail caption
      -$thumbnail-caption-padding:   9px !default;
      -
      -
      -//== Wells
      -//
      -//##
      -
      -$well-bg:                     #f5f5f5 !default;
      -$well-border:                 darken($well-bg, 7%) !default;
      -
      -
      -//== Badges
      -//
      -//##
      -
      -$badge-color:                 #fff !default;
      -//** Linked badge text color on hover
      -$badge-link-hover-color:      #fff !default;
      -$badge-bg:                    $link-color !default;
      -
      -//** Badge text color in active nav link
      -$badge-active-color:          $link-color !default;
      -//** Badge background color in active nav link
      -$badge-active-bg:             #fff !default;
      -
      -$badge-font-weight:           bold !default;
      -$badge-line-height:           1 !default;
      -$badge-border-radius:         10px !default;
      -
      -
      -//== Breadcrumbs
      -//
      -//##
      -
      -$breadcrumb-padding-vertical:   8px !default;
      -$breadcrumb-padding-horizontal: 15px !default;
      -//** Breadcrumb background color
      -$breadcrumb-bg:                 #f5f5f5 !default;
      -//** Breadcrumb text color
      -$breadcrumb-color:              #ccc !default;
      -//** Text color of current page in the breadcrumb
      -$breadcrumb-active-color:       $gray-light !default;
      -//** Textual separator for between breadcrumb elements
      -$breadcrumb-separator:          "/" !default;
      -
      -
      -//== Carousel
      -//
      -//##
      -
      -$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
      -
      -$carousel-control-color:                      #fff !default;
      -$carousel-control-width:                      15% !default;
      -$carousel-control-opacity:                    .5 !default;
      -$carousel-control-font-size:                  20px !default;
      -
      -$carousel-indicator-active-bg:                #fff !default;
      -$carousel-indicator-border-color:             #fff !default;
      -
      -$carousel-caption-color:                      #fff !default;
      -
      -
      -//== Close
      -//
      -//##
      -
      -$close-font-weight:           bold !default;
      -$close-color:                 #000 !default;
      -$close-text-shadow:           0 1px 0 #fff !default;
      -
      -
      -//== Code
      -//
      -//##
      -
      -$code-color:                  #c7254e !default;
      -$code-bg:                     #f9f2f4 !default;
      -
      -$kbd-color:                   #fff !default;
      -$kbd-bg:                      #333 !default;
      -
      -$pre-bg:                      #f5f5f5 !default;
      -$pre-color:                   $gray-dark !default;
      -$pre-border-color:            #ccc !default;
      -$pre-scrollable-max-height:   340px !default;
      -
      -
      -//== Type
      -//
      -//##
      -
      -//** Horizontal offset for forms and lists.
      -$component-offset-horizontal: 180px !default;
      -//** Text muted color
      -$text-muted:                  $gray-light !default;
      -//** Abbreviations and acronyms border color
      -$abbr-border-color:           $gray-light !default;
      -//** Headings small color
      -$headings-small-color:        $gray-light !default;
      -//** Blockquote small color
      -$blockquote-small-color:      $gray-light !default;
      -//** Blockquote font size
      -$blockquote-font-size:        ($font-size-base * 1.25) !default;
      -//** Blockquote border color
      -$blockquote-border-color:     $gray-lighter !default;
      -//** Page header border color
      -$page-header-border-color:    $gray-lighter !default;
      -//** Width of horizontal description list titles
      -$dl-horizontal-offset:        $component-offset-horizontal !default;
      -//** Point at which .dl-horizontal becomes horizontal
      -$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
      -//** Horizontal line color.
      -$hr-border:                   $gray-lighter !default;
      diff --git a/vendor/assets/stylesheets/yeti/_bootswatch.scss b/vendor/assets/stylesheets/yeti/_bootswatch.scss
      deleted file mode 100644
      index 76c4a49..0000000
      --- a/vendor/assets/stylesheets/yeti/_bootswatch.scss
      +++ /dev/null
      @@ -1,440 +0,0 @@
      -// Yeti 3.3.5
      -// Bootswatch
      -// -----------------------------------------------------
      -
      -//$web-font-path: "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,300,700" !default;
      -//@import url($web-font-path);
      -
      -// Navbar =====================================================================
      -
      -.navbar {
      -  border: none;
      -  font-size: 13px;
      -  font-weight: 300;
      -
      -  .navbar-toggle:hover .icon-bar {
      -    background-color: #b3b3b3;
      -  }
      -
      -  &-collapse {
      -    border-top-color: $dropdown-divider-bg;
      -    @include box-shadow(none);
      -  }
      -
      -  .btn {
      -    padding-top: 6px;
      -    padding-bottom: 6px;
      -  }
      -
      -  &-form {
      -    margin-top: 7px;
      -    margin-bottom: 5px;
      -
      -    .form-control {
      -      height: auto;
      -      padding: $padding-xs-vertical $padding-xs-horizontal;
      -    }
      -  }
      -
      -  .dropdown {
      -
      -    &-menu {
      -      border: none;
      -
      -      > li > a,
      -      > li > a:focus {
      -        background-color: transparent;
      -        font-size: 13px;
      -        font-weight: 300;
      -      }
      -    }
      -
      -    &-header {
      -      color: rgba(255, 255, 255, 0.5);
      -    }
      -
      -  }
      -
      -  &-default {
      -
      -    .dropdown-menu {
      -      background-color: $navbar-default-bg;
      -
      -      > li > a,
      -      > li > a:focus {
      -        color: $navbar-default-color;
      -      }
      -
      -      > li > a:hover,
      -      > .active > a,
      -      > .active > a:hover {
      -        background-color: $navbar-default-link-hover-bg;
      -      }
      -    }
      -  }
      -
      -  &-inverse {
      -
      -    .dropdown-menu {
      -      background-color: $navbar-inverse-bg;
      -
      -      > li > a,
      -      > li > a:focus {
      -        color: $navbar-inverse-color;
      -      }
      -
      -      > li > a:hover,
      -      > .active > a,
      -      > .active > a:hover {
      -        background-color: $navbar-inverse-link-hover-bg;
      -      }
      -    }
      -  }
      -}
      -
      -// Buttons ====================================================================
      -
      -.btn {
      -  padding: $padding-base-vertical $padding-base-horizontal;
      -
      -  &-lg {
      -    padding: $padding-large-vertical $padding-large-horizontal;
      -  }
      -
      -  &-sm {
      -    padding: $padding-small-vertical $padding-small-horizontal;
      -  }
      -
      -  &-xs {
      -    padding: $padding-xs-vertical $padding-xs-horizontal;
      -  }
      -}
      -
      -.btn-group {
      -
      -  .btn ~ .dropdown-toggle {
      -    padding-left: 16px;
      -    padding-right: 16px;
      -  }
      -
      -  .dropdown-menu {
      -    border-top-width: 0;
      -  }
      -
      -  &.dropup .dropdown-menu {
      -    border-top-width: 1px;
      -    border-bottom-width: 0;
      -    margin-bottom: 0;
      -  }
      -
      -  .dropdown-toggle {
      -
      -    &.btn-default ~ .dropdown-menu {
      -      background-color: $btn-default-bg;
      -      border-color: $btn-default-border;
      -
      -      > li > a {
      -        color: $btn-default-color;
      -      }
      -
      -      > li > a:hover {
      -        background-color: darken($btn-default-bg, 8%);
      -      }
      -    }
      -
      -    &.btn-primary ~ .dropdown-menu {
      -      background-color: $btn-primary-bg;
      -      border-color: $btn-primary-border;
      -
      -      > li > a {
      -        color: $btn-primary-color;
      -      }
      -
      -      > li > a:hover {
      -        background-color: darken($btn-primary-bg, 8%);
      -      }
      -    }
      -
      -    &.btn-success ~ .dropdown-menu {
      -      background-color: $btn-success-bg;
      -      border-color: $btn-success-border;
      -
      -      > li > a {
      -        color: $btn-success-color;
      -      }
      -
      -      > li > a:hover {
      -        background-color: darken($btn-success-bg, 8%);
      -      }
      -    }
      -
      -    &.btn-info ~ .dropdown-menu {
      -      background-color: $btn-info-bg;
      -      border-color: $btn-info-border;
      -
      -      > li > a {
      -        color: $btn-info-color;
      -      }
      -
      -      > li > a:hover {
      -        background-color: darken($btn-info-bg, 8%);
      -      }
      -    }
      -
      -    &.btn-warning ~ .dropdown-menu {
      -      background-color: $btn-warning-bg;
      -      border-color: $btn-warning-border;
      -
      -      > li > a {
      -        color: $btn-warning-color;
      -      }
      -
      -      > li > a:hover {
      -        background-color: darken($btn-warning-bg, 8%);
      -      }
      -    }
      -
      -    &.btn-danger ~ .dropdown-menu {
      -      background-color: $btn-danger-bg;
      -      border-color: $btn-danger-border;
      -
      -      > li > a {
      -        color: $btn-danger-color;
      -      }
      -
      -      > li > a:hover {
      -        background-color: darken($btn-danger-bg, 8%);
      -      }
      -    }
      -  }
      -}
      -
      -// Typography =================================================================
      -
      -.lead {
      -  color: $gray;
      -}
      -
      -cite {
      -  font-style: italic;
      -}
      -
      -blockquote {
      -  border-left-width: 1px;
      -  color: $gray;
      -
      -  &.pull-right {
      -    border-right-width: 1px;
      -  }
      -
      -  small {
      -    font-size: $font-size-small;
      -    font-weight: 300;
      -  }
      -}
      -
      -// Tables =====================================================================
      -
      -table {
      -  font-size: $font-size-small;
      -}
      -
      -// Forms ======================================================================
      -
      -label,
      -.control-label,
      -.help-block,
      -.checkbox,
      -.radio {
      -  font-size: $font-size-small;
      -  font-weight: normal;
      -}
      -
      -input[type="radio"],
      -input[type="checkbox"] {
      -  margin-top: 1px;
      -}
      -
      -// Navs =======================================================================
      -
      -.nav {
      -  .open > a,
      -  .open > a:hover,
      -  .open > a:focus {
      -    border-color: transparent;
      -  }
      -}
      -
      -.nav-tabs {
      -  > li > a {
      -    background-color: $btn-default-bg;
      -    color: $text-color;
      -  }
      -
      -  .caret {
      -    border-top-color: $text-color;
      -    border-bottom-color: $text-color;
      -  }
      -}
      -
      -.nav-pills {
      -  font-weight: 300;
      -}
      -
      -.breadcrumb {
      -  border: 1px solid $table-border-color;
      -  border-radius: 3px;
      -  font-size: 10px;
      -  font-weight: 300;
      -  text-transform: uppercase;
      -}
      -
      -.pagination {
      -  font-size: $font-size-small;
      -  font-weight: 300;
      -  color: $gray-light;
      -
      -  > li {
      -    > a,
      -    > span {
      -      margin-left: 4px;
      -      color: $gray-light;
      -    }
      -  }
      -
      -  > .active {
      -    > a,
      -    > span {
      -      color: #fff;
      -    }
      -  }
      -
      -  > li,
      -  > li:first-child,
      -  > li:last-child {
      -    > a,
      -    > span {
      -      border-radius: 3px;
      -    }
      -  }
      -
      -  &-lg > li > a,
      -  &-lg > li > span {
      -    padding-left: 22px;
      -    padding-right: 22px;
      -  }
      -
      -  &-sm > li > a,
      -  &-sm > li > span {
      -    padding: 0 5px;
      -  }
      -}
      -
      -.pager {
      -  font-size: $font-size-small;
      -  font-weight: 300;
      -  color: $gray-light;
      -}
      -
      -.list-group {
      -  font-size: $font-size-small;
      -  font-weight: 300;
      -}
      -
      -// Indicators =================================================================
      -
      -.close {
      -  opacity: 0.4;
      -  text-decoration: none;
      -  text-shadow: none;
      -
      -  &:hover,
      -  &:focus {
      -    opacity: 1;
      -  }
      -}
      -
      -.alert {
      -  font-size: $font-size-small;
      -  font-weight: 300;
      -
      -  .alert-link {
      -    font-weight: normal;
      -    color: #fff;
      -    text-decoration: underline;
      -  }
      -}
      -
      -.label {
      -  padding-left: 1em;
      -  padding-right: 1em;
      -  border-radius: 0;
      -  font-weight: 300;
      -
      -  &-default {
      -    background-color: $btn-default-bg;
      -    color: $btn-default-color;
      -  }
      -}
      -
      -.badge {
      -  font-weight: 300;
      -}
      -
      -// Progress bars ==============================================================
      -
      -.progress {
      -  height: 22px;
      -  padding: 2px;
      -  background-color: #f6f6f6;
      -  border: 1px solid #ccc;
      -  @include box-shadow(none);
      -}
      -
      -// Containers =================================================================
      -
      -.dropdown {
      -
      -  &-menu {
      -    padding: 0;
      -    margin-top: 0;
      -    font-size: $font-size-small;
      -
      -    > li > a {
      -      padding: 12px 15px;
      -    }
      -  }
      -
      -  &-header {
      -    padding-left: 15px;
      -    padding-right: 15px;
      -    font-size: 9px;
      -    text-transform: uppercase;
      -  }
      -}
      -
      -.popover {
      -  color: #fff;
      -  font-size: 12px;
      -  font-weight: 300;
      -}
      -
      -.panel {
      -  &-heading,
      -  &-footer {
      -    border-top-right-radius: 0;
      -    border-top-left-radius: 0;
      -  }
      -
      -  &-default {
      -    .close {
      -      color: $text-color;
      -    }
      -  }
      -}
      -
      -.modal {
      -  .close {
      -    color: $text-color;
      -  }
      -}
      diff --git a/vendor/assets/stylesheets/yeti/_variables.scss b/vendor/assets/stylesheets/yeti/_variables.scss
      deleted file mode 100644
      index 3110c78..0000000
      --- a/vendor/assets/stylesheets/yeti/_variables.scss
      +++ /dev/null
      @@ -1,870 +0,0 @@
      -$bootstrap-sass-asset-helper: false !default;
      -// Yeti 3.3.6
      -// Variables
      -// --------------------------------------------------
      -
      -
      -//== Colors
      -//
      -//## Gray and brand colors for use across Bootstrap.
      -
      -$gray-base:              #000 !default;
      -$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
      -$gray-dark:              lighten($gray-base, 20%) !default;   // #333
      -$gray:                   #6f6f6f !default; // #555
      -$gray-light:             lighten($gray-base, 60%) !default;   // #999
      -$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
      -
      -$brand-primary:         #008cba !default;
      -$brand-success:         #43ac6a !default;
      -$brand-info:            #5bc0de !default;
      -$brand-warning:         #E99002 !default;
      -$brand-danger:          #F04124 !default;
      -
      -
      -//== Scaffolding
      -//
      -//## Settings for some of the most global styles.
      -
      -//** Background color for ``.
      -$body-bg:               #fff !default;
      -//** Global text color on ``.
      -$text-color:            $gray-darker !default;
      -
      -//** Global textual link color.
      -$link-color:            $brand-primary !default;
      -//** Link hover color set via `darken()` function.
      -$link-hover-color:      $link-color !default;
      -//** Link hover decoration.
      -$link-hover-decoration: underline !default;
      -
      -
      -//== Typography
      -//
      -//## Font, line-height, and color for body text, headings, and more.
      -
      -$font-family-sans-serif:  "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
      -$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
      -//** Default monospace fonts for ``, ``, and `
      `.
      -$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
      -$font-family-base:        $font-family-sans-serif !default;
      -
      -$font-size-base:          15px !default;
      -$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-small:         12px !default; // ~12px
      -
      -$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
      -$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
      -$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
      -$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
      -$font-size-h5:            $font-size-base !default;
      -$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
      -
      -//** Unit-less `line-height` for use in components like buttons.
      -$line-height-base:        1.4 !default;
      -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
      -$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
      -
      -//** By default, this inherits from the ``.
      -$headings-font-family:    $font-family-base !default;
      -$headings-font-weight:    300 !default;
      -$headings-line-height:    1.1 !default;
      -$headings-color:          inherit !default;
      -
      -
      -//== Iconography
      -//
      -//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
      -
      -//** Load fonts from this directory.
      -$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
      -//** File name for all font files.
      -$icon-font-name:          "glyphicons-halflings-regular" !default;
      -//** Element ID within SVG icon file.
      -$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
      -
      -
      -//== Components
      -//
      -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
      -
      -$padding-base-vertical:     8px !default;
      -$padding-base-horizontal:   12px !default;
      -
      -$padding-large-vertical:    16px !default;
      -$padding-large-horizontal:  20px !default;
      -
      -$padding-small-vertical:    8px !default;
      -$padding-small-horizontal:  12px !default;
      -
      -$padding-xs-vertical:       4px !default;
      -$padding-xs-horizontal:     6px !default;
      -
      -$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
      -$line-height-small:         1.5 !default;
      -
      -$border-radius-base:        0 !default;
      -$border-radius-large:       0 !default;
      -$border-radius-small:       0 !default;
      -
      -//** Global color for active items (e.g., navs or dropdowns).
      -$component-active-color:    #fff !default;
      -//** Global background color for active items (e.g., navs or dropdowns).
      -$component-active-bg:       $brand-primary !default;
      -
      -//** Width of the `border` for generating carets that indicator dropdowns.
      -$caret-width-base:          4px !default;
      -//** Carets increase slightly in size for larger components.
      -$caret-width-large:         5px !default;
      -
      -
      -//== Tables
      -//
      -//## Customizes the `.table` component with basic values, each used across all table variations.
      -
      -//** Padding for ``s and ``s.
      -$table-cell-padding:            8px !default;
      -//** Padding for cells in `.table-condensed`.
      -$table-condensed-cell-padding:  5px !default;
      -
      -//** Default background color used for all tables.
      -$table-bg:                      transparent !default;
      -//** Background color used for `.table-striped`.
      -$table-bg-accent:               #f9f9f9 !default;
      -//** Background color used for `.table-hover`.
      -$table-bg-hover:                #f5f5f5 !default;
      -$table-bg-active:               $table-bg-hover !default;
      -
      -//** Border color for table and cell borders.
      -$table-border-color:            #ddd !default;
      -
      -
      -//== Buttons
      -//
      -//## For each of Bootstrap's buttons, define text, background and border color.
      -
      -$btn-font-weight:                normal !default;
      -
      -$btn-default-color:              $gray-dark !default;
      -$btn-default-bg:                 #e7e7e7 !default;
      -$btn-default-border:             #ccc !default;
      -
      -$btn-primary-color:              #fff !default;
      -$btn-primary-bg:                 $brand-primary !default;
      -$btn-primary-border:             darken($btn-primary-bg, 5%) !default;
      -
      -$btn-success-color:              #fff !default;
      -$btn-success-bg:                 $brand-success !default;
      -$btn-success-border:             darken($btn-success-bg, 5%) !default;
      -
      -$btn-info-color:                 #fff !default;
      -$btn-info-bg:                    $brand-info !default;
      -$btn-info-border:                darken($btn-info-bg, 5%) !default;
      -
      -$btn-warning-color:              #fff !default;
      -$btn-warning-bg:                 $brand-warning !default;
      -$btn-warning-border:             darken($btn-warning-bg, 5%) !default;
      -
      -$btn-danger-color:               #fff !default;
      -$btn-danger-bg:                  $brand-danger !default;
      -$btn-danger-border:              darken($btn-danger-bg, 5%) !default;
      -
      -$btn-link-disabled-color:        $gray-light !default;
      -
      -// Allows for customizing button radius independently from global border radius
      -$btn-border-radius-base:         $border-radius-base !default;
      -$btn-border-radius-large:        $border-radius-large !default;
      -$btn-border-radius-small:        $border-radius-small !default;
      -
      -
      -//== Forms
      -//
      -//##
      -
      -//** `` background color
      -$input-bg:                       #fff !default;
      -//** `` background color
      -$input-bg-disabled:              $gray-lighter !default;
      -
      -//** Text color for ``s
      -$input-color:                    $gray !default;
      -//** `` border color
      -$input-border:                   #ccc !default;
      -
      -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
      -//** Default `.form-control` border radius
      -// This has no effect on ``s in CSS.
      -$input-border-radius:            $border-radius-base !default;
      -//** Large `.form-control` border radius
      -$input-border-radius-large:      $border-radius-large !default;
      -//** Small `.form-control` border radius
      -$input-border-radius-small:      $border-radius-small !default;
      -
      -//** Border color for inputs on focus
      -$input-border-focus:             #66afe9 !default;
      -
      -//** Placeholder text color
      -$input-color-placeholder:        $gray-light !default;
      -
      -//** Default `.form-control` height
      -$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
      -//** Large `.form-control` height
      -$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
      -//** Small `.form-control` height
      -$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
      -
      -//** `.form-group` margin
      -$form-group-margin-bottom:       15px !default;
      -
      -$legend-color:                   $gray-dark !default;
      -$legend-border-color:            #e5e5e5 !default;
      -
      -//** Background color for textual input addons
      -$input-group-addon-bg:           $gray-lighter !default;
      -//** Border color for textual input addons
      -$input-group-addon-border-color: $input-border !default;
      -
      -//** Disabled cursor for form controls and buttons.
      -$cursor-disabled:                not-allowed !default;
      -
      -
      -//== Dropdowns
      -//
      -//## Dropdown menu container and contents.
      -
      -//** Background for the dropdown menu.
      -$dropdown-bg:                    #fff !default;
      -//** Dropdown menu `border-color`.
      -$dropdown-border:                rgba(0,0,0,.15) !default;
      -//** Dropdown menu `border-color` **for IE8**.
      -$dropdown-fallback-border:       #ccc !default;
      -//** Divider color for between dropdown items.
      -$dropdown-divider-bg:            rgba(0,0,0,.2) !default;
      -
      -//** Dropdown link text color.
      -$dropdown-link-color:            #555 !default;
      -//** Hover color for dropdown links.
      -$dropdown-link-hover-color:      darken($gray-dark, 5%) !default;
      -//** Hover background for dropdown links.
      -$dropdown-link-hover-bg:         #eee !default;
      -
      -//** Active dropdown menu item text color.
      -$dropdown-link-active-color:     $component-active-color !default;
      -//** Active dropdown menu item background color.
      -$dropdown-link-active-bg:        $component-active-bg !default;
      -
      -//** Disabled dropdown menu item background color.
      -$dropdown-link-disabled-color:   $gray-light !default;
      -
      -//** Text color for headers within dropdown menus.
      -$dropdown-header-color:          $gray-light !default;
      -
      -//** Deprecated `$dropdown-caret-color` as of v3.1.0
      -$dropdown-caret-color:           #000 !default;
      -
      -
      -//-- Z-index master list
      -//
      -// Warning: Avoid customizing these values. They're used for a bird's eye view
      -// of components dependent on the z-axis and are designed to all work together.
      -//
      -// Note: These variables are not generated into the Customizer.
      -
      -$zindex-navbar:            1000 !default;
      -$zindex-dropdown:          1000 !default;
      -$zindex-popover:           1060 !default;
      -$zindex-tooltip:           1070 !default;
      -$zindex-navbar-fixed:      1030 !default;
      -$zindex-modal-background:  1040 !default;
      -$zindex-modal:             1050 !default;
      -
      -
      -//== Media queries breakpoints
      -//
      -//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
      -
      -// Extra small screen / phone
      -//** Deprecated `$screen-xs` as of v3.0.1
      -$screen-xs:                  480px !default;
      -//** Deprecated `$screen-xs-min` as of v3.2.0
      -$screen-xs-min:              $screen-xs !default;
      -//** Deprecated `$screen-phone` as of v3.0.1
      -$screen-phone:               $screen-xs-min !default;
      -
      -// Small screen / tablet
      -//** Deprecated `$screen-sm` as of v3.0.1
      -$screen-sm:                  768px !default;
      -$screen-sm-min:              $screen-sm !default;
      -//** Deprecated `$screen-tablet` as of v3.0.1
      -$screen-tablet:              $screen-sm-min !default;
      -
      -// Medium screen / desktop
      -//** Deprecated `$screen-md` as of v3.0.1
      -$screen-md:                  992px !default;
      -$screen-md-min:              $screen-md !default;
      -//** Deprecated `$screen-desktop` as of v3.0.1
      -$screen-desktop:             $screen-md-min !default;
      -
      -// Large screen / wide desktop
      -//** Deprecated `$screen-lg` as of v3.0.1
      -$screen-lg:                  1200px !default;
      -$screen-lg-min:              $screen-lg !default;
      -//** Deprecated `$screen-lg-desktop` as of v3.0.1
      -$screen-lg-desktop:          $screen-lg-min !default;
      -
      -// So media queries don't overlap when required, provide a maximum
      -$screen-xs-max:              ($screen-sm-min - 1) !default;
      -$screen-sm-max:              ($screen-md-min - 1) !default;
      -$screen-md-max:              ($screen-lg-min - 1) !default;
      -
      -
      -//== Grid system
      -//
      -//## Define your custom responsive grid.
      -
      -//** Number of columns in the grid.
      -$grid-columns:              12 !default;
      -//** Padding between columns. Gets divided in half for the left and right.
      -$grid-gutter-width:         30px !default;
      -// Navbar collapse
      -//** Point at which the navbar becomes uncollapsed.
      -$grid-float-breakpoint:     $screen-sm-min !default;
      -//** Point at which the navbar begins collapsing.
      -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
      -
      -
      -//== Container sizes
      -//
      -//## Define the maximum width of `.container` for different screen sizes.
      -
      -// Small screen / tablet
      -$container-tablet:             (720px + $grid-gutter-width) !default;
      -//** For `$screen-sm-min` and up.
      -$container-sm:                 $container-tablet !default;
      -
      -// Medium screen / desktop
      -$container-desktop:            (940px + $grid-gutter-width) !default;
      -//** For `$screen-md-min` and up.
      -$container-md:                 $container-desktop !default;
      -
      -// Large screen / wide desktop
      -$container-large-desktop:      (1140px + $grid-gutter-width) !default;
      -//** For `$screen-lg-min` and up.
      -$container-lg:                 $container-large-desktop !default;
      -
      -
      -//== Navbar
      -//
      -//##
      -
      -// Basics of a navbar
      -$navbar-height:                    45px !default;
      -$navbar-margin-bottom:             $line-height-computed !default;
      -$navbar-border-radius:             $border-radius-base !default;
      -$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
      -$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
      -$navbar-collapse-max-height:       340px !default;
      -
      -$navbar-default-color:             #fff !default;
      -$navbar-default-bg:                $gray-dark !default;
      -$navbar-default-border:            darken($navbar-default-bg, 6.5%) !default;
      -
      -// Navbar links
      -$navbar-default-link-color:                #fff !default;
      -$navbar-default-link-hover-color:          #fff !default;
      -$navbar-default-link-hover-bg:             #272727 !default;
      -$navbar-default-link-active-color:         #fff !default;
      -$navbar-default-link-active-bg:            #272727 !default;
      -$navbar-default-link-disabled-color:       #ccc !default;
      -$navbar-default-link-disabled-bg:          transparent !default;
      -
      -// Navbar brand label
      -$navbar-default-brand-color:               $navbar-default-link-color !default;
      -$navbar-default-brand-hover-color:         $navbar-default-brand-color !default;
      -$navbar-default-brand-hover-bg:            transparent !default;
      -
      -// Navbar toggle
      -$navbar-default-toggle-hover-bg:           transparent !default;
      -$navbar-default-toggle-icon-bar-bg:        #fff !default;
      -$navbar-default-toggle-border-color:       transparent !default;
      -
      -
      -//=== Inverted navbar
      -// Reset inverted navbar basics
      -$navbar-inverse-color:                      #fff !default;
      -$navbar-inverse-bg:                         $brand-primary !default;
      -$navbar-inverse-border:                     darken($navbar-inverse-bg, 10%) !default;
      -
      -// Inverted navbar links
      -$navbar-inverse-link-color:                 #fff !default;
      -$navbar-inverse-link-hover-color:           #fff !default;
      -$navbar-inverse-link-hover-bg:              darken($navbar-inverse-bg, 10%) !default;
      -$navbar-inverse-link-active-color:          #fff !default;
      -$navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 10%) !default;
      -$navbar-inverse-link-disabled-color:        #444 !default;
      -$navbar-inverse-link-disabled-bg:           transparent !default;
      -
      -// Inverted navbar brand label
      -$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;
      -$navbar-inverse-brand-hover-color:          #fff !default;
      -$navbar-inverse-brand-hover-bg:             transparent !default;
      -
      -// Inverted navbar toggle
      -$navbar-inverse-toggle-hover-bg:            transparent !default;
      -$navbar-inverse-toggle-icon-bar-bg:         #fff !default;
      -$navbar-inverse-toggle-border-color:        transparent !default;
      -
      -
      -//== Navs
      -//
      -//##
      -
      -//=== Shared nav styles
      -$nav-link-padding:                          10px 15px !default;
      -$nav-link-hover-bg:                         $gray-lighter !default;
      -
      -$nav-disabled-link-color:                   $gray-light !default;
      -$nav-disabled-link-hover-color:             $gray-light !default;
      -
      -//== Tabs
      -$nav-tabs-border-color:                     $table-border-color !default;
      -
      -$nav-tabs-link-hover-border-color:          $gray-lighter !default;
      -
      -$nav-tabs-active-link-hover-bg:             $body-bg !default;
      -$nav-tabs-active-link-hover-color:          $gray !default;
      -$nav-tabs-active-link-hover-border-color:   $table-border-color !default;
      -
      -$nav-tabs-justified-link-border-color:            $table-border-color !default;
      -$nav-tabs-justified-active-link-border-color:     $body-bg !default;
      -
      -//== Pills
      -$nav-pills-border-radius:                   $border-radius-base !default;
      -$nav-pills-active-link-hover-bg:            $component-active-bg !default;
      -$nav-pills-active-link-hover-color:         $component-active-color !default;
      -
      -
      -//== Pagination
      -//
      -//##
      -
      -$pagination-color:                     $link-color !default;
      -$pagination-bg:                        transparent !default;
      -$pagination-border:                    transparent !default;
      -
      -$pagination-hover-color:               $link-hover-color !default;
      -$pagination-hover-bg:                  $gray-lighter !default;
      -$pagination-hover-border:              transparent !default;
      -
      -$pagination-active-color:              #fff !default;
      -$pagination-active-bg:                 $brand-primary !default;
      -$pagination-active-border:             transparent !default;
      -
      -$pagination-disabled-color:            $gray-light !default;
      -$pagination-disabled-bg:               #fff !default;
      -$pagination-disabled-border:           transparent !default;
      -
      -
      -//== Pager
      -//
      -//##
      -
      -$pager-bg:                             $pagination-bg !default;
      -$pager-border:                         $pagination-border !default;
      -$pager-border-radius:                  3px !default;
      -
      -$pager-hover-bg:                       $pagination-hover-bg !default;
      -
      -$pager-active-bg:                      $pagination-active-bg !default;
      -$pager-active-color:                   $pagination-active-color !default;
      -
      -$pager-disabled-color:                 $gray-light !default;
      -
      -
      -//== Jumbotron
      -//
      -//##
      -
      -$jumbotron-padding:              30px !default;
      -$jumbotron-color:                inherit !default;
      -$jumbotron-bg:                   #fafafa !default;
      -$jumbotron-heading-color:        inherit !default;
      -$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
      -$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
      -
      -
      -//== Form states and alerts
      -//
      -//## Define colors for form feedback states and, by default, alerts.
      -
      -$state-success-text:             $brand-success !default;
      -$state-success-bg:               #dff0d8 !default;
      -$state-success-border:           darken($state-success-text, 5%) !default;
      -
      -$state-info-text:                $brand-info !default;
      -$state-info-bg:                  #d9edf7 !default;
      -$state-info-border:              darken($state-info-text, 7%) !default;
      -
      -$state-warning-text:             $brand-warning !default;
      -$state-warning-bg:               #fcf8e3 !default;
      -$state-warning-border:           darken($state-warning-text, 5%) !default;
      -
      -$state-danger-text:              $brand-danger !default;
      -$state-danger-bg:                #f2dede !default;
      -$state-danger-border:            darken($state-danger-text, 5%) !default;
      -
      -
      -//== Tooltips
      -//
      -//##
      -
      -//** Tooltip max width
      -$tooltip-max-width:           200px !default;
      -//** Tooltip text color
      -$tooltip-color:               #fff !default;
      -//** Tooltip background color
      -$tooltip-bg:                  $gray-dark !default;
      -$tooltip-opacity:             .9 !default;
      -
      -//** Tooltip arrow width
      -$tooltip-arrow-width:         5px !default;
      -//** Tooltip arrow color
      -$tooltip-arrow-color:         $tooltip-bg !default;
      -
      -
      -//== Popovers
      -//
      -//##
      -
      -//** Popover body background color
      -$popover-bg:                          $gray-dark !default;
      -//** Popover maximum width
      -$popover-max-width:                   276px !default;
      -//** Popover border color
      -$popover-border-color:                transparent !default;
      -//** Popover fallback border color
      -$popover-fallback-border-color:       $gray-dark !default;
      -
      -//** Popover title background color
      -$popover-title-bg:                    $popover-bg !default;
      -
      -//** Popover arrow width
      -$popover-arrow-width:                 10px !default;
      -//** Popover arrow color
      -$popover-arrow-color:                 $popover-bg !default;
      -
      -//** Popover outer arrow width
      -$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
      -//** Popover outer arrow color
      -$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
      -//** Popover outer arrow fallback color
      -$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
      -
      -
      -//== Labels
      -//
      -//##
      -
      -//** Default label background color
      -$label-default-bg:            $gray-light !default;
      -//** Primary label background color
      -$label-primary-bg:            $brand-primary !default;
      -//** Success label background color
      -$label-success-bg:            $brand-success !default;
      -//** Info label background color
      -$label-info-bg:               $brand-info !default;
      -//** Warning label background color
      -$label-warning-bg:            $brand-warning !default;
      -//** Danger label background color
      -$label-danger-bg:             $brand-danger !default;
      -
      -//** Default label text color
      -$label-color:                 #fff !default;
      -//** Default text color of a linked label
      -$label-link-hover-color:      #fff !default;
      -
      -
      -//== Modals
      -//
      -//##
      -
      -//** Padding applied to the modal body
      -$modal-inner-padding:         20px !default;
      -
      -//** Padding applied to the modal title
      -$modal-title-padding:         15px !default;
      -//** Modal title line-height
      -$modal-title-line-height:     $line-height-base !default;
      -
      -//** Background color of modal content area
      -$modal-content-bg:                             #fff !default;
      -//** Modal content border color
      -$modal-content-border-color:                   rgba(0,0,0,.2) !default;
      -//** Modal content border color **for IE8**
      -$modal-content-fallback-border-color:          #999 !default;
      -
      -//** Modal backdrop background color
      -$modal-backdrop-bg:           #000 !default;
      -//** Modal backdrop opacity
      -$modal-backdrop-opacity:      .5 !default;
      -//** Modal header border color
      -$modal-header-border-color:   #e5e5e5 !default;
      -//** Modal footer border color
      -$modal-footer-border-color:   $modal-header-border-color !default;
      -
      -$modal-lg:                    900px !default;
      -$modal-md:                    600px !default;
      -$modal-sm:                    300px !default;
      -
      -
      -//== Alerts
      -//
      -//## Define alert colors, border radius, and padding.
      -
      -$alert-padding:               15px !default;
      -$alert-border-radius:         $border-radius-base !default;
      -$alert-link-font-weight:      bold !default;
      -
      -$alert-success-bg:            $brand-success !default;
      -$alert-success-text:          #fff !default;
      -$alert-success-border:        $state-success-border !default;
      -
      -$alert-info-bg:               $brand-info !default;
      -$alert-info-text:             #fff !default;
      -$alert-info-border:           $state-info-border !default;
      -
      -$alert-warning-bg:            $brand-warning !default;
      -$alert-warning-text:          #fff !default;
      -$alert-warning-border:        $state-warning-border !default;
      -
      -$alert-danger-bg:             $brand-danger !default;
      -$alert-danger-text:           #fff !default;
      -$alert-danger-border:         $state-danger-border !default;
      -
      -
      -//== Progress bars
      -//
      -//##
      -
      -//** Background color of the whole progress component
      -$progress-bg:                 #f5f5f5 !default;
      -//** Progress bar text color
      -$progress-bar-color:          #fff !default;
      -//** Variable for setting rounded corners on progress bar.
      -$progress-border-radius:      $border-radius-base !default;
      -
      -//** Default progress bar color
      -$progress-bar-bg:             $brand-primary !default;
      -//** Success progress bar color
      -$progress-bar-success-bg:     $brand-success !default;
      -//** Warning progress bar color
      -$progress-bar-warning-bg:     $brand-warning !default;
      -//** Danger progress bar color
      -$progress-bar-danger-bg:      $brand-danger !default;
      -//** Info progress bar color
      -$progress-bar-info-bg:        $brand-info !default;
      -
      -
      -//== List group
      -//
      -//##
      -
      -//** Background color on `.list-group-item`
      -$list-group-bg:                 #fff !default;
      -//** `.list-group-item` border color
      -$list-group-border:             $table-border-color !default;
      -//** List group border radius
      -$list-group-border-radius:      $border-radius-base !default;
      -
      -//** Background color of single list items on hover
      -$list-group-hover-bg:           #f5f5f5 !default;
      -//** Text color of active list items
      -$list-group-active-color:       $component-active-color !default;
      -//** Background color of active list items
      -$list-group-active-bg:          $component-active-bg !default;
      -//** Border color of active list elements
      -$list-group-active-border:      $list-group-active-bg !default;
      -//** Text color for content within active list items
      -$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
      -
      -//** Text color of disabled list items
      -$list-group-disabled-color:      $gray-light !default;
      -//** Background color of disabled list items
      -$list-group-disabled-bg:         $gray-lighter !default;
      -//** Text color for content within disabled list items
      -$list-group-disabled-text-color: $list-group-disabled-color !default;
      -
      -$list-group-link-color:         #555 !default;
      -$list-group-link-hover-color:   $list-group-link-color !default;
      -$list-group-link-heading-color: #333 !default;
      -
      -
      -//== Panels
      -//
      -//##
      -
      -$panel-bg:                    #fff !default;
      -$panel-body-padding:          15px !default;
      -$panel-heading-padding:       10px 15px !default;
      -$panel-footer-padding:        $panel-heading-padding !default;
      -$panel-border-radius:         $border-radius-base !default;
      -
      -//** Border color for elements within panels
      -$panel-inner-border:          $table-border-color !default;
      -$panel-footer-bg:             #f5f5f5 !default;
      -
      -$panel-default-text:          $gray-dark !default;
      -$panel-default-border:        $table-border-color !default;
      -$panel-default-heading-bg:    #f5f5f5 !default;
      -
      -$panel-primary-text:          #fff !default;
      -$panel-primary-border:        $brand-primary !default;
      -$panel-primary-heading-bg:    $brand-primary !default;
      -
      -$panel-success-text:          #fff !default;
      -$panel-success-border:        $state-success-border !default;
      -$panel-success-heading-bg:    $brand-success !default;
      -
      -$panel-info-text:             #fff !default;
      -$panel-info-border:           $state-info-border !default;
      -$panel-info-heading-bg:       $brand-info !default;
      -
      -$panel-warning-text:          #fff !default;
      -$panel-warning-border:        $state-warning-border !default;
      -$panel-warning-heading-bg:    $brand-warning !default;
      -
      -$panel-danger-text:           #fff !default;
      -$panel-danger-border:         $state-danger-border !default;
      -$panel-danger-heading-bg:     $brand-danger !default;
      -
      -
      -//== Thumbnails
      -//
      -//##
      -
      -//** Padding around the thumbnail image
      -$thumbnail-padding:           4px !default;
      -//** Thumbnail background color
      -$thumbnail-bg:                $body-bg !default;
      -//** Thumbnail border color
      -$thumbnail-border:            $table-border-color !default;
      -//** Thumbnail border radius
      -$thumbnail-border-radius:     $border-radius-base !default;
      -
      -//** Custom text color for thumbnail captions
      -$thumbnail-caption-color:     $text-color !default;
      -//** Padding around the thumbnail caption
      -$thumbnail-caption-padding:   9px !default;
      -
      -
      -//== Wells
      -//
      -//##
      -
      -$well-bg:                     $jumbotron-bg !default;
      -$well-border:                 darken($well-bg, 7%) !default;
      -
      -
      -//== Badges
      -//
      -//##
      -
      -$badge-color:                 #fff !default;
      -//** Linked badge text color on hover
      -$badge-link-hover-color:      #fff !default;
      -$badge-bg:                    $btn-primary-bg !default;
      -
      -//** Badge text color in active nav link
      -$badge-active-color:          $link-color !default;
      -//** Badge background color in active nav link
      -$badge-active-bg:             #fff !default;
      -
      -$badge-font-weight:           bold !default;
      -$badge-line-height:           1 !default;
      -$badge-border-radius:         10px !default;
      -
      -
      -//== Breadcrumbs
      -//
      -//##
      -
      -$breadcrumb-padding-vertical:   8px !default;
      -$breadcrumb-padding-horizontal: 15px !default;
      -//** Breadcrumb background color
      -$breadcrumb-bg:                 #f5f5f5 !default;
      -//** Breadcrumb text color
      -$breadcrumb-color:              $gray-light !default;
      -//** Text color of current page in the breadcrumb
      -$breadcrumb-active-color:       $gray-dark !default;
      -//** Textual separator for between breadcrumb elements
      -$breadcrumb-separator:          "/" !default;
      -
      -
      -//== Carousel
      -//
      -//##
      -
      -$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
      -
      -$carousel-control-color:                      #fff !default;
      -$carousel-control-width:                      15% !default;
      -$carousel-control-opacity:                    .5 !default;
      -$carousel-control-font-size:                  20px !default;
      -
      -$carousel-indicator-active-bg:                #fff !default;
      -$carousel-indicator-border-color:             #fff !default;
      -
      -$carousel-caption-color:                      #fff !default;
      -
      -
      -//== Close
      -//
      -//##
      -
      -$close-font-weight:           bold !default;
      -$close-color:                 #fff !default;
      -$close-text-shadow:           0 1px 0 #fff !default;
      -
      -
      -//== Code
      -//
      -//##
      -
      -$code-color:                  #c7254e !default;
      -$code-bg:                     #f9f2f4 !default;
      -
      -$kbd-color:                   #fff !default;
      -$kbd-bg:                      #333 !default;
      -
      -$pre-bg:                      #f5f5f5 !default;
      -$pre-color:                   $gray-dark !default;
      -$pre-border-color:            #ccc !default;
      -$pre-scrollable-max-height:   340px !default;
      -
      -
      -//== Type
      -//
      -//##
      -
      -//** Horizontal offset for forms and lists.
      -$component-offset-horizontal: 180px !default;
      -//** Text muted color
      -$text-muted:                  $gray-light !default;
      -//** Abbreviations and acronyms border color
      -$abbr-border-color:           $gray-light !default;
      -//** Headings small color
      -$headings-small-color:        $gray-light !default;
      -//** Blockquote small color
      -$blockquote-small-color:      $gray !default;
      -//** Blockquote font size
      -$blockquote-font-size:        ($font-size-base * 1.25) !default;
      -//** Blockquote border color
      -$blockquote-border-color:     $table-border-color !default;
      -//** Page header border color
      -$page-header-border-color:    $table-border-color !default;
      -//** Width of horizontal description list titles
      -$dl-horizontal-offset:        $component-offset-horizontal !default;
      -//** Point at which .dl-horizontal becomes horizontal
      -$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
      -//** Horizontal line color.
      -$hr-border:                   $table-border-color !default;