bootsy 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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();