almanac 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +76 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/images/almanac/background.jpg +0 -0
  5. data/app/assets/images/almanac/icons/compose.png +0 -0
  6. data/app/assets/images/almanac/icons/feed.png +0 -0
  7. data/app/assets/images/almanac/icons/gear.png +0 -0
  8. data/app/assets/images/almanac/icons/glyphicons-halflings-white.png +0 -0
  9. data/app/assets/images/almanac/icons/glyphicons-halflings.png +0 -0
  10. data/app/assets/images/almanac/icons/upload.png +0 -0
  11. data/app/assets/images/almanac/logo.jpg +0 -0
  12. data/app/assets/javascripts/almanac/2-jquery.backstretch.js +357 -0
  13. data/app/assets/javascripts/almanac/3-pixastic.js +637 -0
  14. data/app/assets/javascripts/almanac/4-bootstrap-datepicker.js +454 -0
  15. data/app/assets/javascripts/almanac/5-main.coffee.erb +46 -0
  16. data/app/assets/javascripts/almanac/application.js +16 -0
  17. data/app/assets/stylesheets/almanac/1-datepicker.css +7 -0
  18. data/app/assets/stylesheets/almanac/2-main.css.scss +279 -0
  19. data/app/assets/stylesheets/almanac/application.css +15 -0
  20. data/app/controllers/almanac/application_controller.rb +24 -0
  21. data/app/controllers/almanac/blogs_controller.rb +64 -0
  22. data/app/controllers/almanac/comments_controller.rb +41 -0
  23. data/app/controllers/almanac/images_controller.rb +29 -0
  24. data/app/controllers/almanac/posts_controller.rb +109 -0
  25. data/app/helpers/almanac/application_helper.rb +4 -0
  26. data/app/models/almanac/blog.rb +32 -0
  27. data/app/models/almanac/comment.rb +20 -0
  28. data/app/models/almanac/image.rb +10 -0
  29. data/app/models/almanac/post.rb +55 -0
  30. data/app/views/almanac/blogs/_form.html.haml +76 -0
  31. data/app/views/almanac/blogs/_topbar.html.haml +5 -0
  32. data/app/views/almanac/blogs/edit.html.haml +4 -0
  33. data/app/views/almanac/blogs/new.html.haml +3 -0
  34. data/app/views/almanac/blogs/spam.html.haml +15 -0
  35. data/app/views/almanac/posts/_form.html.haml +52 -0
  36. data/app/views/almanac/posts/_post.html.haml +59 -0
  37. data/app/views/almanac/posts/edit.html.haml +1 -0
  38. data/app/views/almanac/posts/index.html.haml +30 -0
  39. data/app/views/almanac/posts/index.rss.builder +18 -0
  40. data/app/views/almanac/posts/new.html.haml +1 -0
  41. data/app/views/almanac/posts/show.html.haml +4 -0
  42. data/app/views/almanac/posts/tag.html.haml +22 -0
  43. data/app/views/layouts/almanac/_ga.html.haml +10 -0
  44. data/app/views/layouts/almanac/_twitter_follow.html.haml +2 -0
  45. data/app/views/layouts/almanac/application.html.haml +52 -0
  46. data/config/routes.rb +22 -0
  47. data/db/migrate/20121009222451_create_almanac_posts.rb +17 -0
  48. data/db/migrate/20121010033555_create_almanac_blogs.rb +14 -0
  49. data/db/migrate/20121017032059_add_excerpt_to_almanac_posts.rb +11 -0
  50. data/db/migrate/20121017210007_create_almanac_files.rb +15 -0
  51. data/db/migrate/20121017221819_rename_file_to_image.rb +9 -0
  52. data/db/migrate/20121025223403_add_image_fields_to_almanac_blogs.rb +13 -0
  53. data/db/migrate/20121029211221_add_new_fields_to_blogs.rb +15 -0
  54. data/db/migrate/20121029221815_acts_as_taggable_on_migration.rb +30 -0
  55. data/db/migrate/20121101030836_create_almanac_comments.rb +16 -0
  56. data/db/migrate/20121102181941_add_rakismet_fields_to_blogs.rb +13 -0
  57. data/db/migrate/20121102185130_add_spam_to_comments.rb +11 -0
  58. data/db/migrate/20121110000024_add_written_at_to_posts.rb +11 -0
  59. data/db/migrate/20121112205256_add_background_fields_to_blogs.rb +13 -0
  60. data/db/migrate/20121113010557_add_footer_to_almanac_blogs.rb +11 -0
  61. data/db/migrate/20121114043648_change_default_value_for_background_tiles_in_almanac_blogs.rb +9 -0
  62. data/lib/almanac.rb +16 -0
  63. data/lib/almanac/MarkdownParser.rb +18 -0
  64. data/lib/almanac/engine.rb +9 -0
  65. data/lib/almanac/version.rb +3 -0
  66. data/lib/tasks/almanac_tasks.rake +4 -0
  67. data/spec/controllers/blogs_controller_spec.rb +80 -0
  68. data/spec/controllers/comments_controller_spec.rb +51 -0
  69. data/spec/controllers/posts_controller_spec.rb +120 -0
  70. data/spec/dummy/README.rdoc +261 -0
  71. data/spec/dummy/Rakefile +7 -0
  72. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  73. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  74. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  75. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  76. data/spec/dummy/app/models/ability.rb +13 -0
  77. data/spec/dummy/app/models/user.rb +11 -0
  78. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  79. data/spec/dummy/config.ru +4 -0
  80. data/spec/dummy/config/application.rb +59 -0
  81. data/spec/dummy/config/boot.rb +10 -0
  82. data/spec/dummy/config/database.yml +25 -0
  83. data/spec/dummy/config/environment.rb +5 -0
  84. data/spec/dummy/config/environments/development.rb +37 -0
  85. data/spec/dummy/config/environments/production.rb +67 -0
  86. data/spec/dummy/config/environments/test.rb +37 -0
  87. data/spec/dummy/config/initializers/almanac.rb +1 -0
  88. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  89. data/spec/dummy/config/initializers/devise.rb +233 -0
  90. data/spec/dummy/config/initializers/dragonfly.rb +7 -0
  91. data/spec/dummy/config/initializers/inflections.rb +15 -0
  92. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  93. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  94. data/spec/dummy/config/initializers/session_store.rb +8 -0
  95. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  96. data/spec/dummy/config/locales/en.yml +5 -0
  97. data/spec/dummy/config/routes.rb +14 -0
  98. data/spec/dummy/db/migrate/20121009230705_create_almanac_posts.rb +18 -0
  99. data/spec/dummy/db/migrate/20121010033827_create_almanac_blogs.rb +15 -0
  100. data/spec/dummy/db/migrate/20121102224650_add_excerpt_to_almanac_posts.rb +12 -0
  101. data/spec/dummy/db/migrate/20121102224651_create_almanac_files..rb +16 -0
  102. data/spec/dummy/db/migrate/20121102224652_rename_file_to_image.rb +10 -0
  103. data/spec/dummy/db/migrate/20121102224653_add_image_fields_to_almanac_blogs.rb +14 -0
  104. data/spec/dummy/db/migrate/20121102224654_add_new_fields_to_almanac_blogs.rb +16 -0
  105. data/spec/dummy/db/migrate/20121102224655_acts_as_taggable_on_migration.rb +31 -0
  106. data/spec/dummy/db/migrate/20121102224656_create_almanac_comments.rb +17 -0
  107. data/spec/dummy/db/migrate/20121102224657_add_rakismet_fields_to_almanac_blogs.rb +14 -0
  108. data/spec/dummy/db/migrate/20121102224658_add_spam_to_almanac_comments.rb +12 -0
  109. data/spec/dummy/db/migrate/20121106220325_devise_create_users.rb +46 -0
  110. data/spec/dummy/db/migrate/20121114032144_add_written_at_to_almanac_posts.rb +12 -0
  111. data/spec/dummy/db/migrate/20121114032145_add_background_fields_to_almanac_blogs.rb +14 -0
  112. data/spec/dummy/db/migrate/20121114032146_add_footer_to_almanac_blogs.rb +12 -0
  113. data/spec/dummy/db/schema.rb +98 -0
  114. data/spec/dummy/db/test.sqlite3 +0 -0
  115. data/spec/dummy/log/production.log +1 -0
  116. data/spec/dummy/log/test.log +2930 -0
  117. data/spec/dummy/public/404.html +26 -0
  118. data/spec/dummy/public/422.html +26 -0
  119. data/spec/dummy/public/500.html +25 -0
  120. data/spec/dummy/public/favicon.ico +0 -0
  121. data/spec/dummy/script/rails +6 -0
  122. data/spec/factories.rb +72 -0
  123. data/spec/models/blog_spec.rb +16 -0
  124. data/spec/models/comment_spec.rb +35 -0
  125. data/spec/models/post_spec.rb +79 -0
  126. data/spec/spec_helper.rb +37 -0
  127. metadata +485 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,76 @@
