locomotivecms 3.0.0.pre.alpha.2 → 3.0.0.pre.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -2
  3. data/README.md +1 -1
  4. data/app/api/locomotive/api/forms/membership_form.rb +13 -0
  5. data/app/api/locomotive/api/resources/membership_resource.rb +5 -3
  6. data/app/assets/javascripts/locomotive.js +2 -0
  7. data/app/assets/javascripts/locomotive/utils/backbone_patches.js.coffee +15 -1
  8. data/app/assets/javascripts/locomotive/utils/file.js.coffee +20 -0
  9. data/app/assets/javascripts/locomotive/utils/nprogress.js.coffee +5 -0
  10. data/app/assets/javascripts/locomotive/utils/rails_ujs.js.coffee +36 -0
  11. data/app/assets/javascripts/locomotive/utils/wysihtml5.js.coffee +1 -1
  12. data/app/assets/javascripts/locomotive/views/content_assets/picker_view.js.coffee +9 -17
  13. data/app/assets/javascripts/locomotive/views/editable_elements/edit_view.js.coffee +39 -0
  14. data/app/assets/javascripts/locomotive/views/editable_elements/index_view.js.coffee +104 -1
  15. data/app/assets/javascripts/locomotive/views/inputs/file_view.js.coffee +79 -10
  16. data/app/assets/javascripts/locomotive/views/inputs/rte/file_view.js.coffee +24 -4
  17. data/app/assets/javascripts/locomotive/views/inputs/rte_view.js.coffee.erb +18 -0
  18. data/app/assets/javascripts/locomotive/views/pages/new_view.js.coffee +3 -6
  19. data/app/assets/javascripts/locomotive/views/shared/drawer_view.js.coffee +24 -8
  20. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +21 -148
  21. data/app/assets/stylesheets/locomotive/application.scss +6 -0
  22. data/app/assets/stylesheets/locomotive/base/_form.scss +1 -0
  23. data/app/assets/stylesheets/locomotive/base/form/_base.scss +9 -0
  24. data/app/assets/stylesheets/locomotive/base/form/_file_input.scss +1 -1
  25. data/app/assets/stylesheets/locomotive/base/form/_link.scss +13 -0
  26. data/app/assets/stylesheets/locomotive/base/form/_select2.scss +28 -1
  27. data/app/assets/stylesheets/locomotive/components/_drawer.scss +8 -18
  28. data/app/assets/stylesheets/locomotive/components/_live_editing.scss +83 -0
  29. data/app/assets/stylesheets/locomotive/components/_transitions.scss +63 -1
  30. data/app/assets/stylesheets/locomotive/components/header/_base.scss +5 -1
  31. data/app/assets/stylesheets/locomotive/components/misc/_notify.scss +5 -7
  32. data/app/assets/stylesheets/locomotive/globals/_bootstrap.scss +4 -4
  33. data/app/assets/stylesheets/locomotive/globals/_mixins.scss +16 -0
  34. data/app/assets/stylesheets/locomotive/globals/_nprogress.scss +3 -0
  35. data/app/assets/stylesheets/locomotive/globals/_variables.scss +57 -49
  36. data/app/assets/stylesheets/locomotive/layouts/_live_editing.scss +29 -0
  37. data/app/controllers/locomotive/editable_elements_controller.rb +49 -2
  38. data/app/controllers/locomotive/pages_controller.rb +2 -2
  39. data/app/helpers/locomotive/custom_fields_helper.rb +1 -1
  40. data/app/helpers/locomotive/editable_elements_helper.rb +40 -0
  41. data/app/helpers/locomotive/pages_helper.rb +0 -1
  42. data/app/inputs/locomotive/array_input.rb +1 -1
  43. data/app/inputs/locomotive/file_input.rb +35 -7
  44. data/app/inputs/locomotive/rte_input.rb +2 -1
  45. data/app/inputs/locomotive/toggle_input.rb +1 -1
  46. data/app/models/locomotive/concerns/content_entry/localized.rb +4 -4
  47. data/app/models/locomotive/concerns/content_type/sync.rb +0 -5
  48. data/app/models/locomotive/concerns/page/redirect.rb +1 -1
  49. data/app/models/locomotive/content_entry.rb +5 -11
  50. data/app/models/locomotive/content_type.rb +22 -0
  51. data/app/models/locomotive/editable_control.rb +12 -27
  52. data/app/models/locomotive/editable_element.rb +8 -0
  53. data/app/models/locomotive/editable_file.rb +0 -1
  54. data/app/models/locomotive/editable_text.rb +10 -10
  55. data/app/models/locomotive/page.rb +1 -1
  56. data/app/policies/locomotive/page_policy.rb +1 -1
  57. data/app/services/locomotive/editable_element_service.rb +47 -0
  58. data/app/services/locomotive/page_parsing_service.rb +85 -31
  59. data/app/uploaders/locomotive/editable_file_uploader.rb +5 -1
  60. data/app/views/locomotive/editable_elements/_edit.html.haml +49 -0
  61. data/app/views/locomotive/editable_elements/_edit_with_content_entry.html.haml +21 -0
  62. data/app/views/locomotive/editable_elements/_form.html.haml +23 -0
  63. data/app/views/locomotive/editable_elements/index.html.haml +8 -2
  64. data/app/views/locomotive/editable_elements/index_without_preview.html.haml +33 -0
  65. data/app/views/locomotive/layouts/{preview.html.haml → live_editing.html.haml} +9 -9
  66. data/app/views/locomotive/my_account/form/_main.html.haml +1 -1
  67. data/app/views/locomotive/pages/form/_actions.html.haml +8 -1
  68. data/app/views/locomotive/pages/form/_main.html.haml +1 -1
  69. data/app/views/locomotive/pages/form/_tabs.html.haml +2 -2
  70. data/app/views/locomotive/pages/new.html.haml +1 -1
  71. data/app/views/locomotive/shared/header/_site.html.haml +1 -1
  72. data/app/views/locomotive/shared/rte/_image_popover.html.haml +2 -2
  73. data/app/views/locomotive/shared/rte/_link_popover.html.haml +1 -1
  74. data/app/views/locomotive/shared/sidebar/_page.html.haml +5 -2
  75. data/config/locales/admin_ui.en.yml +10 -16
  76. data/config/locales/inputs.en.yml +18 -11
  77. data/config/locales/simple_form.en.yml +13 -1
  78. data/config/routes.rb +3 -1
  79. data/lib/locomotive.rb +1 -1
  80. data/lib/locomotive/action_controller/responder.rb +16 -0
  81. data/lib/locomotive/carrierwave/patches.rb +54 -0
  82. data/lib/locomotive/dependencies.rb +1 -0
  83. data/lib/locomotive/engine.rb +9 -3
  84. data/lib/locomotive/middlewares.rb +1 -1
  85. data/lib/locomotive/middlewares/page_editing.rb +41 -0
  86. data/lib/locomotive/middlewares/site.rb +2 -0
  87. data/lib/locomotive/simple_form.rb +6 -5
  88. data/lib/locomotive/steam_adaptor.rb +2 -0
  89. data/lib/locomotive/version.rb +1 -1
  90. data/lib/tasks/development.rake +4 -0
  91. data/spec/dummy/config/environments/production.rb +2 -0
  92. data/spec/dummy/config/initializers/devise.rb +2 -0
  93. data/spec/dummy/config/mongoid.yml +2 -2
  94. data/spec/models/locomotive/content_entry_spec.rb +11 -2
  95. data/spec/support/factories.rb +0 -1
  96. data/vendor/assets/javascripts/locomotive/history.js +2122 -0
  97. data/vendor/assets/javascripts/locomotive/subscribe.js +206 -329
  98. metadata +44 -127
  99. data/lib/locomotive/middlewares/permalink.rb +0 -22
  100. data/lib/locomotive/previous_liquid/asset_host.rb +0 -51
  101. data/lib/locomotive/previous_liquid/drops/base.rb +0 -40
  102. data/lib/locomotive/previous_liquid/drops/content_entry.rb +0 -78
  103. data/lib/locomotive/previous_liquid/drops/content_types.rb +0 -119
  104. data/lib/locomotive/previous_liquid/drops/current_user.rb +0 -21
  105. data/lib/locomotive/previous_liquid/drops/page.rb +0 -115
  106. data/lib/locomotive/previous_liquid/drops/proxy_collection.rb +0 -64
  107. data/lib/locomotive/previous_liquid/drops/session_proxy.rb +0 -16
  108. data/lib/locomotive/previous_liquid/drops/site.rb +0 -29
  109. data/lib/locomotive/previous_liquid/drops/uploader.rb +0 -21
  110. data/lib/locomotive/previous_liquid/errors.rb +0 -8
  111. data/lib/locomotive/previous_liquid/filters/base.rb +0 -61
  112. data/lib/locomotive/previous_liquid/filters/date.rb +0 -82
  113. data/lib/locomotive/previous_liquid/filters/html.rb +0 -117
  114. data/lib/locomotive/previous_liquid/filters/misc.rb +0 -75
  115. data/lib/locomotive/previous_liquid/filters/resize.rb +0 -18
  116. data/lib/locomotive/previous_liquid/filters/text.rb +0 -53
  117. data/lib/locomotive/previous_liquid/filters/translate.rb +0 -38
  118. data/lib/locomotive/previous_liquid/patches.rb +0 -21
  119. data/lib/locomotive/previous_liquid/tags/consume.rb +0 -104
  120. data/lib/locomotive/previous_liquid/tags/csrf.rb +0 -40
  121. data/lib/locomotive/previous_liquid/tags/editable.rb +0 -4
  122. data/lib/locomotive/previous_liquid/tags/editable/base.rb +0 -88
  123. data/lib/locomotive/previous_liquid/tags/editable/control.rb +0 -41
  124. data/lib/locomotive/previous_liquid/tags/editable/file.rb +0 -43
  125. data/lib/locomotive/previous_liquid/tags/editable/text.rb +0 -79
  126. data/lib/locomotive/previous_liquid/tags/extends.rb +0 -47
  127. data/lib/locomotive/previous_liquid/tags/fetch_page.rb +0 -36
  128. data/lib/locomotive/previous_liquid/tags/google_analytics.rb +0 -39
  129. data/lib/locomotive/previous_liquid/tags/hybrid.rb +0 -25
  130. data/lib/locomotive/previous_liquid/tags/inherited_block.rb +0 -31
  131. data/lib/locomotive/previous_liquid/tags/inline_editor.rb +0 -40
  132. data/lib/locomotive/previous_liquid/tags/javascript.rb +0 -16
  133. data/lib/locomotive/previous_liquid/tags/link_to.rb +0 -43
  134. data/lib/locomotive/previous_liquid/tags/locale_switcher.rb +0 -83
  135. data/lib/locomotive/previous_liquid/tags/model_form.rb +0 -75
  136. data/lib/locomotive/previous_liquid/tags/nav.rb +0 -164
  137. data/lib/locomotive/previous_liquid/tags/paginate.rb +0 -114
  138. data/lib/locomotive/previous_liquid/tags/path_helper.rb +0 -85
  139. data/lib/locomotive/previous_liquid/tags/path_to.rb +0 -21
  140. data/lib/locomotive/previous_liquid/tags/seo.rb +0 -72
  141. data/lib/locomotive/previous_liquid/tags/session_assign.rb +0 -39
  142. data/lib/locomotive/previous_liquid/tags/snippet.rb +0 -75
  143. data/lib/locomotive/previous_liquid/tags/with_scope.rb +0 -65
  144. data/spec/fixtures/portfolio/Gemfile +0 -21
  145. data/spec/fixtures/portfolio/app/content_types/messages.yml +0 -57
  146. data/spec/fixtures/portfolio/app/content_types/projects.yml +0 -74
  147. data/spec/fixtures/portfolio/app/views/pages/404.liquid.haml +0 -10
  148. data/spec/fixtures/portfolio/app/views/pages/index.liquid.haml +0 -213
  149. data/spec/fixtures/portfolio/app/views/snippets/footer.liquid.haml +0 -2
  150. data/spec/fixtures/portfolio/config.ru +0 -3
  151. data/spec/fixtures/portfolio/config/deploy.yml +0 -18
  152. data/spec/fixtures/portfolio/config/site.yml +0 -33
  153. data/spec/fixtures/portfolio/config/translations.yml +0 -8
  154. data/spec/fixtures/portfolio/data/messages.yml +0 -1
  155. data/spec/fixtures/portfolio/data/projects.yml +0 -41
  156. data/spec/fixtures/portfolio/icon.png +0 -0
  157. data/spec/fixtures/portfolio/public/javascripts/bootstrap.min.js +0 -6
  158. data/spec/fixtures/portfolio/public/javascripts/cbpAnimatedHeader.js +0 -44
  159. data/spec/fixtures/portfolio/public/javascripts/cbpAnimatedHeader.min.js +0 -11
  160. data/spec/fixtures/portfolio/public/javascripts/classie.js +0 -80
  161. data/spec/fixtures/portfolio/public/javascripts/contact_me.js +0 -65
  162. data/spec/fixtures/portfolio/public/javascripts/freelancer.js +0 -37
  163. data/spec/fixtures/portfolio/public/javascripts/jqBootstrapValidation.js +0 -912
  164. data/spec/fixtures/portfolio/public/samples/portfolio/cabin.png +0 -0
  165. data/spec/fixtures/portfolio/public/samples/portfolio/cake.png +0 -0
  166. data/spec/fixtures/portfolio/public/samples/portfolio/circus.png +0 -0
  167. data/spec/fixtures/portfolio/public/samples/portfolio/game.png +0 -0
  168. data/spec/fixtures/portfolio/public/samples/portfolio/safe.png +0 -0
  169. data/spec/fixtures/portfolio/public/samples/portfolio/submarine.png +0 -0
  170. data/spec/fixtures/portfolio/public/samples/profile.png +0 -0
  171. data/spec/fixtures/portfolio/public/stylesheets/bootstrap.min.css +0 -7
  172. data/spec/fixtures/portfolio/public/stylesheets/freelancer.css +0 -445
  173. data/spec/lib/locomotive/liquid/tags/editable/file_spec.rb +0 -72
  174. data/spec/lib/locomotive/liquid/tags/editable/text_spec.rb +0 -85
  175. data/spec/lib/locomotive/liquid/tags/extends_spec.rb +0 -58
  176. data/vendor/assets/javascripts/locomotive/editable_field.js +0 -50
  177. data/vendor/assets/javascripts/locomotive/form_submit_notification.js +0 -39
  178. data/vendor/assets/javascripts/locomotive/slugify.js +0 -47
