bootsy 0.2.1 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e3fa1e33cc474133f385772500c3f1c3c7c622d4
4
- data.tar.gz: 477c5ad9e850218869fc3f68c93fed33ed90d045
3
+ metadata.gz: 10213f792bf2d4b2a8e5a29aa80b63b21ca14e8a
4
+ data.tar.gz: 8786ccb949991086a701ea862ceae43898843bc8
5
5
  SHA512:
6
- metadata.gz: 74a7ec62cbfb633d74b83d4c9e8ba97c74d1d605a2ca4b556acba3e4fad8b66d1d5548a3150196928ac26a96345dbc32ff38dd54c7d1f9e16ff15f194d7b016d
7
- data.tar.gz: cc39af7ac32035dec2c52384d06d0aca6f40bca12926b89f8ee5b963e7282949cbb637854ac8d0eb067456efe0866c79334bf849be0faf09ea1f97d854ef8f0c
6
+ metadata.gz: 46477141879b70d6e6e1989aafe182fb49c70946cb8df87d9b2ccea0ecb1f8111d93574435d46ef1cea1edca58ed01af99e3e8f265bd4a4c5bf64374ea453ff1
7
+ data.tar.gz: e4ef2cb97c4e5b54d4b56e437c8bfff94f909443bb426efaaedf8a651d5703c21b2d53e9b5af4af586d06925440ea531d961dc872cabb6451d632218a63b6962
data/README.md CHANGED
@@ -3,69 +3,76 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/bootsy.png)](http://badge.fury.io/rb/bootsy)
4
4
  [![Build Status](https://secure.travis-ci.org/volmer/bootsy.png?branch=master)](http://travis-ci.org/volmer/bootsy)
5
5
  [![Dependency Status](https://gemnasium.com/volmer/bootsy.png)](https://gemnasium.com/volmer/bootsy)
6
+ [![Code Climate](https://codeclimate.com/github/volmer/bootsy.png)](https://codeclimate.com/github/volmer/bootsy)
7
+ [![Coverage Status](https://coveralls.io/repos/volmer/bootsy/badge.png?branch=master)](https://coveralls.io/r/volmer/bootsy)
6
8
 
7
- *Bootsy* is a WYSIWYG solution for Rails based on [Bootstrap-wysihtml5](https://github.com/jhollingworth/bootstrap-wysihtml5) which includes image uploads via [CarrierWave](https://github.com/jnicklas/carrierwave).
9
+ *Bootsy* is a WYSIWYG solution for Rails based on [Bootstrap-wysihtml5](https://github.com/jhollingworth/bootstrap-wysihtml5) which includes image uploads via [CarrierWave](https://github.com/carrierwaveuploader/carrierwave).
8
10
 
9
11
 
10
12
  ## Requirements
11
13
 
12
- * Ruby >= 1.9.3;
14
+ * Ruby `2.0` or `1.9.3`;
13
15
  * ImageMagick or GraphicsMagick (for MiniMagick);
14
- * Rails ~> 3.2 (Rails 4 support is comming soon);
16
+ * Rails `4.0` (you can get a *temporary* support for Rails `3.2` on [this branch](https://github.com/volmer/bootsy/tree/rails-3.2));
15
17
  * [Twitter Bootstrap](http://twitter.github.com/bootstrap/) properly added on your application.
16
18
 
17
19
 
18
20
  ## Installation
19
21
 
20
22
  1. Add Bootsy to your Gemfile:
21
-
22
- ```ruby
23
- gem 'bootsy'
24
- ```
23
+ ```ruby
24
+ gem 'bootsy'
25
+ ```
25
26
 
26
27
  2. Run the bundle command to install it:
27
-
28
- ```console
29
- bundle install
30
- ```
28
+ ```console
29
+ bundle install
30
+ ```
31
31
 
32
32
  3. Run the install generator:
33
- ```console
34
- rails g bootsy:install
35
- ```
33
+ ```console
34
+ rails g bootsy:install
35
+ ```
36
36
 
37
37
  4. Add and run migrations (if you're using ActiveRecord):
38
- ```console
39
- rake bootsy:install:migrations
40
- rake db:migrate
41
- ```
38
+ ```console
39
+ rake bootsy:install:migrations
40
+ rake db:migrate
41
+ ```
42
42
 
43
43
 
44
44
  ## Usage
45
45
 
46
46
  Just call the brand new method `bootsy_area` in your `FormBuilder` instances, the same way you'd call the basic `textarea` method. Example:
47
+ ```erb
48
+ <%= form_for(@post) do |f| %>
49
+ <%= f.label :title %><br />
50
+ <%= f.text_field :title %>
47
51
 
48
- ```erb
49
- <%= form_for(@post) do |f| %>
50
- <%= f.label :title %><br />
51
- <%= f.text_field :title %>
52
+ <%= f.label :content %><br />
53
+ <%= f.bootsy_area :content %>
52
54
 
53
- <%= f.label :content %><br />
54
- <%= f.bootsy_area :content %>
55
-
56
- <%= f.submit %>
57
- <% end %>
58
- ```
55
+ <%= f.submit %>
56
+ <% end %>
57
+ ```
59
58
 
60
59
  Bootsy will group the uploaded images as galleries and associate them to one of your models. For example, if you have a `Post` model and you want to use `bootsy_area` with it, then you should include the `Bootsy::Container` module:
61
-
62
- ```ruby
63
- class Post < ActiveRecord::Base
64
- include Bootsy::Container
65
-
66
- attr_accessible :content, :title
67
- end
68
- ```
60
+ ```ruby
61
+ class Post < ActiveRecord::Base
62
+ include Bootsy::Container
63
+
64
+ attr_accessible :content, :title
65
+ end
66
+ ```
67
+
68
+ Don't forget to ensure the association of new instances of your model with Bootsy image galleries. For `strong_parameters`, you must allow the parameter `bootsy_image_gallery_id` in your controllers. Example:
69
+ ```ruby
70
+ private
71
+ # Never trust parameters from the scary internet, only allow the white list through.
72
+ def post_params
73
+ params.require(:post).permit(:title, :content, :bootsy_image_gallery_id)
74
+ end
75
+ ```
69
76
 
70
77
  ## Editor options
71
78
 
@@ -75,20 +82,18 @@ It is possible to customize how the editor is displayed and its behavior by pass
75
82
  ### Buttons
76
83
 
77
84
  You can enable/disable the buttons available on the editor. For example, if you want to disable the link and color buttons:
78
-
79
- ```erb
80
- <%= f.bootsy_area :my_attribute, editor_options: {link: false, color: false} %>
81
- ```
85
+ ```erb
86
+ <%= f.bootsy_area :my_attribute, editor_options: {link: false, color: false} %>
87
+ ```
82
88
  Available options are: `:font_styles`, `:emphasis`, `:lists`, `:html`, `:link`, `:image` and `:color`.
83
89
 
84
90
 
85
91
  ### Alert for usaved changes
86
92
 
87
93
  By default, Bootsy alerts for unsaved changes if the user attempts to unload the window. You can disable this behaviour by doing:
88
-
89
- ```erb
90
- <%= f.bootsy_area :my_attribute, editor_options: {alert_unsaved: false} %>
91
- ```
94
+ ```erb
95
+ <%= f.bootsy_area :my_attribute, editor_options: {alert_unsaved: false} %>
96
+ ```
92
97
 
93
98
  ## Uploader
94
99
 
@@ -117,4 +122,4 @@ Do you want to use Bootsy alongside with [SimpleForm](https://github.com/platafo
117
122
 
118
123
  ## License
119
124
 
120
- MIT License. Copyright 2013 Volmer Soares
125
+ MIT License. Copyright 2013 Volmer Soares
data/Rakefile CHANGED
@@ -22,10 +22,13 @@ end
22
22
 
23
23
  Bundler::GemHelper.install_tasks
24
24
 
25
- require "cucumber/rake/task"
25
+ require 'cucumber/rake/task'
26
26
  require 'rspec/core/rake_task'
27
+ require 'coveralls/rake/task'
27
28
 
28
- task :default => [:spec,:run]
29
+ Coveralls::RakeTask.new
30
+
31
+ task default: [:spec,:run, 'coveralls:push']
29
32
 
30
33
  RSpec::Core::RakeTask.new(:spec)
31
34
 
@@ -2,4 +2,6 @@
2
2
  //= require bootsy/wysihtml5
3
3
  //= require bootsy/bootstrap-wysihtml5
4
4
  //= require bootsy/bootsy
5
- //= require_tree .
5
+ //= require bootsy/init
6
+ //= require bootsy/editor_options
7
+ //= require bootsy/translations
@@ -1,233 +1,168 @@
1
- window.Bootsy = (function(){
1
+ window.Bootsy = window.Bootsy || {};
2
2
 
3
- var Bootsy = {caretBookmark: false, unsavedChanges: false, editor: false, editorOptions: {}, eventCallbacks: {'loaded': []}, triggeredEvents: []};
3
+ window.Bootsy.Area = function ($el) {
4
+ var self = this;
4
5
 
5
- Bootsy.translations = {
6
- en: {
7
- alert_unsaved: 'You have unsaved changes.'
6
+ this.progressBar = function () {
7
+ self.imageGalleryModal.find('div.modal-body').html('<div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div>');
8
+ };
9
+
10
+ this.setImageGalleryId = function (id) {
11
+ self.imageGalleryModal.data('bootsy-gallery-id', id)
12
+ $('input.bootsy_image_gallery_id').val(id);
13
+ };
14
+
15
+ this.refreshGallery = function () {
16
+ self.progressBar();
17
+ $.ajax({
18
+ url: '/bootsy/images',
19
+ type: 'GET',
20
+ cache: false,
21
+ data: {
22
+ image_gallery_id: self.imageGalleryModal.data('bootsy-gallery-id')
23
+ },
24
+ dataType: 'json',
25
+ success: function (data) {
26
+ self.imageGalleryModal.find('div.modal-body').html(data.partial);
27
+ self.imageGalleryModal.find('a.refresh-btn').hide();
28
+ },
29
+ error: function (e) {
30
+ alert(Bootsy.translations[self.locale].error);
31
+ self.imageGalleryModal.find('a.refresh-btn').show();
32
+ }
33
+ });
34
+ };
35
+
36
+ this.openImageGallery = function (editor) {
37
+ editor.currentView.element.focus(false);
38
+ self.caretBookmark = editor.composer.selection.getBookmark();
39
+ $('#bootsy_image_gallery').modal('show');
40
+ };
41
+
42
+ this.insertImage = function (image) {
43
+ $('#bootsy_image_gallery').modal('hide');
44
+ self.editor.currentView.element.focus();
45
+ if (self.caretBookmark) {
46
+ self.editor.composer.selection.setBookmark(self.caretBookmark);
47
+ self.caretBookmark = null;
8
48
  }
49
+ self.editor.composer.commands.exec('insertImage', image);
9
50
  };
10
51
 
11
- Bootsy.on = function(eventName, callback){
12
- Bootsy.eventCallbacks[eventName].push(callback);
52
+ this.on = function (eventName, callback) {
53
+ self.eventCallbacks[eventName].push(callback);
13
54
  };
14
55
 
15
- Bootsy.trigger = function(eventName){
16
- var callbacks = Bootsy.eventCallbacks[eventName];
17
- for(i in callbacks){
56
+ this.trigger = function (eventName) {
57
+ var callbacks = self.eventCallbacks[eventName];
58
+ for(i in callbacks) {
18
59
  callbacks[i]();
19
60
  }
20
- Bootsy.triggeredEvents.push(eventName);
61
+ self.triggeredEvents.push(eventName);
21
62
  };
22
63
 
23
- Bootsy.after = function(eventName, callback){
24
- if(Bootsy.triggeredEvents.indexOf(eventName) != -1){
64
+ this.after = function (eventName, callback) {
65
+ if(self.triggeredEvents.indexOf(eventName) != -1) {
25
66
  callback();
26
67
  }else{
27
- Bootsy.on(eventName, callback);
68
+ self.on(eventName, callback);
28
69
  }
29
70
  };
30
-
31
- Bootsy.progressBar = function(element){
32
- element.find('div.modal-body').html('<div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div>');
33
- };
34
71
 
35
- Bootsy.refreshGallery = function(element){
36
- element.find('a.refresh_btn').show().click();
72
+ this.alertUnsavedChanges = function () {
73
+ if (self.unsavedChanges) {
74
+ return Bootsy.translations[self.locale].alert_unsaved;
75
+ }
37
76
  };
38
77
 
39
- Bootsy.openImageGallery = function(editor){
40
- editor.currentView.element.focus(false);
41
- Bootsy.caretBookmark = editor.composer.selection.getBookmark();
42
- $('#bootsy_image_gallery').modal('show');
78
+ this.clear = function () {
79
+ self.editor.clear();
80
+ self.setImageGalleryId('');
43
81
  };
44
82
 
45
- Bootsy.insertImage = function(image, editor){
46
- $('#bootsy_image_gallery').modal('hide');
47
- editor.currentView.element.focus();
48
- if (Bootsy.caretBookmark) {
49
- editor.composer.selection.setBookmark(Bootsy.caretBookmark);
50
- Bootsy.caretBookmark = null;
51
- }
52
- editor.composer.commands.exec("insertImage", image);
83
+ this.locale = $el.data('bootsy-locale') || $('html').attr('lang') || 'en';
84
+ this.caretBookmark = false;
85
+ this.unsavedChanges = false;
86
+ this.editor = false;
87
+ this.eventCallbacks = {'loaded': []};
88
+ this.triggeredEvents = [];
89
+ this.editorOptions = {locale: this.locale};
90
+
91
+ if ($el.data('bootsy-font-styles') === false) this.editorOptions['font-styles'] = false;
92
+ if ($el.data('bootsy-emphasis') === false) this.editorOptions.emphasis = false;
93
+ if ($el.data('bootsy-lists') === false) this.editorOptions.lists = false;
94
+ if ($el.data('bootsy-html') === true) this.editorOptions.html = true;
95
+ if ($el.data('bootsy-link') === false) this.editorOptions.link = false;
96
+ if ($el.data('bootsy-color') === false) this.editorOptions.color = false;
97
+
98
+ if ($el.data('bootsy-alert-unsaved') !== false) {
99
+ window.onbeforeunload = this.alertUnsavedChanges;
53
100
  }
54
101
 
55
- Bootsy.alertUnsavedChanges = function(){
56
- if(Bootsy.unsavedChanges){
57
- return Bootsy.translations[Bootsy.locale].alert_unsaved;
58
- }
59
- };
60
-
61
- Bootsy.ready = function(){
62
- if($('textarea.bootsy_text_area').length > 0){
63
- Bootsy.locale = $('textarea.bootsy_text_area').attr('data-bootsy-locale') || $('html').attr('lang') || 'en';
64
-
65
- var templates = {
66
- customCommand: function(locale, options) {
102
+ $el.closest('form').submit(function (e) {
103
+ self.unsavedChanges = false;
104
+ return true;
105
+ });
106
+
107
+ if ($el.data('bootsy-image') !== false) {
108
+ if ($el.data('bootsy-uploader') !== false) {
109
+ this.editorOptions.image = false;
110
+ this.editorOptions.customCommand = true;
111
+ this.editorOptions.customCommandCallback = this.openImageGallery;
112
+ this.editorOptions.customTemplates = {
113
+ customCommand: function (locale, options) {
67
114
  var size = (options && options.size) ? ' btn-'+options.size : '';
68
115
  return "<li>" +
69
116
  "<a class='btn" + size + "' data-wysihtml5-command='customCommand' title='" + locale.image.insert + "' tabindex='-1'><i class='icon-picture'></i></a>" +
70
117
  "</li>";
71
- },
118
+ }
72
119
  };
73
120
 
74
- Bootsy.editorOptions = {
75
- parserRules: {
76
- classes: {
77
- "wysiwyg-color-silver" : 1,
78
- "wysiwyg-color-gray" : 1,
79
- "wysiwyg-color-white" : 1,
80
- "wysiwyg-color-maroon" : 1,
81
- "wysiwyg-color-red" : 1,
82
- "wysiwyg-color-purple" : 1,
83
- "wysiwyg-color-fuchsia" : 1,
84
- "wysiwyg-color-green" : 1,
85
- "wysiwyg-color-lime" : 1,
86
- "wysiwyg-color-olive" : 1,
87
- "wysiwyg-color-yellow" : 1,
88
- "wysiwyg-color-navy" : 1,
89
- "wysiwyg-color-blue" : 1,
90
- "wysiwyg-color-teal" : 1,
91
- "wysiwyg-color-aqua" : 1,
92
- "wysiwyg-color-orange" : 1,
93
- "wysiwyg-float-left": 1,
94
- "wysiwyg-float-right": 1
95
- },
96
-
97
- tags: {
98
- "b": {},
99
- "i": {},
100
- "br": {},
101
- "ol": {},
102
- "ul": {},
103
- "li": {},
104
- "h1": {},
105
- "h2": {},
106
- "h3": {},
107
- "small": {},
108
- "p": {},
109
- "blockquote": {},
110
- "u": 1,
111
- "cite": {
112
- "check_attributes": {
113
- "title": "alt"
114
- }
115
- },
116
- "img": {
117
- "check_attributes": {
118
- "width": "numbers",
119
- "alt": "alt",
120
- "src": "src",
121
- "height": "numbers"
122
- },
123
- "add_class": {
124
- "align": "align_img"
125
- }
126
- },
127
-
128
- "a": {
129
- set_attributes: {
130
- target: "_blank",
131
- rel: "nofollow"
132
- },
133
- check_attributes: {
134
- href: "url" // important to avoid XSS
135
- }
136
- },
137
- "span": 1,
138
- "div": 1,
139
- // to allow save and edit files with code tag hacks
140
- "code": 1,
141
- "pre": 1
142
- }
143
- },
144
- color: true,
145
- locale: Bootsy.locale,
146
- customTemplates: templates
147
- };
121
+ this.imageGalleryModal = $('#bootsy_image_gallery');
148
122
 
149
- Bootsy.editorOptions.stylesheets = ["/assets/bootsy/bootsy.css"];
150
-
151
- if($('textarea.bootsy_text_area').attr('data-bootsy-image') == 'false'){
152
- Bootsy.editorOptions.image = false;
153
- }else{
154
-
155
- if($('textarea.bootsy_text_area').attr('data-bootsy-uploader') != 'false'){
156
- Bootsy.editorOptions.image = false;
157
- Bootsy.editorOptions.customCommand = true;
158
- Bootsy.editorOptions.customCommandCallback = Bootsy.openImageGallery;
159
-
160
- element = $('#bootsy_image_gallery');
161
-
162
- element.parents('form').after(element);
163
-
164
- element.on('click', 'a.refresh_btn', function(e){
165
- $(this).hide();
166
- Bootsy.progressBar(element);
167
- });
168
-
169
- element.find('a.destroy_btn').click(function(e){
170
- Bootsy.progressBar(element);
171
- });
172
-
173
- element.modal({show: false});
174
- element.on('shown', function(){
175
- Bootsy.refreshGallery(element);
176
- });
177
-
178
- element.on('hide', function() {
179
- Bootsy.editor.currentView.element.focus();
180
- });
181
-
182
- element.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
183
- e.stopPropagation();
184
- });
185
-
186
- element.on('click', 'ul.dropdown-menu a.insert', function(e){
187
- var imagePrefix = "/"+$(this).attr('data-image-size')+"_";
188
- if($(this).attr('data-image-size') == 'original'){
189
- imagePrefix = '/';
190
- }
191
- var img = $(this).parents('li.dropdown').find('img');
192
- var obj = {
193
- src: img.attr('src').replace("/thumb_", imagePrefix),
194
- alt: img.attr('alt').replace("Thumb_", "")
195
- };
196
-
197
- obj.align = $(this).attr('data-position');
198
-
199
- Bootsy.insertImage(obj, Bootsy.editor);
200
- });
201
- }
202
- }
123
+ this.imageGalleryModal.parents('form').after(this.imageGalleryModal);
203
124
 
204
- if($('textarea.bootsy_text_area').attr('data-bootsy-font-styles') == 'false') Bootsy.editorOptions['font-styles'] = false;
205
- if($('textarea.bootsy_text_area').attr('data-bootsy-emphasis') == 'false') Bootsy.editorOptions.emphasis = false;
206
- if($('textarea.bootsy_text_area').attr('data-bootsy-lists') == 'false') Bootsy.editorOptions.lists = false;
207
- if($('textarea.bootsy_text_area').attr('data-bootsy-html') == 'true') Bootsy.editorOptions.html = true;
208
- if($('textarea.bootsy_text_area').attr('data-bootsy-link') == 'false') Bootsy.editorOptions.link = false;
209
- if($('textarea.bootsy_text_area').attr('data-bootsy-color') == 'false') Bootsy.editorOptions.color = false;
125
+ this.imageGalleryModal.on('click', 'a[href="#refresh-gallery"]', this.refreshGallery);
210
126
 
211
- Bootsy.editor = $('textarea.bootsy_text_area').wysihtml5(Bootsy.editorOptions).data("wysihtml5").editor;
127
+ this.imageGalleryModal.find('a.destroy_btn').click(this.progressBar);
212
128
 
213
- if($('textarea.bootsy_text_area').attr('data-bootsy-alert-unsaved') != 'false'){
214
- window.onbeforeunload = Bootsy.alertUnsavedChanges;
215
- }
129
+ this.imageGalleryModal.modal({show: false});
130
+ this.imageGalleryModal.on('shown', this.refreshGallery);
216
131
 
217
- Bootsy.editor.on("change", function(){
218
- Bootsy.unsavedChanges = true;
132
+ this.imageGalleryModal.on('hide', function () {
133
+ self.progressBar();
134
+ self.editor.currentView.element.focus();
219
135
  });
220
136
 
221
- $('textarea.bootsy_text_area').closest('form').submit(function(e){
222
- Bootsy.unsavedChanges = false;
223
- return true;
137
+ this.imageGalleryModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function (e) {
138
+ e.stopPropagation();
224
139
  });
225
140
 
226
- Bootsy.trigger('loaded');
141
+ this.imageGalleryModal.on('click', 'ul.dropdown-menu a.insert', function (e) {
142
+ var imagePrefix = "/"+$(this).attr('data-image-size')+"_";
143
+ if($(this).data('image-size') == 'original') {
144
+ imagePrefix = '/';
145
+ }
146
+ var img = $(this).parents('li.dropdown').find('img');
147
+ var obj = {
148
+ src: img.attr('src').replace("/thumb_", imagePrefix),
149
+ alt: img.attr('alt').replace("Thumb_", "")
150
+ };
151
+
152
+ obj.align = $(this).data('position');
153
+
154
+ self.insertImage(obj);
155
+ });
227
156
  }
228
- };
157
+ } else {
158
+ this.editorOptions.image = false;
159
+ }
160
+
161
+ this.editor = $el.wysihtml5($.extend(Bootsy.editorOptions, this.editorOptions)).data('wysihtml5').editor;
229
162
 
230
- return Bootsy;
231
- }).call(this);
163
+ this.editor.on('change', function () {
164
+ self.unsavedChanges = true;
165
+ });
232
166
 
233
- $(Bootsy.ready);
167
+ this.trigger('loaded');
168
+ };
@@ -0,0 +1,80 @@
1
+ window.Bootsy = window.Bootsy || {};
2
+
3
+ var page_stylesheets = [];
4
+ $('link[rel="stylesheet"]').each(function () {
5
+ page_stylesheets.push($(this).attr('href'));
6
+ });
7
+
8
+ window.Bootsy.editorOptions = {
9
+ parserRules: {
10
+ classes: {
11
+ "wysiwyg-color-silver" : 1,
12
+ "wysiwyg-color-gray" : 1,
13
+ "wysiwyg-color-white" : 1,
14
+ "wysiwyg-color-maroon" : 1,
15
+ "wysiwyg-color-red" : 1,
16
+ "wysiwyg-color-purple" : 1,
17
+ "wysiwyg-color-fuchsia" : 1,
18
+ "wysiwyg-color-green" : 1,
19
+ "wysiwyg-color-lime" : 1,
20
+ "wysiwyg-color-olive" : 1,
21
+ "wysiwyg-color-yellow" : 1,
22
+ "wysiwyg-color-navy" : 1,
23
+ "wysiwyg-color-blue" : 1,
24
+ "wysiwyg-color-teal" : 1,
25
+ "wysiwyg-color-aqua" : 1,
26
+ "wysiwyg-color-orange" : 1,
27
+ "wysiwyg-float-left": 1,
28
+ "wysiwyg-float-right": 1
29
+ },
30
+
31
+ tags: {
32
+ "b": {},
33
+ "i": {},
34
+ "br": {},
35
+ "ol": {},
36
+ "ul": {},
37
+ "li": {},
38
+ "h1": {},
39
+ "h2": {},
40
+ "h3": {},
41
+ "small": {},
42
+ "p": {},
43
+ "blockquote": {},
44
+ "u": 1,
45
+ "cite": {
46
+ "check_attributes": {
47
+ "title": "alt"
48
+ }
49
+ },
50
+ "img": {
51
+ "check_attributes": {
52
+ "width": "numbers",
53
+ "alt": "alt",
54
+ "src": "src",
55
+ "height": "numbers"
56
+ },
57
+ "add_class": {
58
+ "align": "align_img"
59
+ }
60
+ },
61
+
62
+ "a": {
63
+ set_attributes: {
64
+ target: "_blank",
65
+ rel: "nofollow"
66
+ },
67
+ check_attributes: {
68
+ href: "url" // important to avoid XSS
69
+ }
70
+ },
71
+ "span": 1,
72
+ "div": 1,
73
+ // to allow save and edit files with code tag hacks
74
+ "code": 1,
75
+ "pre": 1
76
+ }
77
+ },
78
+ color: true,
79
+ stylesheets: page_stylesheets
80
+ };
@@ -0,0 +1,8 @@
1
+ window.Bootsy = window.Bootsy || {};
2
+
3
+ $(function(){
4
+ Bootsy.areas = [];
5
+ $('textarea.bootsy_text_area').each(function() {
6
+ Bootsy.areas.push(new Bootsy.Area($(this)));
7
+ });
8
+ });
@@ -0,0 +1,8 @@
1
+ window.Bootsy = window.Bootsy || {};
2
+
3
+ window.Bootsy.translations = {
4
+ en: {
5
+ alert_unsaved: 'You have unsaved changes.',
6
+ error: 'Something went very wrong. Please try again later.'
7
+ }
8
+ };
@@ -1,4 +1,7 @@
1
1
  module Bootsy
2
2
  class ApplicationController < ActionController::Base
3
+ # Prevent CSRF attacks by raising an exception.
4
+ # For APIs, you may want to use :null_session instead.
5
+ protect_from_forgery with: :exception
3
6
  end
4
7
  end
@@ -9,9 +9,13 @@ module Bootsy
9
9
  @images = @gallery.images
10
10
 
11
11
  respond_to do |format|
12
- format.js
13
12
  format.html # index.html.erb
14
- format.json { render json: @images }
13
+ format.json do
14
+ partial_str = render_to_string(file: 'bootsy/images/_index',
15
+ formats: [:html],
16
+ locals: { gallery: @gallery })
17
+ render json: { partial: partial_str }
18
+ end
15
19
  end
16
20
  end
17
21
 
@@ -20,12 +24,11 @@ module Bootsy
20
24
  def create
21
25
  @gallery = find_gallery
22
26
  @gallery.save! unless @gallery.persisted?
23
- @image = Image.new params[:image]
27
+ @image = Image.new image_params
24
28
  @image.image_gallery_id = @gallery.id
25
- @images = @gallery.images
26
-
29
+
27
30
  respond_to do |format|
28
- if @image.save
31
+ if @image.save
29
32
  format.js
30
33
  format.json { render json: @image, status: :created, location: @image }
31
34
  else
@@ -34,13 +37,13 @@ module Bootsy
34
37
  end
35
38
  end
36
39
  end
37
-
40
+
38
41
  # DELETE /images/1
39
42
  # DELETE /images/1.json
40
43
  def destroy
41
44
  @image = Image.find(params[:id])
42
45
  @image.destroy
43
-
46
+
44
47
  respond_to do |format|
45
48
  format.js
46
49
  format.html { redirect_to images_url }
@@ -50,11 +53,14 @@ module Bootsy
50
53
 
51
54
  private
52
55
  def find_gallery
53
- begin
54
- return ImageGallery.find params[:image_gallery_id]
55
- rescue
56
- return ImageGallery.new
57
- end
56
+ ImageGallery.find params[:image_gallery_id]
57
+ rescue
58
+ ImageGallery.new
59
+ end
60
+
61
+ # Never trust parameters from the scary internet, only allow the white list through.
62
+ def image_params
63
+ params.require(:image).permit(:image_file)
58
64
  end
59
65
  end
60
66
  end
@@ -1,12 +1,11 @@
1
1
  module Bootsy
2
2
  module ApplicationHelper
3
- def refresh_btn gallery, collection
4
- link_to t('bootsy.action.refresh'), [bootsy, resource_or_nil(gallery), collection], remote: true, :class => 'btn btn-mini refresh_btn'
3
+ def refresh_btn
4
+ link_to t('bootsy.action.refresh'), '#refresh-gallery', class: 'btn btn-mini refresh-btn'
5
5
  end
6
6
 
7
7
  def resource_or_nil resource
8
- resource = nil unless resource.nil? || resource.persisted?
9
- resource
8
+ resource if resource.present? && resource.persisted?
10
9
  end
11
10
  end
12
11
  end
@@ -1,40 +1,35 @@
1
1
  # encoding: utf-8
2
2
  module Bootsy
3
3
  class ImageUploader < CarrierWave::Uploader::Base
4
-
5
4
  include CarrierWave::MiniMagick
6
5
 
7
- include Sprockets::Helpers::RailsHelper
8
- include Sprockets::Helpers::IsolatedHelper
9
-
10
- storage :file
11
-
6
+ storage Bootsy.storage
12
7
 
13
8
  def store_dir
14
9
  "#{Bootsy.store_dir}/#{model.class.to_s.underscore}/#{model.id}"
15
10
  end
16
11
 
17
12
  # Process files as they are uploaded:
18
- process :resize_to_limit => [1160, 2000]
13
+ process resize_to_limit: [1160, 2000]
19
14
 
20
15
  version :large do
21
- process :resize_to_fit => [Bootsy.large_image[:width], Bootsy.large_image[:height]]
16
+ process resize_to_fit: [Bootsy.large_image[:width], Bootsy.large_image[:height]]
22
17
  end
23
18
 
24
19
  version :medium do
25
- process :resize_to_fit => [Bootsy.medium_image[:width], Bootsy.medium_image[:height]]
20
+ process resize_to_fit: [Bootsy.medium_image[:width], Bootsy.medium_image[:height]]
26
21
  end
27
22
 
28
23
  version :small do
29
- process :resize_to_fit => [Bootsy.small_image[:width], Bootsy.small_image[:height]]
24
+ process resize_to_fit: [Bootsy.small_image[:width], Bootsy.small_image[:height]]
30
25
  end
31
26
 
32
27
  version :thumb do
33
- process :resize_to_fill => [60, 60]
28
+ process resize_to_fill: [60, 60]
34
29
  end
35
30
 
36
31
  def extension_white_list
37
32
  %w(jpg jpeg gif png)
38
33
  end
39
34
  end
40
- end
35
+ end
@@ -1,5 +1,5 @@
1
1
  <ul class="thumbnails">
2
- <% images.each do |image| %>
2
+ <% gallery.images.each do |image| %>
3
3
  <li class="span1 dropdown">
4
4
  <%= link_to image_tag(image.image_file.thumb.url), '#', :class => 'thumbnail', data: { toggle: 'dropdown'} %>
5
5
  <ul class="dropdown-menu" role="menu">
@@ -35,8 +35,8 @@
35
35
  <% end %>
36
36
  </ul>
37
37
 
38
- <%= refresh_btn gallery, :images %>
38
+ <%= refresh_btn %>
39
39
 
40
40
  <hr />
41
41
 
42
- <%= render 'bootsy/images/new', {image: (defined?(image) && image.errors.any?) ? image : gallery.images.new } %>
42
+ <%= render 'bootsy/images/new', {image: (defined?(image) && image.errors.any?) ? image : gallery.images.new } %>
@@ -1,12 +1,12 @@
1
- <div class="modal hide fade" id="bootsy_image_gallery">
1
+ <div class="modal hide fade" id="bootsy_image_gallery" data-no-turbolink data-bootsy-gallery-id="<%= container.bootsy_image_gallery_id %>">
2
2
  <div class="modal-header">
3
3
  <button type="button" class="close" data-dismiss="modal">×</button>
4
4
  <h2><%= t 'bootsy.image.p' %></h2>
5
5
  </div>
6
6
  <div class="modal-body">
7
- <%= refresh_btn container.bootsy_image_gallery, :images %>
7
+ <%= refresh_btn %>
8
8
  </div>
9
9
  <div class="modal-footer">
10
10
  <a href="#" class="btn" data-dismiss="modal"><%= t 'bootsy.action.close' %></a>
11
11
  </div>
12
- </div>
12
+ </div>
@@ -1,6 +1,7 @@
1
1
  <h3><%= t 'bootsy.image.new' %></h3>
2
2
 
3
3
  <%= form_for [bootsy, resource_or_nil(image.image_gallery), image], remote: true, html: {:class => 'bootsy form-inline'} do |f| %>
4
+ <%= hidden_field_tag :authenticity_token, form_authenticity_token %>
4
5
  <% if image.errors.any? %>
5
6
  <% image.errors.full_messages.each do |msg| %>
6
7
  <div class="alert alert-error"><%= msg %></div>
@@ -1,3 +1,2 @@
1
- $('input.bootsy_image_gallery_id').val("<%= @gallery.id %>");
2
- $('#bootsy_image_gallery div.modal-body').html("<%= j render 'bootsy/images/index', {images: @images, gallery: @gallery, image: @image}%>");
3
- $('#bootsy_image_gallery a.refresh_btn').hide();
1
+ Bootsy.areas[0].setImageGalleryId(<%= @gallery.id %>);
2
+ Bootsy.areas[0].refreshGallery();
@@ -1 +1 @@
1
- Bootsy.refreshGallery($('#bootsy_image_gallery'));
1
+ Bootsy.areas[0].refreshGallery($('#bootsy_image_gallery'));
data/lib/bootsy.rb CHANGED
@@ -37,7 +37,11 @@ module Bootsy
37
37
  mattr_accessor :original_image
38
38
  @@original_image = {}
39
39
 
40
- # Store directory (inside of 'public')
40
+ # Storage mode
41
+ mattr_accessor :storage
42
+ @@storage = :file
43
+
44
+ # Store directory (inside 'public')
41
45
  mattr_accessor :store_dir
42
46
  @@store_dir = 'uploads'
43
47
 
@@ -4,8 +4,6 @@ module Bootsy
4
4
 
5
5
  mount_uploader :image_file, ImageUploader
6
6
 
7
- attr_accessible :image_file
8
-
9
7
  validates_presence_of :image_file, :image_gallery_id
10
8
  end
11
9
  end
@@ -2,5 +2,7 @@ module Bootsy
2
2
  class ImageGallery < ActiveRecord::Base
3
3
  belongs_to :bootsy_resource, polymorphic: true
4
4
  has_many :images, dependent: :destroy
5
+
6
+ scope :destroy_orphans, ->(time_limit) { where('created_at < ? AND bootsy_resource_id IS NULL', time_limit).destroy_all }
5
7
  end
6
8
  end
@@ -1,20 +1,19 @@
1
1
  require 'active_support/concern'
2
2
 
3
3
  module Bootsy
4
- module Container
4
+ module Container
5
5
 
6
6
  extend ActiveSupport::Concern
7
-
7
+
8
8
  included do
9
9
  class_eval do
10
- has_one :bootsy_image_gallery, :class_name => 'Bootsy::ImageGallery', as: :bootsy_resource, dependent: :destroy
11
- attr_accessible :bootsy_image_gallery_id
10
+ has_one :bootsy_image_gallery, class_name: 'Bootsy::ImageGallery', as: :bootsy_resource, dependent: :destroy
12
11
 
13
12
  def bootsy_image_gallery_id
14
13
  if self.bootsy_image_gallery.nil?
15
- return nil
14
+ nil
16
15
  else
17
- return self.bootsy_image_gallery.id
16
+ self.bootsy_image_gallery.id
18
17
  end
19
18
  end
20
19
 
@@ -29,4 +28,4 @@ module Bootsy
29
28
  end
30
29
  end
31
30
  end
32
- end
31
+ end
@@ -18,7 +18,7 @@ module Bootsy
18
18
  output += self.hidden_field object_name(object), :bootsy_image_gallery_id, class: 'bootsy_image_gallery_id'
19
19
  end
20
20
  end
21
-
21
+
22
22
  output
23
23
  end
24
24
 
@@ -60,4 +60,4 @@ module Bootsy
60
60
  (options[:data] || {}).merge Hash[bootsy_options.map{|k,v|["bootsy-#{k}",v]}]
61
61
  end
62
62
  end
63
- end
63
+ end
@@ -1,3 +1,3 @@
1
1
  module Bootsy
2
- VERSION = "0.2.1"
2
+ VERSION = '1.0.0'
3
3
  end
@@ -14,13 +14,13 @@ module Bootsy
14
14
  def add_assets
15
15
 
16
16
  [{original: 'app/assets/javascripts/application.js',
17
- skip_if: 'require bootsy',
18
- content: "//= require bootsy\n",
19
- position: {before: '//= require_tree .'}},
17
+ skip_if: 'require bootsy',
18
+ content: "\n//= require bootsy",
19
+ position: {after: '//= require jquery_ujs'}},
20
20
  {original: 'app/assets/stylesheets/application.css',
21
- skip_if: 'require bootsy',
22
- content: "*= require bootsy\n",
23
- position: {before: '*/'}}]. each do |params|
21
+ skip_if: 'require bootsy',
22
+ content: "\n *= require bootsy",
23
+ position: {after: '*= require_self'}}]. each do |params|
24
24
 
25
25
  if File.binread(params[:original]).include?(params[:skip_if])
26
26
  say_status 'skipped', "insert into #{params[:original]}", :yellow
@@ -37,4 +37,4 @@ module Bootsy
37
37
 
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -48,7 +48,17 @@ Bootsy.setup do |config|
48
48
  # config.allow_destroy = true
49
49
 
50
50
 
51
- # Store directory (inside of 'public')
51
+ # Storage mode
52
+ # You can change the sorage mode below from :file to :fog if you want
53
+ # to use Amazon S3 and other cloud services. If you do that, please add
54
+ # 'fog' to your Gemfile and create and configure your credentials in an
55
+ # initializer file, as described in Carrierwave's docs:
56
+ # https://github.com/carrierwaveuploader/carrierwave/blob/master/README.md#using-amazon-s3
57
+ #
58
+ # config.storage = :file
59
+
60
+
61
+ # Store directory (inside 'public') for storage = :file
52
62
  # BE CAREFUL! Changing this may break previously uploaded file paths!
53
63
  # config.store_dir = 'uploads'
54
- end
64
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volmer Soares
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-03 00:00:00.000000000 Z
11
+ date: 2013-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mini_magick
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 3.5.0
19
+ version: 3.6.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 3.5.0
26
+ version: 3.6.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: carrierwave
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.5
47
+ version: 1.1.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.5
54
+ version: 1.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec-rails
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - ~>
88
88
  - !ruby/object:Gem::Version
89
- version: '0.9'
89
+ version: '1.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
- version: '0.9'
96
+ version: '1.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: cucumber-rails
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - ~>
116
116
  - !ruby/object:Gem::Version
117
- version: '1.5'
117
+ version: '2.1'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ~>
123
123
  - !ruby/object:Gem::Version
124
- version: '1.5'
124
+ version: '2.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: selenium-webdriver
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: '2.33'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: '2.33'
125
139
  description: A beautiful WYSIWYG editor with image uploads for Rails.
126
140
  email:
127
141
  - volmerius@gmail.com
@@ -129,46 +143,48 @@ executables: []
129
143
  extensions: []
130
144
  extra_rdoc_files: []
131
145
  files:
132
- - app/uploaders/bootsy/image_uploader.rb
133
- - app/views/bootsy/images/index.js.erb
134
- - app/views/bootsy/images/_index.html.erb
135
- - app/views/bootsy/images/destroy.js.erb
136
- - app/views/bootsy/images/create.js.erb
137
- - app/views/bootsy/images/_modal.html.erb
138
- - app/views/bootsy/images/_new.html.erb
139
- - app/controllers/bootsy/application_controller.rb
140
- - app/controllers/bootsy/images_controller.rb
141
- - app/helpers/bootsy/application_helper.rb
142
- - app/assets/javascripts/bootsy.js
146
+ - app/assets/javascripts/bootsy/bootstrap-wysihtml5.js
147
+ - app/assets/javascripts/bootsy/bootsy.js
148
+ - app/assets/javascripts/bootsy/editor_options.js
149
+ - app/assets/javascripts/bootsy/init.js
143
150
  - app/assets/javascripts/bootsy/locales/bootstrap-wysihtml5.pt-BR.js
144
151
  - app/assets/javascripts/bootsy/locales/bootsy.pt-BR.js
145
- - app/assets/javascripts/bootsy/bootsy.js
152
+ - app/assets/javascripts/bootsy/translations.js
146
153
  - app/assets/javascripts/bootsy/wysihtml5.js
147
- - app/assets/javascripts/bootsy/bootstrap-wysihtml5.js
148
- - app/assets/stylesheets/bootsy.css
154
+ - app/assets/javascripts/bootsy.js
149
155
  - app/assets/stylesheets/bootsy/bootstrap-wysihtml5.css
150
156
  - app/assets/stylesheets/bootsy/bootsy.css
157
+ - app/assets/stylesheets/bootsy.css
158
+ - app/controllers/bootsy/application_controller.rb
159
+ - app/controllers/bootsy/images_controller.rb
160
+ - app/helpers/bootsy/application_helper.rb
161
+ - app/uploaders/bootsy/image_uploader.rb
162
+ - app/views/bootsy/images/_index.html.erb
163
+ - app/views/bootsy/images/_modal.html.erb
164
+ - app/views/bootsy/images/_new.html.erb
165
+ - app/views/bootsy/images/create.js.erb
166
+ - app/views/bootsy/images/destroy.js.erb
167
+ - config/bootsy.yml
168
+ - config/cucumber.yml
151
169
  - config/locales/en.yml
152
170
  - config/locales/pt-BR.yml
153
171
  - config/routes.rb
154
- - config/bootsy.yml
155
- - config/cucumber.yml
156
172
  - db/migrate/20120624171333_create_bootsy_images.rb
157
173
  - db/migrate/20120628124845_create_bootsy_image_galleries.rb
174
+ - lib/bootsy/activerecord/image.rb
175
+ - lib/bootsy/activerecord/image_gallery.rb
176
+ - lib/bootsy/container.rb
177
+ - lib/bootsy/core_ext.rb
178
+ - lib/bootsy/engine.rb
179
+ - lib/bootsy/form_builder.rb
180
+ - lib/bootsy/form_helper.rb
181
+ - lib/bootsy/version.rb
182
+ - lib/bootsy.rb
158
183
  - lib/generators/bootsy/install_generator.rb
159
184
  - lib/generators/bootsy/templates/bootsy.rb
160
185
  - lib/generators/bootsy/USAGE
161
- - lib/bootsy.rb
162
186
  - lib/tasks/bootsy_tasks.rake
163
187
  - lib/tasks/cucumber.rake
164
- - lib/bootsy/form_helper.rb
165
- - lib/bootsy/version.rb
166
- - lib/bootsy/activerecord/image_gallery.rb
167
- - lib/bootsy/activerecord/image.rb
168
- - lib/bootsy/core_ext.rb
169
- - lib/bootsy/container.rb
170
- - lib/bootsy/form_builder.rb
171
- - lib/bootsy/engine.rb
172
188
  - MIT-LICENSE
173
189
  - Rakefile
174
190
  - README.md
@@ -1,2 +0,0 @@
1
- $('#bootsy_image_gallery div.modal-body').html("<%= j render 'bootsy/images/index', {images: @images, gallery: @gallery}%>");
2
- $('#bootsy_image_gallery a.refresh_btn').hide();