1
+ # Almanac
2
+ Almanac is the most elegant mountable blog engine that can be easily hooked up in the existing Rails application.
3
+
4
+ ## Main Features
5
+ - Slick default design that can be easily customized.
6
+ - Markdown for everything.
7
+ - Drafts that make sense.
8
+ - Easy Google Analytics support.
9
+ - Akismet support for spam filtering in comments.
10
+ - Built-in social sharing with Facebook and Twitter.
11
+ - RSS support.
12
+ - Tags for posts.
13
+ - Photo uploading.
14
+ - Complete integration with Devise and CanCan.
15
+ - Tested with RSpec and FactoryGirl
16
+ - Uses haml, scss, CoffeeScript and Bootstrap for views.
17
+
18
+ ## Installation
19
+ ### 1. Add the gem to your `Gemfile`
20
+ ```ruby
21
+ gem "almanac"
22
+ ```
23
+ And run `bundle install`.
24
+
25
+ ### 2. Setup Routes
26
+ To hook up Almanac routes to your current Rails app simply put this code in your `config/routes.rd` file
27
+
28
+ ```ruby
29
+ mount Almanac::Engine, :at => '/blog'
30
+ ```
31
+
32
+ You can obviously setup any route you want. E.g. `/posts` or `/almanac`.
33
+
34
+ ### 3. Run Almanac Migrations
35
+ First off, install Almanac migrations:
36
+
37
+ ```ruby
38
+ bundle exec rake almanac:install:migrations
39
+ ```
40
+
41
+ Then migrate your database:
42
+
43
+ ```ruby
44
+ bundle exec rake db:migrate
45
+ ```
46
+
47
+ ### 4. Devise and CanCan Setup
48
+ Almanac relies on Devise and CanCan properly configured in your app. In short, the `current_user` variable and CanCan `ability.rb` file has to exist. You can setup permissions for the following Almanac models:
49
+
50
+ ```ruby
51
+ can :manage, Almanac::Post
52
+ can :manage, Almanac::Blog
53
+ can :manage, Almanac::Comment
54
+ can :manage, Almanac::Image
55
+ ```
56
+
57
+ These particular rules will allow the specified user to do anything with any Almanac record in the database.
58
+
59
+ ### 5. Specify User Class Name
60
+ Lastly, you'll have to specify the name of your user model. Create a `config/initializers/almanac.rb` file and add the following line there:
61
+
62
+ ```ruby
63
+ Almanac.user_class = "User" # other possibilities: "Author", "Writer", etc.
64
+ ```
65
+
66
+ ## Testing
67
+ Almanac's models and controllers are tested with RSpec and FactoryGirl. Rails engines, such as Almanac, are normally tested with a dummy app that is located inside the 'spec' folder. Migrate your test database from the `spec/dummy` directory:
68
+
69
+ ```ruby
70
+ rake db:migrate RAILS_ENV=test
71
+ ```
72
+
73
+ Go back to the `almanac` directory and run `rspec spec`.
74
+
75
+ ## Contribute
76
+ Fork the repo, do work, test it, pull request.
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Almanac'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,357 @@
1
+ /*! Backstretch - v2.0.1 - 2012-10-01
2
+ * http://srobbin.com/jquery-plugins/backstretch/
3
+ * Copyright (c) 2012 Scott Robbin; Licensed MIT */
4
+
5
+ ;(function ($, window, undefined) {
6
+ 'use strict';
7
+
8
+ /* PLUGIN DEFINITION
9
+ * ========================= */
10
+
11
+ $.fn.backstretch = function (images, options) {
12
+ // We need at least one image
13
+ if (images === undefined || images.length === 0) {
14
+ $.error("No images were supplied for Backstretch");
15
+ }
16
+
17
+ /*
18
+ * Scroll the page one pixel to get the right window height on iOS
19
+ * Pretty harmless for everyone else
20
+ */
21
+ if ($(window).scrollTop() === 0 ) {
22
+ window.scrollTo(0, 0);
23
+ }
24
+
25
+ return this.each(function () {
26
+ var $this = $(this)
27
+ , obj = $this.data('backstretch');
28
+
29
+ // If we've already attached Backstretch to this element, remove the old instance.
30
+ if (obj) {
31
+ // Merge the old options with the new
32
+ options = $.extend(obj.options, options);
33
+
34
+ // Remove the old instance
35
+ obj.destroy(true);
36
+ }
37
+
38
+ obj = new Backstretch(this, images, options);
39
+ $this.data('backstretch', obj);
40
+ });
41
+ };
42
+
43
+ // If no element is supplied, we'll attach to body
44
+ $.backstretch = function (images, options) {
45
+ // Return the instance
46
+ return $('body')
47
+ .backstretch(images, options)
48
+ .data('backstretch');
49
+ };
50
+
51
+ // Custom selector
52
+ $.expr[':'].backstretch = function(elem) {
53
+ return $(elem).data('backstretch') !== undefined;
54
+ };
55
+
56
+ /* DEFAULTS
57
+ * ========================= */
58
+
59
+ $.fn.backstretch.defaults = {
60
+ centeredX: true // Should we center the image on the X axis?
61
+ , centeredY: true // Should we center the image on the Y axis?
62
+ , duration: 5000 // Amount of time in between slides (if slideshow)
63
+ , fade: 0 // Speed of fade transition between slides
64
+ };
65
+
66
+ /* STYLES
67
+ *
68
+ * Baked-in styles that we'll apply to our elements.
69
+ * In an effort to keep the plugin simple, these are not exposed as options.
70
+ * That said, anyone can override these in their own stylesheet.
71
+ * ========================= */
72
+ var styles = {
73
+ wrap: {
74
+ left: 0
75
+ , top: 0
76
+ , overflow: 'hidden'
77
+ , margin: 0
78
+ , padding: 0
79
+ , height: '100%'
80
+ , width: '100%'
81
+ , zIndex: -999999
82
+ }
83
+ , img: {
84
+ position: 'absolute'
85
+ , display: 'none'
86
+ , margin: 0
87
+ , padding: 0
88
+ , border: 'none'
89
+ , width: 'auto'
90
+ , height: 'auto'
91
+ , maxWidth: 'none'
92
+ , zIndex: -999999
93
+ }
94
+ };
95
+
96
+ /* CLASS DEFINITION
97
+ * ========================= */
98
+ var Backstretch = function (container, images, options) {
99
+ this.options = $.extend({}, $.fn.backstretch.defaults, options || {});
100
+
101
+ /* In its simplest form, we allow Backstretch to be called on an image path.
102
+ * e.g. $.backstretch('/path/to/image.jpg')
103
+ * So, we need to turn this back into an array.
104
+ */
105
+ this.images = $.isArray(images) ? images : [images];
106
+
107
+ // Preload images
108
+ $.each(this.images, function () {
109
+ $('<img />')[0].src = this;
110
+ });
111
+
112
+ // Convenience reference to know if the container is body.
113
+ this.isBody = container === document.body;
114
+
115
+ /* We're keeping track of a few different elements
116
+ *
117
+ * Container: the element that Backstretch was called on.
118
+ * Wrap: a DIV that we place the image into, so we can hide the overflow.
119
+ * Root: Convenience reference to help calculate the correct height.
120
+ */
121
+ this.$container = $(container);
122
+ this.$wrap = $('<div class="backstretch"></div>').css(styles.wrap).appendTo(this.$container);
123
+ this.$root = this.isBody ? supportsFixedPosition ? $(window) : $(document) : this.$container;
124
+
125
+ // Non-body elements need some style adjustments
126
+ if (!this.isBody) {
127
+ // If the container is statically positioned, we need to make it relative,
128
+ // and if no zIndex is defined, we should set it to zero.
129
+ var position = this.$container.css('position')
130
+ , zIndex = this.$container.css('zIndex');
131
+
132
+ this.$container.css({
133
+ position: position === 'static' ? 'relative' : position
134
+ , zIndex: zIndex === 'auto' ? 0 : zIndex
135
+ , background: 'none'
136
+ });
137
+
138
+ // Needs a higher z-index
139
+ this.$wrap.css({zIndex: -999998});
140
+ }
141
+
142
+ // Fixed or absolute positioning?
143
+ this.$wrap.css({
144
+ position: this.isBody && supportsFixedPosition ? 'fixed' : 'absolute'
145
+ });
146
+
147
+ // Set the first image
148
+ this.index = 0;
149
+ this.show(this.index);
150
+
151
+ // Listen for resize
152
+ $(window).on('resize.backstretch', $.proxy(this.resize, this))
153
+ .on('orientationchange.backstretch', $.proxy(function () {
154
+ // Need to do this in order to get the right window height
155
+ if (this.isBody && window.pageYOffset === 0) {
156
+ window.scrollTo(0, 1);
157
+ this.resize();
158
+ }
159
+ }, this));
160
+ };
161
+
162
+ /* PUBLIC METHODS
163
+ * ========================= */
164
+ Backstretch.prototype = {
165
+ resize: function () {
166
+ try {
167
+ var bgCSS = {left: 0, top: 0}
168
+ , rootWidth = this.isBody ? this.$root.width() : this.$root.innerWidth()
169
+ , bgWidth = rootWidth
170
+ , rootHeight = this.isBody ? ( window.innerHeight ? window.innerHeight : this.$root.height() ) : this.$root.innerHeight()
171
+ , bgHeight = bgWidth / this.$img.data('ratio')
172
+ , bgOffset;
173
+
174
+ // Make adjustments based on image ratio
175
+ if (bgHeight >= rootHeight) {
176
+ bgOffset = (bgHeight - rootHeight) / 2;
177
+ if(this.options.centeredY) {
178
+ bgCSS.top = '-' + bgOffset + 'px';
179
+ }
180
+ } else {
181
+ bgHeight = rootHeight;
182
+ bgWidth = bgHeight * this.$img.data('ratio');
183
+ bgOffset = (bgWidth - rootWidth) / 2;
184
+ if(this.options.centeredX) {
185
+ bgCSS.left = '-' + bgOffset + 'px';
186
+ }
187
+ }
188
+
189
+ this.$wrap.css({width: rootWidth, height: rootHeight})
190
+ .find('img:not(.deleteable)').css({width: bgWidth, height: bgHeight}).css(bgCSS);
191
+ } catch(err) {
192
+ // IE7 seems to trigger resize before the image is loaded.
193
+ // This try/catch block is a hack to let it fail gracefully.
194
+ }
195
+
196
+ return this;
197
+ }
198
+
199
+ // Show the slide at a certain position
200
+ , show: function (index) {
201
+ // Validate index
202
+ if (Math.abs(index) > this.images.length - 1) {
203
+ return;
204
+ } else {
205
+ this.index = index;
206
+ }
207
+
208
+ // Vars
209
+ var self = this
210
+ , oldImage = self.$wrap.find('img').addClass('deleteable')
211
+ , evt = $.Event('backstretch.show', {
212
+ relatedTarget: self.$container[0]
213
+ });
214
+
215
+ // Pause the slideshow
216
+ clearInterval(self.interval);
217
+
218
+ // New image
219
+ self.$img = $('<img />')
220
+ .css(styles.img)
221
+ .bind('load', function (e) {
222
+ var imgWidth = this.width || $(e.target).width()
223
+ , imgHeight = this.height || $(e.target).height();
224
+
225
+ // Save the ratio
226
+ $(this).data('ratio', imgWidth / imgHeight);
227
+
228
+ // Resize
229
+ self.resize();
230
+
231
+ // Show the image, then delete the old one
232
+ // "speed" option has been deprecated, but we want backwards compatibilty
233
+ $(this).fadeIn(self.options.speed || self.options.fade, function () {
234
+ oldImage.remove();
235
+
236
+ // Resume the slideshow
237
+ if (!self.paused) {
238
+ self.cycle();
239
+ }
240
+
241
+ // Trigger the event
242
+ self.$container.trigger(evt);
243
+ });
244
+ })
245
+ .appendTo(self.$wrap);
246
+
247
+ // Hack for IE img onload event
248
+ self.$img.attr('src', self.images[index]);
249
+ return self;
250
+ }
251
+
252
+ , next: function () {
253
+ // Next slide
254
+ return this.show(this.index < this.images.length - 1 ? this.index + 1 : 0);
255
+ }
256
+
257
+ , prev: function () {
258
+ // Previous slide
259
+ return this.show(this.index === 0 ? this.images.length - 1 : this.index - 1);
260
+ }
261
+
262
+ , pause: function () {
263
+ // Pause the slideshow
264
+ this.paused = true;
265
+ return this;
266
+ }
267
+
268
+ , resume: function () {
269
+ // Resume the slideshow
270
+ this.paused = false;
271
+ this.next();
272
+ return this;
273
+ }
274
+
275
+ , cycle: function () {
276
+ // Start/resume the slideshow
277
+ if(this.images.length > 1) {
278
+ // Clear the interval, just in case
279
+ clearInterval(this.interval);
280
+
281
+ this.interval = setInterval($.proxy(function () {
282
+ // Check for paused slideshow
283
+ if (!this.paused) {
284
+ this.next();
285
+ }
286
+ }, this), this.options.duration);
287
+ }
288
+ return this;
289
+ }
290
+
291
+ , destroy: function (preserveBackground) {
292
+ // Stop the resize events
293
+ $(window).off('resize.backstretch orientationchange.backstretch');
294
+
295
+ // Clear the interval
296
+ clearInterval(this.interval);
297
+
298
+ // Remove Backstretch
299
+ if(!preserveBackground) {
300
+ this.$wrap.remove();
301
+ }
302
+ this.$container.removeData('backstretch');
303
+ }
304
+ };
305
+
306
+ /* SUPPORTS FIXED POSITION?
307
+ *
308
+ * Based on code from jQuery Mobile 1.1.0
309
+ * http://jquerymobile.com/
310
+ *
311
+ * In a nutshell, we need to figure out if fixed positioning is supported.
312
+ * Unfortunately, this is very difficult to do on iOS, and usually involves
313
+ * injecting content, scrolling the page, etc.. It's ugly.
314
+ * jQuery Mobile uses this workaround. It's not ideal, but works.
315
+ *
316
+ * Modified to detect IE6
317
+ * ========================= */
318
+
319
+ var supportsFixedPosition = (function () {
320
+ var ua = navigator.userAgent
321
+ , platform = navigator.platform
322
+ // Rendering engine is Webkit, and capture major version
323
+ , wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ )
324
+ , wkversion = !!wkmatch && wkmatch[ 1 ]
325
+ , ffmatch = ua.match( /Fennec\/([0-9]+)/ )
326
+ , ffversion = !!ffmatch && ffmatch[ 1 ]
327
+ , operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ )
328
+ , omversion = !!operammobilematch && operammobilematch[ 1 ]
329
+ , iematch = ua.match( /MSIE ([0-9]+)/ )
330
+ , ieversion = !!iematch && iematch[ 1 ];
331
+
332
+ return !(
333
+ // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
334
+ ((platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534) ||
335
+
336
+ // Opera Mini
337
+ (window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]") ||
338
+ (operammobilematch && omversion < 7458) ||
339
+
340
+ //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
341
+ (ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533) ||
342
+
343
+ // Firefox Mobile before 6.0 -
344
+ (ffversion && ffversion < 6) ||
345
+
346
+ // WebOS less than 3
347
+ ("palmGetResource" in window && wkversion && wkversion < 534) ||
348
+
349
+ // MeeGo
350
+ (ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1) ||
351
+
352
+ // IE6
353
+ (ieversion && ieversion <= 6)
354
+ );
355
+ }());
356
+
357
+ }(jQuery, window));