@@ -1,41 +0,0 @@
1
- - "Sample 1":
2
- image: "http://placehold.it/900x650" # Path to a file in the public/samples folder or to a remote and external file.
3
- description: "<p>Quas eveniet nostrum consequatur. Quod est quis sequi numquam. Minima dicta aut excepturi qui et at maiores. Non quia autem totam. Dolorem aliquam aut ut sit itaque voluptates.</p>"
4
- client: Acme Corp
5
- date: 2014/10/15
6
- category: Interface
7
-
8
- - "Sample 2":
9
- image: "http://placehold.it/900x650" # Path to a file in the public/samples folder or to a remote and external file.
10
- description: "<p>Sint voluptas impedit cum aut nulla et. Omnis ratione quisquam laudantium. Sed fugiat sed error. Incidunt ut aspernatur quidem debitis ad voluptatibus voluptas porro.</p>"
11
- client: Acme Corp
12
- date: 2014/10/15
13
- category: Interface
14
-
15
- # - "Sample 3":
16
- # image: "http://placehold.it/900x650" # Path to a file in the public/samples folder or to a remote and external file.
17
- # description: "<p>Eveniet repellat sit minus eaque dolores consequatur. Dolores est iure omnis sit veniam natus. Veniam autem molestiae consequatur doloribus. Blanditiis molestias non voluptatem cumque earum excepturi nemo. Aut quia dolorem expedita.</p>"
18
- # client: Acme Corp
19
- # date: 2014/10/15
20
- # category: Interface
21
-
22
- # - "Sample 4":
23
- # image: "http://placehold.it/900x650" # Path to a file in the public/samples folder or to a remote and external file.
24
- # description: "<p>Doloremque ut rem eos hic sit culpa labore. Delectus officiis quo occaecati mollitia rerum qui. Non voluptatem accusamus modi qui aut. Impedit et deleniti aut fugit voluptatum esse. Et ut et quibusdam optio debitis.</p>"
25
- # client: Acme Corp
26
- # date: 2014/10/15
27
- # category: Interface
28
-
29
- # - "Sample 5":
30
- # image: "http://placehold.it/900x650" # Path to a file in the public/samples folder or to a remote and external file.
31
- # description: "<p>Eveniet repellat sit minus eaque dolores consequatur. Dolores est iure omnis sit veniam natus. Veniam autem molestiae consequatur doloribus. Blanditiis molestias non voluptatem cumque earum excepturi nemo. Aut quia dolorem expedita.</p>"
32
- # client: Acme Corp
33
- # date: 2014/10/15
34
- # category: Interface
35
-
36
- # - "Sample 6":
37
- # image: "http://placehold.it/900x650" # Path to a file in the public/samples folder or to a remote and external file.
38
- # description: "<p>Doloremque ut rem eos hic sit culpa labore. Delectus officiis quo occaecati mollitia rerum qui. Non voluptatem accusamus modi qui aut. Impedit et deleniti aut fugit voluptatum esse. Et ut et quibusdam optio debitis.</p>"
39
- # client: Acme Corp
40
- # date: 2014/10/15
41
- # category: Interface
@@ -1,6 +0,0 @@
1
- /*!
2
- * Bootstrap v3.2.0 (http://getbootstrap.com)
3
- * Copyright 2011-2014 Twitter, Inc.
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
- */
6
- if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f+', [role="menu"], [role="listbox"]',g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$backdrop=this.isShown=null,this.scrollbarWidth=0,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.2.0",c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.$body.addClass("modal-open"),this.setScrollbar(),this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(c.$body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one("bsTransitionEnd",function(){c.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(300):c.$element.trigger("focus").trigger(e)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.$body.removeClass("modal-open"),this.resetScrollbar(),this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;if(this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;e?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(150):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var f=function(){c.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",f).emulateTransitionEnd(150):f()}else b&&b()},c.prototype.checkScrollbar=function(){document.body.clientWidth>=window.innerWidth||(this.scrollbarWidth=this.scrollbarWidth||this.measureScrollbar())},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.scrollbarWidth&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.2.0",c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var c=a.contains(document.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!c)return;var d=this,e=this.tip(),f=this.getUID(this.type);this.setContent(),e.attr("id",f),this.$element.attr("aria-describedby",f),this.options.animation&&e.addClass("fade");var g="function"==typeof this.options.placement?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,i=h.test(g);i&&(g=g.replace(h,"")||"top"),e.detach().css({top:0,left:0,display:"block"}).addClass(g).data("bs."+this.type,this),this.options.container?e.appendTo(this.options.container):e.insertAfter(this.$element);var j=this.getPosition(),k=e[0].offsetWidth,l=e[0].offsetHeight;if(i){var m=g,n=this.$element.parent(),o=this.getPosition(n);g="bottom"==g&&j.top+j.height+l-o.scroll>o.height?"top":"top"==g&&j.top-o.scroll-l<0?"bottom":"right"==g&&j.right+k>o.width?"left":"left"==g&&j.left-k<o.left?"right":g,e.removeClass(m).addClass(g)}var p=this.getCalculatedOffset(g,j,k,l);this.applyPlacement(p,g);var q=function(){d.$element.trigger("shown.bs."+d.type),d.hoverState=null};a.support.transition&&this.$tip.hasClass("fade")?e.one("bsTransitionEnd",q).emulateTransitionEnd(150):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top=b.top+g,b.left=b.left+h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=k.left?2*k.left-e+i:2*k.top-f+j,m=k.left?"left":"top",n=k.left?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(l,d[0][n],m)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.removeAttr("aria-describedby"),this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one("bsTransitionEnd",b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName;return a.extend({},"function"==typeof c.getBoundingClientRect?c.getBoundingClientRect():null,{scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop(),width:d?a(window).width():b.outerWidth(),height:d?a(window).height():b.outerHeight()},d?{top:0,left:0}:b.offset())},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.2.0",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").empty()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.2.0",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.2.0",c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.closest("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},c.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one("bsTransitionEnd",e).emulateTransitionEnd(150):e(),f.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(c){c.preventDefault(),b.call(a(this),"show")})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.2.0",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=a(document).height(),d=this.$target.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=b-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){null!=this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:b-this.$element.height()-h}))}}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},d.offsetBottom&&(d.offset.bottom=d.offsetBottom),d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
@@ -1,44 +0,0 @@
1
- /**
2
- * cbpAnimatedHeader.js v1.0.0
3
- * http://www.codrops.com
4
- *
5
- * Licensed under the MIT license.
6
- * http://www.opensource.org/licenses/mit-license.php
7
- *
8
- * Copyright 2013, Codrops
9
- * http://www.codrops.com
10
- */
11
- var cbpAnimatedHeader = (function() {
12
-
13
- var docElem = document.documentElement,
14
- header = document.querySelector( '.navbar-fixed-top' ),
15
- didScroll = false,
16
- changeHeaderOn = 300;
17
-
18
- function init() {
19
- window.addEventListener( 'scroll', function( event ) {
20
- if( !didScroll ) {
21
- didScroll = true;
22
- setTimeout( scrollPage, 250 );
23
- }
24
- }, false );
25
- }
26
-
27
- function scrollPage() {
28
- var sy = scrollY();
29
- if ( sy >= changeHeaderOn ) {
30
- classie.add( header, 'navbar-shrink' );
31
- }
32
- else {
33
- classie.remove( header, 'navbar-shrink' );
34
- }
35
- didScroll = false;
36
- }
37
-
38
- function scrollY() {
39
- return window.pageYOffset || docElem.scrollTop;
40
- }
41
-
42
- init();
43
-
44
- })();
@@ -1,11 +0,0 @@
1
- /**
2
- * cbpAnimatedHeader.min.js v1.0.0
3
- * http://www.codrops.com
4
- *
5
- * Licensed under the MIT license.
6
- * http://www.opensource.org/licenses/mit-license.php
7
- *
8
- * Copyright 2013, Codrops
9
- * http://www.codrops.com
10
- */
11
- var cbpAnimatedHeader=(function(){var b=document.documentElement,g=document.querySelector(".cbp-af-header"),e=false,a=300;function f(){window.addEventListener("scroll",function(h){if(!e){e=true;setTimeout(d,250)}},false)}function d(){var h=c();if(h>=a){classie.add(g,"cbp-af-header-shrink")}else{classie.remove(g,"cbp-af-header-shrink")}e=false}function c(){return window.pageYOffset||b.scrollTop}f()})();
@@ -1,80 +0,0 @@
1
- /*!
2
- * classie - class helper functions
3
- * from bonzo https://github.com/ded/bonzo
4
- *
5
- * classie.has( elem, 'my-class' ) -> true/false
6
- * classie.add( elem, 'my-new-class' )
7
- * classie.remove( elem, 'my-unwanted-class' )
8
- * classie.toggle( elem, 'my-class' )
9
- */
10
-
11
- /*jshint browser: true, strict: true, undef: true */
12
- /*global define: false */
13
-
14
- ( function( window ) {
15
-
16
- 'use strict';
17
-
18
- // class helper functions from bonzo https://github.com/ded/bonzo
19
-
20
- function classReg( className ) {
21
- return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
22
- }
23
-
24
- // classList support for class management
25
- // altho to be fair, the api sucks because it won't accept multiple classes at once
26
- var hasClass, addClass, removeClass;
27
-
28
- if ( 'classList' in document.documentElement ) {
29
- hasClass = function( elem, c ) {
30
- return elem.classList.contains( c );
31
- };
32
- addClass = function( elem, c ) {
33
- elem.classList.add( c );
34
- };
35
- removeClass = function( elem, c ) {
36
- elem.classList.remove( c );
37
- };
38
- }
39
- else {
40
- hasClass = function( elem, c ) {
41
- return classReg( c ).test( elem.className );
42
- };
43
- addClass = function( elem, c ) {
44
- if ( !hasClass( elem, c ) ) {
45
- elem.className = elem.className + ' ' + c;
46
- }
47
- };
48
- removeClass = function( elem, c ) {
49
- elem.className = elem.className.replace( classReg( c ), ' ' );
50
- };
51
- }
52
-
53
- function toggleClass( elem, c ) {
54
- var fn = hasClass( elem, c ) ? removeClass : addClass;
55
- fn( elem, c );
56
- }
57
-
58
- var classie = {
59
- // full names
60
- hasClass: hasClass,
61
- addClass: addClass,
62
- removeClass: removeClass,
63
- toggleClass: toggleClass,
64
- // short names
65
- has: hasClass,
66
- add: addClass,
67
- remove: removeClass,
68
- toggle: toggleClass
69
- };
70
-
71
- // transport
72
- if ( typeof define === 'function' && define.amd ) {
73
- // AMD
74
- define( classie );
75
- } else {
76
- // browser global
77
- window.classie = classie;
78
- }
79
-
80
- })( window );
@@ -1,65 +0,0 @@
1
- $(function() {
2
-
3
- $("input,textarea").jqBootstrapValidation({
4
- preventSubmit: true,
5
- submitError: function($form, event, errors) {
6
- // additional error messages or events
7
- },
8
- submitSuccess: function($form, event) {
9
- event.preventDefault(); // prevent default submit behaviour
10
- // get values from FORM
11
- var name = $("input#name").val();
12
- var email = $("input#email").val();
13
- var phone = $("input#phone").val();
14
- var message = $("textarea#message").val();
15
- var firstName = name; // For Success/Failure Message
16
- // Check for white space in name for Success/Fail message
17
- if (firstName.indexOf(' ') >= 0) {
18
- firstName = name.split(' ').slice(0, -1).join(' ');
19
- }
20
- $.ajax({
21
- url: $form.attr('action'),
22
- type: "POST",
23
- data: $form.serialize(),
24
- cache: false,
25
- success: function() {
26
- // Success message
27
- $('#success').html("<div class='alert alert-success'>");
28
- $('#success > .alert-success').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>&times;")
29
- .append("</button>");
30
- $('#success > .alert-success')
31
- .append("<strong>Your message has been sent. </strong>");
32
- $('#success > .alert-success')
33
- .append('</div>');
34
-
35
- //clear all fields
36
- $('#contactForm').trigger("reset");
37
- },
38
- error: function() {
39
- // Fail message
40
- $('#success').html("<div class='alert alert-danger'>");
41
- $('#success > .alert-danger').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>&times;")
42
- .append("</button>");
43
- $('#success > .alert-danger').append("<strong>Sorry " + firstName + ", it seems that my mail server is not responding. Please try again later!");
44
- $('#success > .alert-danger').append('</div>');
45
- //clear all fields
46
- $('#contactForm').trigger("reset");
47
- },
48
- })
49
- },
50
- filter: function() {
51
- return $(this).is(":visible");
52
- },
53
- });
54
-
55
- $("a[data-toggle=\"tab\"]").click(function(e) {
56
- e.preventDefault();
57
- $(this).tab("show");
58
- });
59
- });
60
-
61
-
62
- /*When clicking on Full hide fail/success boxes */
63
- $('#name').focus(function() {
64
- $('#success').html('');
65
- });
@@ -1,37 +0,0 @@
1
- /*!
2
- * Start Bootstrap - Freelancer Bootstrap Theme (http://startbootstrap.com)
3
- * Code licensed under the Apache License v2.0.
4
- * For details, see http://www.apache.org/licenses/LICENSE-2.0.
5
- */
6
-
7
- // jQuery for page scrolling feature - requires jQuery Easing plugin
8
- $(function() {
9
- $('.page-scroll a').bind('click', function(event) {
10
- var $anchor = $(this);
11
- $('html, body').stop().animate({
12
- scrollTop: $($anchor.attr('href')).offset().top
13
- }, 1500, 'easeInOutExpo');
14
- event.preventDefault();
15
- });
16
- });
17
-
18
- // Floating label headings for the contact form
19
- $(function() {
20
- $("body").on("input propertychange", ".floating-label-form-group", function(e) {
21
- $(this).toggleClass("floating-label-form-group-with-value", !! $(e.target).val());
22
- }).on("focus", ".floating-label-form-group", function() {
23
- $(this).addClass("floating-label-form-group-with-focus");
24
- }).on("blur", ".floating-label-form-group", function() {
25
- $(this).removeClass("floating-label-form-group-with-focus");
26
- });
27
- });
28
-
29
- // Highlight the top nav as scrolling occurs
30
- $('body').scrollspy({
31
- target: '.navbar-fixed-top'
32
- })
33
-
34
- // Closes the Responsive Menu on Menu Item Click
35
- $('.navbar-collapse ul li a').click(function() {
36
- $('.navbar-toggle:visible').click();
37
- });
@@ -1,912 +0,0 @@
1
- /* jqBootstrapValidation
2
- * A plugin for automating validation on Twitter Bootstrap formatted forms.
3
- *
4
- * v1.3.6
5
- *
6
- * License: MIT <http://opensource.org/licenses/mit-license.php> - see LICENSE file
7
- *
8
- * http://ReactiveRaven.github.com/jqBootstrapValidation/
9
- */
10
-
11
- (function( $ ){
12
-
13
- var createdElements = [];
14
-
15
- var defaults = {
16
- options: {
17
- prependExistingHelpBlock: false,
18
- sniffHtml: true, // sniff for 'required', 'maxlength', etc
19
- preventSubmit: true, // stop the form submit event from firing if validation fails
20
- submitError: false, // function called if there is an error when trying to submit
21
- submitSuccess: false, // function called just before a successful submit event is sent to the server
22
- semanticallyStrict: false, // set to true to tidy up generated HTML output
23
- autoAdd: {
24
- helpBlocks: true
25
- },
26
- filter: function () {
27
- // return $(this).is(":visible"); // only validate elements you can see
28
- return true; // validate everything
29
- }
30
- },
31
- methods: {
32
- init : function( options ) {
33
-
34
- var settings = $.extend(true, {}, defaults);
35
-
36
- settings.options = $.extend(true, settings.options, options);
37
-
38
- var $siblingElements = this;
39
-
40
- var uniqueForms = $.unique(
41
- $siblingElements.map( function () {
42
- return $(this).parents("form")[0];
43
- }).toArray()
44
- );
45
-
46
- $(uniqueForms).bind("submit", function (e) {
47
- var $form = $(this);
48
- var warningsFound = 0;
49
- var $inputs = $form.find("input,textarea,select").not("[type=submit],[type=image]").filter(settings.options.filter);
50
- $inputs.trigger("submit.validation").trigger("validationLostFocus.validation");
51
-
52
- $inputs.each(function (i, el) {
53
- var $this = $(el),
54
- $controlGroup = $this.parents(".control-group").first();
55
- if (
56
- $controlGroup.hasClass("warning")
57
- ) {
58
- $controlGroup.removeClass("warning").addClass("error");
59
- warningsFound++;
60
- }
61
- });
62
-
63
- $inputs.trigger("validationLostFocus.validation");
64
-
65
- if (warningsFound) {
66
- if (settings.options.preventSubmit) {
67
- e.preventDefault();
68
- }
69
- $form.addClass("error");
70
- if ($.isFunction(settings.options.submitError)) {
71
- settings.options.submitError($form, e, $inputs.jqBootstrapValidation("collectErrors", true));
72
- }
73
- } else {
74
- $form.removeClass("error");
75
- if ($.isFunction(settings.options.submitSuccess)) {
76
- settings.options.submitSuccess($form, e);
77
- }
78
- }
79
- });
80
-
81
- return this.each(function(){
82
-
83
- // Get references to everything we're interested in
84
- var $this = $(this),
85
- $controlGroup = $this.parents(".control-group").first(),
86
- $helpBlock = $controlGroup.find(".help-block").first(),
87
- $form = $this.parents("form").first(),
88
- validatorNames = [];
89
-
90
- // create message container if not exists
91
- if (!$helpBlock.length && settings.options.autoAdd && settings.options.autoAdd.helpBlocks) {
92
- $helpBlock = $('<div class="help-block" />');
93
- $controlGroup.find('.controls').append($helpBlock);
94
- createdElements.push($helpBlock[0]);
95
- }
96
-
97
- // =============================================================
98
- // SNIFF HTML FOR VALIDATORS
99
- // =============================================================
100
-
101
- // *snort sniff snuffle*
102
-
103
- if (settings.options.sniffHtml) {
104
- var message = "";
105
- // ---------------------------------------------------------
106
- // PATTERN
107
- // ---------------------------------------------------------
108
- if ($this.attr("pattern") !== undefined) {
109
- message = "Not in the expected format<!-- data-validation-pattern-message to override -->";
110
- if ($this.data("validationPatternMessage")) {
111
- message = $this.data("validationPatternMessage");
112
- }
113
- $this.data("validationPatternMessage", message);
114
- $this.data("validationPatternRegex", $this.attr("pattern"));
115
- }
116
- // ---------------------------------------------------------
117
- // MAX
118
- // ---------------------------------------------------------
119
- if ($this.attr("max") !== undefined || $this.attr("aria-valuemax") !== undefined) {
120
- var max = ($this.attr("max") !== undefined ? $this.attr("max") : $this.attr("aria-valuemax"));
121
- message = "Too high: Maximum of '" + max + "'<!-- data-validation-max-message to override -->";
122
- if ($this.data("validationMaxMessage")) {
123
- message = $this.data("validationMaxMessage");
124
- }
125
- $this.data("validationMaxMessage", message);
126
- $this.data("validationMaxMax", max);
127
- }
128
- // ---------------------------------------------------------
129
- // MIN
130
- // ---------------------------------------------------------
131
- if ($this.attr("min") !== undefined || $this.attr("aria-valuemin") !== undefined) {
132
- var min = ($this.attr("min") !== undefined ? $this.attr("min") : $this.attr("aria-valuemin"));
133
- message = "Too low: Minimum of '" + min + "'<!-- data-validation-min-message to override -->";
134
- if ($this.data("validationMinMessage")) {
135
- message = $this.data("validationMinMessage");
136
- }
137
- $this.data("validationMinMessage", message);
138
- $this.data("validationMinMin", min);
139
- }
140
- // ---------------------------------------------------------
141
- // MAXLENGTH
142
- // ---------------------------------------------------------
143
- if ($this.attr("maxlength") !== undefined) {
144
- message = "Too long: Maximum of '" + $this.attr("maxlength") + "' characters<!-- data-validation-maxlength-message to override -->";
145
- if ($this.data("validationMaxlengthMessage")) {
146
- message = $this.data("validationMaxlengthMessage");
147
- }
148
- $this.data("validationMaxlengthMessage", message);
149
- $this.data("validationMaxlengthMaxlength", $this.attr("maxlength"));
150
- }
151
- // ---------------------------------------------------------
152
- // MINLENGTH
153
- // ---------------------------------------------------------
154
- if ($this.attr("minlength") !== undefined) {
155
- message = "Too short: Minimum of '" + $this.attr("minlength") + "' characters<!-- data-validation-minlength-message to override -->";
156
- if ($this.data("validationMinlengthMessage")) {
157
- message = $this.data("validationMinlengthMessage");
158
- }
159
- $this.data("validationMinlengthMessage", message);
160
- $this.data("validationMinlengthMinlength", $this.attr("minlength"));
161
- }
162
- // ---------------------------------------------------------
163
- // REQUIRED
164
- // ---------------------------------------------------------
165
- if ($this.attr("required") !== undefined || $this.attr("aria-required") !== undefined) {
166
- message = settings.builtInValidators.required.message;
167
- if ($this.data("validationRequiredMessage")) {
168
- message = $this.data("validationRequiredMessage");
169
- }
170
- $this.data("validationRequiredMessage", message);
171
- }
172
- // ---------------------------------------------------------
173
- // NUMBER
174
- // ---------------------------------------------------------
175
- if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "number") {
176
- message = settings.builtInValidators.number.message;
177
- if ($this.data("validationNumberMessage")) {
178
- message = $this.data("validationNumberMessage");
179
- }
180
- $this.data("validationNumberMessage", message);
181
- }
182
- // ---------------------------------------------------------
183
- // EMAIL
184
- // ---------------------------------------------------------
185
- if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "email") {
186
- message = "Not a valid email address<!-- data-validator-validemail-message to override -->";
187
- if ($this.data("validationValidemailMessage")) {
188
- message = $this.data("validationValidemailMessage");
189
- } else if ($this.data("validationEmailMessage")) {
190
- message = $this.data("validationEmailMessage");
191
- }
192
- $this.data("validationValidemailMessage", message);
193
- }
194
- // ---------------------------------------------------------
195
- // MINCHECKED
196
- // ---------------------------------------------------------
197
- if ($this.attr("minchecked") !== undefined) {
198
- message = "Not enough options checked; Minimum of '" + $this.attr("minchecked") + "' required<!-- data-validation-minchecked-message to override -->";
199
- if ($this.data("validationMincheckedMessage")) {
200
- message = $this.data("validationMincheckedMessage");
201
- }
202
- $this.data("validationMincheckedMessage", message);
203
- $this.data("validationMincheckedMinchecked", $this.attr("minchecked"));
204
- }
205
- // ---------------------------------------------------------
206
- // MAXCHECKED
207
- // ---------------------------------------------------------
208
- if ($this.attr("maxchecked") !== undefined) {
209
- message = "Too many options checked; Maximum of '" + $this.attr("maxchecked") + "' required<!-- data-validation-maxchecked-message to override -->";
210
- if ($this.data("validationMaxcheckedMessage")) {
211
- message = $this.data("validationMaxcheckedMessage");
212
- }
213
- $this.data("validationMaxcheckedMessage", message);
214
- $this.data("validationMaxcheckedMaxchecked", $this.attr("maxchecked"));
215
- }
216
- }
217
-
218
- // =============================================================
219
- // COLLECT VALIDATOR NAMES
220
- // =============================================================
221
-
222
- // Get named validators
223
- if ($this.data("validation") !== undefined) {
224
- validatorNames = $this.data("validation").split(",");
225
- }
226
-
227
- // Get extra ones defined on the element's data attributes
228
- $.each($this.data(), function (i, el) {
229
- var parts = i.replace(/([A-Z])/g, ",$1").split(",");
230
- if (parts[0] === "validation" && parts[1]) {
231
- validatorNames.push(parts[1]);
232
- }
233
- });
234
-
235
- // =============================================================
236
- // NORMALISE VALIDATOR NAMES
237
- // =============================================================
238
-
239
- var validatorNamesToInspect = validatorNames;
240
- var newValidatorNamesToInspect = [];
241
-
242
- do // repeatedly expand 'shortcut' validators into their real validators
243
- {
244
- // Uppercase only the first letter of each name
245
- $.each(validatorNames, function (i, el) {
246
- validatorNames[i] = formatValidatorName(el);
247
- });
248
-
249
- // Remove duplicate validator names
250
- validatorNames = $.unique(validatorNames);
251
-
252
- // Pull out the new validator names from each shortcut
253
- newValidatorNamesToInspect = [];
254
- $.each(validatorNamesToInspect, function(i, el) {
255
- if ($this.data("validation" + el + "Shortcut") !== undefined) {
256
- // Are these custom validators?
257
- // Pull them out!
258
- $.each($this.data("validation" + el + "Shortcut").split(","), function(i2, el2) {
259
- newValidatorNamesToInspect.push(el2);
260
- });
261
- } else if (settings.builtInValidators[el.toLowerCase()]) {
262
- // Is this a recognised built-in?
263
- // Pull it out!
264
- var validator = settings.builtInValidators[el.toLowerCase()];
265
- if (validator.type.toLowerCase() === "shortcut") {
266
- $.each(validator.shortcut.split(","), function (i, el) {
267
- el = formatValidatorName(el);
268
- newValidatorNamesToInspect.push(el);
269
- validatorNames.push(el);
270
- });
271
- }
272
- }
273
- });
274
-
275
- validatorNamesToInspect = newValidatorNamesToInspect;
276
-
277
- } while (validatorNamesToInspect.length > 0)
278
-
279
- // =============================================================
280
- // SET UP VALIDATOR ARRAYS
281
- // =============================================================
282
-
283
- var validators = {};
284
-
285
- $.each(validatorNames, function (i, el) {
286
- // Set up the 'override' message
287
- var message = $this.data("validation" + el + "Message");
288
- var hasOverrideMessage = (message !== undefined);
289
- var foundValidator = false;
290
- message =
291
- (
292
- message
293
- ? message
294
- : "'" + el + "' validation failed <!-- Add attribute 'data-validation-" + el.toLowerCase() + "-message' to input to change this message -->"
295
- )
296
- ;
297
-
298
- $.each(
299
- settings.validatorTypes,
300
- function (validatorType, validatorTemplate) {
301
- if (validators[validatorType] === undefined) {
302
- validators[validatorType] = [];
303
- }
304
- if (!foundValidator && $this.data("validation" + el + formatValidatorName(validatorTemplate.name)) !== undefined) {
305
- validators[validatorType].push(
306
- $.extend(
307
- true,
308
- {
309
- name: formatValidatorName(validatorTemplate.name),
310
- message: message
311
- },
312
- validatorTemplate.init($this, el)
313
- )
314
- );
315
- foundValidator = true;
316
- }
317
- }
318
- );
319
-
320
- if (!foundValidator && settings.builtInValidators[el.toLowerCase()]) {
321
-
322
- var validator = $.extend(true, {}, settings.builtInValidators[el.toLowerCase()]);
323
- if (hasOverrideMessage) {
324
- validator.message = message;
325
- }
326
- var validatorType = validator.type.toLowerCase();
327
-
328
- if (validatorType === "shortcut") {
329
- foundValidator = true;
330
- } else {
331
- $.each(
332
- settings.validatorTypes,
333
- function (validatorTemplateType, validatorTemplate) {
334
- if (validators[validatorTemplateType] === undefined) {
335
- validators[validatorTemplateType] = [];
336
- }
337
- if (!foundValidator && validatorType === validatorTemplateType.toLowerCase()) {
338
- $this.data("validation" + el + formatValidatorName(validatorTemplate.name), validator[validatorTemplate.name.toLowerCase()]);
339
- validators[validatorType].push(
340
- $.extend(
341
- validator,
342
- validatorTemplate.init($this, el)
343
- )
344
- );
345
- foundValidator = true;
346
- }
347
- }
348
- );
349
- }
350
- }
351
-
352
- if (! foundValidator) {
353
- $.error("Cannot find validation info for '" + el + "'");
354
- }
355
- });
356
-
357
- // =============================================================
358
- // STORE FALLBACK VALUES
359
- // =============================================================
360
-
361
- $helpBlock.data(
362
- "original-contents",
363
- (
364
- $helpBlock.data("original-contents")
365
- ? $helpBlock.data("original-contents")
366
- : $helpBlock.html()
367
- )
368
- );
369
-
370
- $helpBlock.data(
371
- "original-role",
372
- (
373
- $helpBlock.data("original-role")
374
- ? $helpBlock.data("original-role")
375
- : $helpBlock.attr("role")
376
- )
377
- );
378
-
379
- $controlGroup.data(
380
- "original-classes",
381
- (
382
- $controlGroup.data("original-clases")
383
- ? $controlGroup.data("original-classes")
384
- : $controlGroup.attr("class")
385
- )
386
- );
387
-
388
- $this.data(
389
- "original-aria-invalid",
390
- (
391
- $this.data("original-aria-invalid")
392
- ? $this.data("original-aria-invalid")
393
- : $this.attr("aria-invalid")
394
- )
395
- );
396
-
397
- // =============================================================
398
- // VALIDATION
399
- // =============================================================
400
-
401
- $this.bind(
402
- "validation.validation",
403
- function (event, params) {
404
-
405
- var value = getValue($this);
406
-
407
- // Get a list of the errors to apply
408
- var errorsFound = [];
409
-
410
- $.each(validators, function (validatorType, validatorTypeArray) {
411
- if (value || value.length || (params && params.includeEmpty) || (!!settings.validatorTypes[validatorType].blockSubmit && params && !!params.submitting)) {
412
- $.each(validatorTypeArray, function (i, validator) {
413
- if (settings.validatorTypes[validatorType].validate($this, value, validator)) {
414
- errorsFound.push(validator.message);
415
- }
416
- });
417
- }
418
- });
419
-
420
- return errorsFound;
421
- }
422
- );
423
-
424
- $this.bind(
425
- "getValidators.validation",
426
- function () {
427
- return validators;
428
- }
429
- );
430
-
431
- // =============================================================
432
- // WATCH FOR CHANGES
433
- // =============================================================
434
- $this.bind(
435
- "submit.validation",
436
- function () {
437
- return $this.triggerHandler("change.validation", {submitting: true});
438
- }
439
- );
440
- $this.bind(
441
- [
442
- "keyup",
443
- "focus",
444
- "blur",
445
- "click",
446
- "keydown",
447
- "keypress",
448
- "change"
449
- ].join(".validation ") + ".validation",
450
- function (e, params) {
451
-
452
- var value = getValue($this);
453
-
454
- var errorsFound = [];
455
-
456
- $controlGroup.find("input,textarea,select").each(function (i, el) {
457
- var oldCount = errorsFound.length;
458
- $.each($(el).triggerHandler("validation.validation", params), function (j, message) {
459
- errorsFound.push(message);
460
- });
461
- if (errorsFound.length > oldCount) {
462
- $(el).attr("aria-invalid", "true");
463
- } else {
464
- var original = $this.data("original-aria-invalid");
465
- $(el).attr("aria-invalid", (original !== undefined ? original : false));
466
- }
467
- });
468
-
469
- $form.find("input,select,textarea").not($this).not("[name=\"" + $this.attr("name") + "\"]").trigger("validationLostFocus.validation");
470
-
471
- errorsFound = $.unique(errorsFound.sort());
472
-
473
- // Were there any errors?
474
- if (errorsFound.length) {
475
- // Better flag it up as a warning.
476
- $controlGroup.removeClass("success error").addClass("warning");
477
-
478
- // How many errors did we find?
479
- if (settings.options.semanticallyStrict && errorsFound.length === 1) {
480
- // Only one? Being strict? Just output it.
481
- $helpBlock.html(errorsFound[0] +
482
- ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" ));
483
- } else {
484
- // Multiple? Being sloppy? Glue them together into an UL.
485
- $helpBlock.html("<ul role=\"alert\"><li>" + errorsFound.join("</li><li>") + "</li></ul>" +
486
- ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" ));
487
- }
488
- } else {
489
- $controlGroup.removeClass("warning error success");
490
- if (value.length > 0) {
491
- $controlGroup.addClass("success");
492
- }
493
- $helpBlock.html($helpBlock.data("original-contents"));
494
- }
495
-
496
- if (e.type === "blur") {
497
- $controlGroup.removeClass("success");
498
- }
499
- }
500
- );
501
- $this.bind("validationLostFocus.validation", function () {
502
- $controlGroup.removeClass("success");
503
- });
504
- });
505
- },
506
- destroy : function( ) {
507
-
508
- return this.each(
509
- function() {
510
-
511
- var
512
- $this = $(this),
513
- $controlGroup = $this.parents(".control-group").first(),
514
- $helpBlock = $controlGroup.find(".help-block").first();
515
-
516
- // remove our events
517
- $this.unbind('.validation'); // events are namespaced.
518
- // reset help text
519
- $helpBlock.html($helpBlock.data("original-contents"));
520
- // reset classes
521
- $controlGroup.attr("class", $controlGroup.data("original-classes"));
522
- // reset aria
523
- $this.attr("aria-invalid", $this.data("original-aria-invalid"));
524
- // reset role
525
- $helpBlock.attr("role", $this.data("original-role"));
526
- // remove all elements we created
527
- if (createdElements.indexOf($helpBlock[0]) > -1) {
528
- $helpBlock.remove();
529
- }
530
-
531
- }
532
- );
533
-
534
- },
535
- collectErrors : function(includeEmpty) {
536
-
537
- var errorMessages = {};
538
- this.each(function (i, el) {
539
- var $el = $(el);
540
- var name = $el.attr("name");
541
- var errors = $el.triggerHandler("validation.validation", {includeEmpty: true});
542
- errorMessages[name] = $.extend(true, errors, errorMessages[name]);
543
- });
544
-
545
- $.each(errorMessages, function (i, el) {
546
- if (el.length === 0) {
547
- delete errorMessages[i];
548
- }
549
- });
550
-
551
- return errorMessages;
552
-
553
- },
554
- hasErrors: function() {
555
-
556
- var errorMessages = [];
557
-
558
- this.each(function (i, el) {
559
- errorMessages = errorMessages.concat(
560
- $(el).triggerHandler("getValidators.validation") ? $(el).triggerHandler("validation.validation", {submitting: true}) : []
561
- );
562
- });
563
-
564
- return (errorMessages.length > 0);
565
- },
566
- override : function (newDefaults) {
567
- defaults = $.extend(true, defaults, newDefaults);
568
- }
569
- },
570
- validatorTypes: {
571
- callback: {
572
- name: "callback",
573
- init: function ($this, name) {
574
- return {
575
- validatorName: name,
576
- callback: $this.data("validation" + name + "Callback"),
577
- lastValue: $this.val(),
578
- lastValid: true,
579
- lastFinished: true
580
- };
581
- },
582
- validate: function ($this, value, validator) {
583
- if (validator.lastValue === value && validator.lastFinished) {
584
- return !validator.lastValid;
585
- }
586
-
587
- if (validator.lastFinished === true)
588
- {
589
- validator.lastValue = value;
590
- validator.lastValid = true;
591
- validator.lastFinished = false;
592
-
593
- var rrjqbvValidator = validator;
594
- var rrjqbvThis = $this;
595
- executeFunctionByName(
596
- validator.callback,
597
- window,
598
- $this,
599
- value,
600
- function (data) {
601
- if (rrjqbvValidator.lastValue === data.value) {
602
- rrjqbvValidator.lastValid = data.valid;
603
- if (data.message) {
604
- rrjqbvValidator.message = data.message;
605
- }
606
- rrjqbvValidator.lastFinished = true;
607
- rrjqbvThis.data("validation" + rrjqbvValidator.validatorName + "Message", rrjqbvValidator.message);
608
- // Timeout is set to avoid problems with the events being considered 'already fired'
609
- setTimeout(function () {
610
- rrjqbvThis.trigger("change.validation");
611
- }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst
612
- }
613
- }
614
- );
615
- }
616
-
617
- return false;
618
-
619
- }
620
- },
621
- ajax: {
622
- name: "ajax",
623
- init: function ($this, name) {
624
- return {
625
- validatorName: name,
626
- url: $this.data("validation" + name + "Ajax"),
627
- lastValue: $this.val(),
628
- lastValid: true,
629
- lastFinished: true
630
- };
631
- },
632
- validate: function ($this, value, validator) {
633
- if (""+validator.lastValue === ""+value && validator.lastFinished === true) {
634
- return validator.lastValid === false;
635
- }
636
-
637
- if (validator.lastFinished === true)
638
- {
639
- validator.lastValue = value;
640
- validator.lastValid = true;
641
- validator.lastFinished = false;
642
- $.ajax({
643
- url: validator.url,
644
- data: "value=" + value + "&field=" + $this.attr("name"),
645
- dataType: "json",
646
- success: function (data) {
647
- if (""+validator.lastValue === ""+data.value) {
648
- validator.lastValid = !!(data.valid);
649
- if (data.message) {
650
- validator.message = data.message;
651
- }
652
- validator.lastFinished = true;
653
- $this.data("validation" + validator.validatorName + "Message", validator.message);
654
- // Timeout is set to avoid problems with the events being considered 'already fired'
655
- setTimeout(function () {
656
- $this.trigger("change.validation");
657
- }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst
658
- }
659
- },
660
- failure: function () {
661
- validator.lastValid = true;
662
- validator.message = "ajax call failed";
663
- validator.lastFinished = true;
664
- $this.data("validation" + validator.validatorName + "Message", validator.message);
665
- // Timeout is set to avoid problems with the events being considered 'already fired'
666
- setTimeout(function () {
667
- $this.trigger("change.validation");
668
- }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst
669
- }
670
- });
671
- }
672
-
673
- return false;
674
-
675
- }
676
- },
677
- regex: {
678
- name: "regex",
679
- init: function ($this, name) {
680
- return {regex: regexFromString($this.data("validation" + name + "Regex"))};
681
- },
682
- validate: function ($this, value, validator) {
683
- return (!validator.regex.test(value) && ! validator.negative)
684
- || (validator.regex.test(value) && validator.negative);
685
- }
686
- },
687
- required: {
688
- name: "required",
689
- init: function ($this, name) {
690
- return {};
691
- },
692
- validate: function ($this, value, validator) {
693
- return !!(value.length === 0 && ! validator.negative)
694
- || !!(value.length > 0 && validator.negative);
695
- },
696
- blockSubmit: true
697
- },
698
- match: {
699
- name: "match",
700
- init: function ($this, name) {
701
- var element = $this.parents("form").first().find("[name=\"" + $this.data("validation" + name + "Match") + "\"]").first();
702
- element.bind("validation.validation", function () {
703
- $this.trigger("change.validation", {submitting: true});
704
- });
705
- return {"element": element};
706
- },
707
- validate: function ($this, value, validator) {
708
- return (value !== validator.element.val() && ! validator.negative)
709
- || (value === validator.element.val() && validator.negative);
710
- },
711
- blockSubmit: true
712
- },
713
- max: {
714
- name: "max",
715
- init: function ($this, name) {
716
- return {max: $this.data("validation" + name + "Max")};
717
- },
718
- validate: function ($this, value, validator) {
719
- return (parseFloat(value, 10) > parseFloat(validator.max, 10) && ! validator.negative)
720
- || (parseFloat(value, 10) <= parseFloat(validator.max, 10) && validator.negative);
721
- }
722
- },
723
- min: {
724
- name: "min",
725
- init: function ($this, name) {
726
- return {min: $this.data("validation" + name + "Min")};
727
- },
728
- validate: function ($this, value, validator) {
729
- return (parseFloat(value) < parseFloat(validator.min) && ! validator.negative)
730
- || (parseFloat(value) >= parseFloat(validator.min) && validator.negative);
731
- }
732
- },
733
- maxlength: {
734
- name: "maxlength",
735
- init: function ($this, name) {
736
- return {maxlength: $this.data("validation" + name + "Maxlength")};
737
- },
738
- validate: function ($this, value, validator) {
739
- return ((value.length > validator.maxlength) && ! validator.negative)
740
- || ((value.length <= validator.maxlength) && validator.negative);
741
- }
742
- },
743
- minlength: {
744
- name: "minlength",
745
- init: function ($this, name) {
746
- return {minlength: $this.data("validation" + name + "Minlength")};
747
- },
748
- validate: function ($this, value, validator) {
749
- return ((value.length < validator.minlength) && ! validator.negative)
750
- || ((value.length >= validator.minlength) && validator.negative);
751
- }
752
- },
753
- maxchecked: {
754
- name: "maxchecked",
755
- init: function ($this, name) {
756
- var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]");
757
- elements.bind("click.validation", function () {
758
- $this.trigger("change.validation", {includeEmpty: true});
759
- });
760
- return {maxchecked: $this.data("validation" + name + "Maxchecked"), elements: elements};
761
- },
762
- validate: function ($this, value, validator) {
763
- return (validator.elements.filter(":checked").length > validator.maxchecked && ! validator.negative)
764
- || (validator.elements.filter(":checked").length <= validator.maxchecked && validator.negative);
765
- },
766
- blockSubmit: true
767
- },
768
- minchecked: {
769
- name: "minchecked",
770
- init: function ($this, name) {
771
- var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]");
772
- elements.bind("click.validation", function () {
773
- $this.trigger("change.validation", {includeEmpty: true});
774
- });
775
- return {minchecked: $this.data("validation" + name + "Minchecked"), elements: elements};
776
- },
777
- validate: function ($this, value, validator) {
778
- return (validator.elements.filter(":checked").length < validator.minchecked && ! validator.negative)
779
- || (validator.elements.filter(":checked").length >= validator.minchecked && validator.negative);
780
- },
781
- blockSubmit: true
782
- }
783
- },
784
- builtInValidators: {
785
- email: {
786
- name: "Email",
787
- type: "shortcut",
788
- shortcut: "validemail"
789
- },
790
- validemail: {
791
- name: "Validemail",
792
- type: "regex",
793
- regex: "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\.[A-Za-z]{2,4}",
794
- message: "Not a valid email address<!-- data-validator-validemail-message to override -->"
795
- },
796
- passwordagain: {
797
- name: "Passwordagain",
798
- type: "match",
799
- match: "password",
800
- message: "Does not match the given password<!-- data-validator-paswordagain-message to override -->"
801
- },
802
- positive: {
803
- name: "Positive",
804
- type: "shortcut",
805
- shortcut: "number,positivenumber"
806
- },
807
- negative: {
808
- name: "Negative",
809
- type: "shortcut",
810
- shortcut: "number,negativenumber"
811
- },
812
- number: {
813
- name: "Number",
814
- type: "regex",
815
- regex: "([+-]?\\\d+(\\\.\\\d*)?([eE][+-]?[0-9]+)?)?",
816
- message: "Must be a number<!-- data-validator-number-message to override -->"
817
- },
818
- integer: {
819
- name: "Integer",
820
- type: "regex",
821
- regex: "[+-]?\\\d+",
822
- message: "No decimal places allowed<!-- data-validator-integer-message to override -->"
823
- },
824
- positivenumber: {
825
- name: "Positivenumber",
826
- type: "min",
827
- min: 0,
828
- message: "Must be a positive number<!-- data-validator-positivenumber-message to override -->"
829
- },
830
- negativenumber: {
831
- name: "Negativenumber",
832
- type: "max",
833
- max: 0,
834
- message: "Must be a negative number<!-- data-validator-negativenumber-message to override -->"
835
- },
836
- required: {
837
- name: "Required",
838
- type: "required",
839
- message: "This is required<!-- data-validator-required-message to override -->"
840
- },
841
- checkone: {
842
- name: "Checkone",
843
- type: "minchecked",
844
- minchecked: 1,
845
- message: "Check at least one option<!-- data-validation-checkone-message to override -->"
846
- }
847
- }
848
- };
849
-
850
- var formatValidatorName = function (name) {
851
- return name
852
- .toLowerCase()
853
- .replace(
854
- /(^|\s)([a-z])/g ,
855
- function(m,p1,p2) {
856
- return p1+p2.toUpperCase();
857
- }
858
- )
859
- ;
860
- };
861
-
862
- var getValue = function ($this) {
863
- // Extract the value we're talking about
864
- var value = $this.val();
865
- var type = $this.attr("type");
866
- if (type === "checkbox") {
867
- value = ($this.is(":checked") ? value : "");
868
- }
869
- if (type === "radio") {
870
- value = ($('input[name="' + $this.attr("name") + '"]:checked').length > 0 ? value : "");
871
- }
872
- return value;
873
- };
874
-
875
- function regexFromString(inputstring) {
876
- return new RegExp("^" + inputstring + "$");
877
- }
878
-
879
- /**
880
- * Thanks to Jason Bunting via StackOverflow.com
881
- *
882
- * http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string#answer-359910
883
- * Short link: http://tinyurl.com/executeFunctionByName
884
- **/
885
- function executeFunctionByName(functionName, context /*, args*/) {
886
- var args = Array.prototype.slice.call(arguments).splice(2);
887
- var namespaces = functionName.split(".");
888
- var func = namespaces.pop();
889
- for(var i = 0; i < namespaces.length; i++) {
890
- context = context[namespaces[i]];
891
- }
892
- return context[func].apply(this, args);
893
- }
894
-
895
- $.fn.jqBootstrapValidation = function( method ) {
896
-
897
- if ( defaults.methods[method] ) {
898
- return defaults.methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
899
- } else if ( typeof method === 'object' || ! method ) {
900
- return defaults.methods.init.apply( this, arguments );
901
- } else {
902
- $.error( 'Method ' + method + ' does not exist on jQuery.jqBootstrapValidation' );
903
- return null;
904
- }
905
-
906
- };
907
-
908
- $.jqBootstrapValidation = function (options) {
909
- $(":input").not("[type=image],[type=submit]").jqBootstrapValidation.apply(this,arguments);
910
- };
911
-
912
- })( jQuery );