bootsy 1.2.0 → 2.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: 06d4f6c3c4baaff130fb3321a969e1090706013e
4
- data.tar.gz: 75b66ce2924940d0d4b56a236adfac9de8651c0e
3
+ metadata.gz: 8b7b61a6335378da2590cdd884b0f7b5b7aa5840
4
+ data.tar.gz: c1f5549e531f7e423576602a0f611fb0ff96bb26
5
5
  SHA512:
6
- metadata.gz: e50200981071659ce01e15a40ab22f19b98c0910ec187ffb07cc41830b25f997071afacf374bfbc6532455d10af75a8b9ec3582b2729f5bb3ba87deba6ff1ac4
7
- data.tar.gz: 8e1dd14d053308773af5ca8db3cb7debe28ebf2619d8e7ac3f8f47063881cdcba67d79b5f8fab327246ac95f63871cb234f798c397694e122ff9044b4c2d2b80
6
+ metadata.gz: 6e9ff624b3d22b75b597c461b0161cbfc6346448a0e04dd2f21dc7c9b5ebb10c813ae780d8c00e2c477134c4b7cbbfe1736bad339991bc4e91db0df578ab3ecc
7
+ data.tar.gz: 02ac8fd962645345fac9236095a6ba41a64029706b13e467e1978318f0401356bb254100c56f78b3fbd9de2e0aaf636d15e6a2b3e8f907e2dac297fb8495c390
data/README.md CHANGED
@@ -8,13 +8,15 @@
8
8
 
9
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).
10
10
 
11
+ ![image](https://f.cloud.github.com/assets/301187/1365250/e1b7ba80-3854-11e3-9bfe-8bd1e090aca8.png)
12
+
11
13
 
12
14
  ## Requirements
13
15
 
14
16
  * Ruby `2.0` or `1.9.3`;
15
17
  * ImageMagick or GraphicsMagick (for MiniMagick);
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));
17
- * [Twitter Bootstrap](http://twitter.github.com/bootstrap/) properly added on your application.
18
+ * Rails `4.0`;
19
+ * [Bootstrap `3`](http://getbootstrap.com/) properly added to your application.
18
20
 
19
21
 
20
22
  ## Installation
@@ -31,8 +33,10 @@ bundle install
31
33
 
32
34
  3. Run the install generator:
33
35
  ```console
34
- rails g bootsy:install
36
+ rails generate bootsy:install
35
37
  ```
38
+ It will include the javascripts and stylesheets in the assets pipeline,
39
+ create the `bootsy.rb` initializer and add a copy of the english translations.
36
40
 
37
41
  4. Add and run migrations (if you're using ActiveRecord):
38
42
  ```console
@@ -43,7 +47,8 @@ rake db:migrate
43
47
 
44
48
  ## Usage
45
49
 
46
- Just call the brand new method `bootsy_area` in your `FormBuilder` instances, the same way you'd call the basic `textarea` method. Example:
50
+ Just call the brand new method `bootsy_area` in your `FormBuilder` instances, the
51
+ same way you'd call the basic `textarea` method. Example:
47
52
  ```erb
48
53
  <%= form_for(@post) do |f| %>
49
54
  <%= f.label :title %>
@@ -56,7 +61,9 @@ Just call the brand new method `bootsy_area` in your `FormBuilder` instances, th
56
61
  <% end %>
57
62
  ```
58
63
 
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:
64
+ Bootsy will group the uploaded images as galleries and associate them to one of
65
+ your models. For example, if you have a `Post` model and you want to use `bootsy_area`
66
+ with it, then you should include the `Bootsy::Container` module:
60
67
  ```ruby
61
68
  class Post < ActiveRecord::Base
62
69
  include Bootsy::Container
@@ -65,7 +72,9 @@ class Post < ActiveRecord::Base
65
72
  end
66
73
  ```
67
74
 
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:
75
+ Don't forget to ensure the association of new instances of your model with Bootsy
76
+ image galleries. For `strong_parameters`, you must allow the parameter `bootsy_image_gallery_id`
77
+ in your controllers. Example:
69
78
  ```ruby
70
79
  private
71
80
  # Never trust parameters from the scary internet, only allow the white list through.
@@ -75,9 +84,10 @@ end
75
84
  ```
76
85
 
77
86
 
78
- ## Bootsy with SimpleForm builders
87
+ ## Bootsy with [Simple Form](https://github.com/plataformatec/simple_form) builders
79
88
 
80
- Just use the brand new input type `bootsy` in your `SimpleForm::FormBuilder` instances, in the same way you would use the basic `text` input. Example:
89
+ Just use the brand new input type `bootsy` in your `SimpleForm::FormBuilder` instances,
90
+ in the same way you would use the basic `text` input. Example:
81
91
  ```erb
82
92
  <%= simple_form_for @post do |f| %>
83
93
  <%= f.input :title %>
@@ -91,12 +101,14 @@ Just use the brand new input type `bootsy` in your `SimpleForm::FormBuilder` ins
91
101
 
92
102
  ## Editor options
93
103
 
94
- It is possible to customize how the editor is displayed and its behavior by passing a hash `editor_options` to your `bootsy_area`.
104
+ It is possible to customize how the editor is displayed and its behavior by passing
105
+ a hash `editor_options` to your `bootsy_area`.
95
106
 
96
107
 
97
108
  ### Buttons
98
109
 
99
- You can enable/disable the buttons available on the editor. For example, if you want to disable the link and color buttons:
110
+ You can enable/disable the buttons available on the editor. For example, if you
111
+ want to disable the link and color buttons:
100
112
  ```erb
101
113
  <%= f.bootsy_area :my_attribute, editor_options: {link: false, color: false} %>
102
114
  ```
@@ -105,24 +117,36 @@ Available options are: `:font_styles`, `:emphasis`, `:lists`, `:html`, `:link`,
105
117
 
106
118
  ### Alert for usaved changes
107
119
 
108
- By default, Bootsy alerts for unsaved changes if the user attempts to unload the window. You can disable this behaviour by doing:
120
+ By default, Bootsy alerts for unsaved changes if the user attempts to unload
121
+ the window. You can disable this behaviour by doing:
109
122
  ```erb
110
123
  <%= f.bootsy_area :my_attribute, editor_options: {alert_unsaved: false} %>
111
124
  ```
112
125
 
113
126
  ## Uploader
114
127
 
115
- It's also possible to use Bootsy without the image upload feature. Just call `bootsy_area` in a form builder not associated to a `Bootsy::Container` model. This way users can insert images in their texts by providing an image url.
128
+ It's also possible to use Bootsy without the image upload feature. Just call
129
+ `bootsy_area` in a form builder not associated to a `Bootsy::Container` model.
130
+ This way users can insert images in their texts by providing an image url.
116
131
 
117
132
 
118
133
  ## Configuration
119
134
 
120
- You can set the default editor options, image sizes available (small, medium, large and/or its original), its dimensions and more. Take a look at the initalizer file, `/config/initializers/bootsy.rb`.
135
+ You can set the default editor options, image sizes available (small, medium,
136
+ large and/or its original), its dimensions and more. Take a look at the initalizer
137
+ file, `/config/initializers/bootsy.rb`.
121
138
 
122
139
 
123
140
  ## I18n
124
141
 
125
- Bootsy defines some i18n keys. The english translation is automatically added to your `config/locales` directory as `bootsy.en.yml`. You can follow that template in order to translate Bootsy to your language. You can find some examples [here](https://github.com/volmer/bootsy/tree/master/config/locales). It is also necessary to add a translation for Bootstrap-wysihtml5, the javascript editor, in your assets pipeline. Instructions [here](https://github.com/jhollingworth/bootstrap-wysihtml5#i18n). If you are using the alert for unsaved changes, you have to define a translation for it as well. Just follow [this example](https://github.com/volmer/bootsy/tree/master/app/assets/bootsy/locales/bootsy.pt-BR.js).
142
+ Bootsy defines some i18n keys. The english translation is automatically added
143
+ to your `config/locales` directory as `bootsy.en.yml`. You can follow that template
144
+ in order to translate Bootsy to your language. You can find some examples
145
+ [here](https://github.com/volmer/bootsy/tree/master/config/locales). It is also
146
+ necessary to add a translation for Bootstrap-wysihtml5, the javascript editor, in
147
+ your assets pipeline. Instructions [here](https://github.com/jhollingworth/bootstrap-wysihtml5#i18n).
148
+ If you are using the alert for unsaved changes, you have to define a translation
149
+ for it as well. Just follow [this example](https://github.com/volmer/bootsy/tree/master/app/assets/bootsy/locales/bootsy.pt-BR.js).
126
150
 
127
151
 
128
152
  ## License
@@ -5,14 +5,14 @@
5
5
  "font-styles": function(locale, options) {
6
6
  var size = (options && options.size) ? ' btn-'+options.size : '';
7
7
  return "<li class='dropdown'>" +
8
- "<a class='btn dropdown-toggle" + size + "' data-toggle='dropdown' href='#' title='" + locale.font_styles.title + "'>" +
8
+ "<a class='btn btn-default dropdown-toggle" + size + "' data-toggle='dropdown' href='#' title='" + locale.font_styles.title + "'>" +
9
9
  "<i class='icon-font'></i>&nbsp;<span class='current-font'>" + locale.font_styles.normal + "</span>&nbsp;<b class='caret'></b>" +
10
10
  "</a>" +
11
11
  "<ul class='dropdown-menu'>" +
12
- "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='div' tabindex='-1'>" + locale.font_styles.normal + "</a></li>" +
13
- "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h1' tabindex='-1'>" + locale.font_styles.h1 + "</a></li>" +
14
- "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h2' tabindex='-1'>" + locale.font_styles.h2 + "</a></li>" +
15
- "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h3' tabindex='-1'>" + locale.font_styles.h3 + "</a></li>" +
12
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='div' tabindex='-1' role='menuitem'>" + locale.font_styles.normal + "</a></li>" +
13
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h1' tabindex='-1' role='menuitem'>" + locale.font_styles.h1 + "</a></li>" +
14
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h2' tabindex='-1' role='menuitem'>" + locale.font_styles.h2 + "</a></li>" +
15
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h3' tabindex='-1' role='menuitem'>" + locale.font_styles.h3 + "</a></li>" +
16
16
  "</ul>" +
17
17
  "</li>";
18
18
  },
@@ -21,9 +21,9 @@
21
21
  var size = (options && options.size) ? ' btn-'+options.size : '';
22
22
  return "<li>" +
23
23
  "<div class='btn-group'>" +
24
- "<a class='btn" + size + "' data-wysihtml5-command='bold' title='CTRL+B' tabindex='-1'>" + locale.emphasis.bold + "</a>" +
25
- "<a class='btn" + size + "' data-wysihtml5-command='italic' title='CTRL+I' tabindex='-1'>" + locale.emphasis.italic + "</a>" +
26
- "<a class='btn" + size + "' data-wysihtml5-command='underline' title='CTRL+U' tabindex='-1'>" + locale.emphasis.underline + "</a>" +
24
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='bold' title='CTRL+B' tabindex='-1'>" + locale.emphasis.bold + "</a>" +
25
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='italic' title='CTRL+I' tabindex='-1'>" + locale.emphasis.italic + "</a>" +
26
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='underline' title='CTRL+U' tabindex='-1'>" + locale.emphasis.underline + "</a>" +
27
27
  "</div>" +
28
28
  "</li>";
29
29
  },
@@ -32,10 +32,10 @@
32
32
  var size = (options && options.size) ? ' btn-'+options.size : '';
33
33
  return "<li>" +
34
34
  "<div class='btn-group'>" +
35
- "<a class='btn" + size + "' data-wysihtml5-command='insertUnorderedList' title='" + locale.lists.unordered + "' tabindex='-1'><i class='icon-list'></i></a>" +
36
- "<a class='btn" + size + "' data-wysihtml5-command='insertOrderedList' title='" + locale.lists.ordered + "' tabindex='-1'><i class='icon-th-list'></i></a>" +
37
- "<a class='btn" + size + "' data-wysihtml5-command='Outdent' title='" + locale.lists.outdent + "' tabindex='-1'><i class='icon-indent-left'></i></a>" +
38
- "<a class='btn" + size + "' data-wysihtml5-command='Indent' title='" + locale.lists.indent + "' tabindex='-1'><i class='icon-indent-right'></i></a>" +
35
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='insertUnorderedList' title='" + locale.lists.unordered + "' tabindex='-1'><i class='icon-list'></i></a>" +
36
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='insertOrderedList' title='" + locale.lists.ordered + "' tabindex='-1'><i class='icon-th-list'></i></a>" +
37
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='Outdent' title='" + locale.lists.outdent + "' tabindex='-1'><i class='icon-indent-left'></i></a>" +
38
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='Indent' title='" + locale.lists.indent + "' tabindex='-1'><i class='icon-indent-right'></i></a>" +
39
39
  "</div>" +
40
40
  "</li>";
41
41
  },
@@ -43,40 +43,48 @@
43
43
  "link": function(locale, options) {
44
44
  var size = (options && options.size) ? ' btn-'+options.size : '';
45
45
  return "<li>" +
46
- "<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>" +
47
- "<div class='modal-header'>" +
48
- "<a class='close' data-dismiss='modal'>&times;</a>" +
49
- "<h3>" + locale.link.insert + "</h3>" +
50
- "</div>" +
51
- "<div class='modal-body'>" +
52
- "<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>" +
53
- "</div>" +
54
- "<div class='modal-footer'>" +
55
- "<a href='#' class='btn' data-dismiss='modal'>" + locale.link.cancel + "</a>" +
56
- "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.link.insert + "</a>" +
46
+ "<div class='bootstrap-wysihtml5-insert-link-modal modal fade' tabindex='-1' role='dialog' aria-hidden='true'>" +
47
+ "<div class='modal-dialog'>" +
48
+ "<div class='modal-content'>" +
49
+ "<div class='modal-header'>" +
50
+ "<button type='button' class='close' data-dismiss='modal' aria-hidden='true'>&times;</button>" +
51
+ "<h3 class='modal-title'>" + locale.link.insert + "</h3>" +
52
+ "</div>" +
53
+ "<div class='modal-body'>" +
54
+ "<input value='http://' class='bootstrap-wysihtml5-insert-link-url form-control input-lg'>" +
55
+ "</div>" +
56
+ "<div class='modal-footer'>" +
57
+ "<a href='#' class='btn btn-default' data-dismiss='modal'>" + locale.link.cancel + "</a>" +
58
+ "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.link.insert + "</a>" +
59
+ "</div>" +
60
+ "</div>" +
57
61
  "</div>" +
58
62
  "</div>" +
59
- "<a class='btn" + size + "' data-wysihtml5-command='createLink' title='" + locale.link.insert + "' tabindex='-1'><i class='icon-share'></i></a>" +
63
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='createLink' title='" + locale.link.insert + "' tabindex='-1'><i class='icon-share'></i></a>" +
60
64
  "</li>";
61
65
  },
62
66
 
63
67
  "image": function(locale, options) {
64
68
  var size = (options && options.size) ? ' btn-'+options.size : '';
65
69
  return "<li>" +
66
- "<div class='bootstrap-wysihtml5-insert-image-modal modal hide fade'>" +
67
- "<div class='modal-header'>" +
68
- "<a class='close' data-dismiss='modal'>&times;</a>" +
69
- "<h3>" + locale.image.insert + "</h3>" +
70
- "</div>" +
71
- "<div class='modal-body'>" +
72
- "<input value='http://' class='bootstrap-wysihtml5-insert-image-url input-xlarge'>" +
73
- "</div>" +
74
- "<div class='modal-footer'>" +
75
- "<a href='#' class='btn' data-dismiss='modal'>" + locale.image.cancel + "</a>" +
76
- "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.image.insert + "</a>" +
70
+ "<div class='bootstrap-wysihtml5-insert-image-modal modal fade' tabindex='-1' role='dialog' aria-hidden='true'>" +
71
+ "<div class='modal-dialog'>" +
72
+ "<div class='modal-content'>" +
73
+ "<div class='modal-header'>" +
74
+ "<button type='button' class='close' data-dismiss='modal' aria-hidden='true'>&times;</button>" +
75
+ "<h3 class='modal-title'>" + locale.image.insert + "</h3>" +
76
+ "</div>" +
77
+ "<div class='modal-body'>" +
78
+ "<input value='http://' class='bootstrap-wysihtml5-insert-image-url form-control input-lg'>" +
79
+ "</div>" +
80
+ "<div class='modal-footer'>" +
81
+ "<a href='#' class='btn btn-default ' data-dismiss='modal'>" + locale.image.cancel + "</a>" +
82
+ "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.image.insert + "</a>" +
83
+ "</div>" +
84
+ "</div>" +
77
85
  "</div>" +
78
86
  "</div>" +
79
- "<a class='btn" + size + "' data-wysihtml5-command='insertImage' title='" + locale.image.insert + "' tabindex='-1'><i class='icon-picture'></i></a>" +
87
+ "<a class='btn btn-default " + size + "' data-wysihtml5-command='insertImage' title='" + locale.image.insert + "' tabindex='-1'><i class='icon-picture'></i></a>" +
80
88
  "</li>";
81
89
  },
82
90
 
@@ -84,7 +92,7 @@
84
92
  var size = (options && options.size) ? ' btn-'+options.size : '';
85
93
  return "<li>" +
86
94
  "<div class='btn-group'>" +
87
- "<a class='btn" + size + "' data-wysihtml5-action='change_view' title='" + locale.html.edit + "' tabindex='-1'><i class='icon-pencil'></i></a>" +
95
+ "<a class='btn btn-default " + size + "' data-wysihtml5-action='change_view' title='" + locale.html.edit + "' tabindex='-1'><i class='icon-pencil'></i></a>" +
88
96
  "</div>" +
89
97
  "</li>";
90
98
  },
@@ -92,21 +100,21 @@
92
100
  "color": function(locale, options) {
93
101
  var size = (options && options.size) ? ' btn-'+options.size : '';
94
102
  return "<li class='dropdown'>" +
95
- "<a class='btn dropdown-toggle" + size + "' data-toggle='dropdown' href='#' tabindex='-1' title='" + locale.colours.title + "'>" +
103
+ "<a class='btn btn-default dropdown-toggle" + size + "' data-toggle='dropdown' href='#' tabindex='-1' title='" + locale.colours.title + "'>" +
96
104
  "<span class='current-color'>" + locale.colours.black + "</span>&nbsp;<b class='caret'></b>" +
97
105
  "</a>" +
98
106
  "<ul class='dropdown-menu'>" +
99
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='black'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='black'>" + locale.colours.black + "</a></li>" +
100
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='silver'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='silver'>" + locale.colours.silver + "</a></li>" +
101
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='gray'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='gray'>" + locale.colours.gray + "</a></li>" +
102
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='maroon'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='maroon'>" + locale.colours.maroon + "</a></li>" +
103
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='red'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='red'>" + locale.colours.red + "</a></li>" +
104
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='purple'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='purple'>" + locale.colours.purple + "</a></li>" +
105
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='green'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='green'>" + locale.colours.green + "</a></li>" +
106
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='olive'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='olive'>" + locale.colours.olive + "</a></li>" +
107
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='navy'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='navy'>" + locale.colours.navy + "</a></li>" +
108
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='blue'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='blue'>" + locale.colours.blue + "</a></li>" +
109
- "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='orange'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='orange'>" + locale.colours.orange + "</a></li>" +
107
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='black'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='black' role='menuitem'>" + locale.colours.black + "</a></li>" +
108
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='silver'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='silver' role='menuitem'>" + locale.colours.silver + "</a></li>" +
109
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='gray'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='gray' role='menuitem'>" + locale.colours.gray + "</a></li>" +
110
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='maroon'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='maroon' role='menuitem'>" + locale.colours.maroon + "</a></li>" +
111
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='red'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='red' role='menuitem'>" + locale.colours.red + "</a></li>" +
112
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='purple'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='purple' role='menuitem'>" + locale.colours.purple + "</a></li>" +
113
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='green'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='green' role='menuitem'>" + locale.colours.green + "</a></li>" +
114
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='olive'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='olive' role='menuitem'>" + locale.colours.olive + "</a></li>" +
115
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='navy'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='navy' role='menuitem'>" + locale.colours.navy + "</a></li>" +
116
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='blue'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='blue' role='menuitem'>" + locale.colours.blue + "</a></li>" +
117
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='orange'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='orange' role='menuitem'>" + locale.colours.orange + "</a></li>" +
110
118
  "</ul>" +
111
119
  "</li>";
112
120
  }
@@ -143,7 +151,7 @@
143
151
 
144
152
  createEditor: function(options) {
145
153
  options = options || {};
146
-
154
+
147
155
  // Add the toolbar to a clone of the options object so multiple instances
148
156
  // of the WYISYWG don't break because "toolbar" is already defined
149
157
  options = $.extend(true, {}, options);
@@ -392,7 +400,7 @@
392
400
  return methods.init.apply( this, arguments );
393
401
  } else {
394
402
  $.error( 'Method ' + method + ' does not exist on jQuery.wysihtml5' );
395
- }
403
+ }
396
404
  };
397
405
 
398
406
  $.fn.wysihtml5.Constructor = Wysihtml5;
@@ -41,7 +41,7 @@ $.fn.bootstrapFileInput = function() {
41
41
 
42
42
  // Now we're going to replace that input field with a Bootstrap button.
43
43
  // The input will actually still be there, it will just be float above and transparent (done with the CSS).
44
- $elem.replaceWith('<a class="file-input-wrapper btn' + className + '">'+buttonWord+input+'</a>');
44
+ $elem.replaceWith('<a class="file-input-wrapper btn btn-default ' + className + '">'+buttonWord+input+'</a>');
45
45
  })
46
46
 
47
47
  // After we have found all of the file inputs let's apply a listener for tracking the mouse movement.
@@ -1,221 +1,278 @@
1
1
  window.Bootsy = window.Bootsy || {};
2
2
 
3
- window.Bootsy.Area = function ($el) {
4
- var self = this;
5
- self.bootsyUploadInit = false; // this flag tells the refreshGallery method whether there was a new upload or not
3
+ Bootsy.Area = function($el) {
4
+ this.$el = $el;
5
+ this.modal = $el.siblings('.bootsy-modal');
6
+ this.locale = $el.data('bootsy-locale') || $('html').attr('lang') || 'en';
7
+ this.unsavedChanges = false;
6
8
 
7
- this.progressBar = function () {
8
- // Show loading spinner
9
- $('.bootsy-spinner img').fadeIn(200);
9
+ this.options = {
10
+ locale: this.locale,
11
+ alertUnsavedChanges: $el.data('bootsy-alert-unsaved'),
12
+ image: $el.data('bootsy-image'),
13
+ uploader: $el.data('bootsy-uploader'),
10
14
  };
11
15
 
12
- this.setImageGalleryId = function (id) {
13
- self.imageGalleryModal.data('bootsy-gallery-id', id)
14
- $('input.bootsy_image_gallery_id').val(id);
15
- };
16
+ if ($el.data('bootsy-font-styles') === false) this.options['font-styles'] = false;
17
+ if ($el.data('bootsy-emphasis') === false) this.options.emphasis = false;
18
+ if ($el.data('bootsy-lists') === false) this.options.lists = false;
19
+ if ($el.data('bootsy-html') === true) this.options.html = true;
20
+ if ($el.data('bootsy-link') === false) this.options.link = false;
21
+ if ($el.data('bootsy-color') === false) this.options.color = false;
16
22
 
17
- this.deleteImage = function (id) {
18
- self.imageGalleryModal.find("ul.thumbnails").find("[data-id='" + id + "']").hide(200, function(){
19
- $(this).remove();
20
- // Put message back if 0 images
21
- if ( self.imageGalleryModal.find('.thumbnails li').length == 0 ) {
22
- self.imageGalleryModal.find('.alert').fadeIn(200);
23
- }
24
- });
25
- };
23
+ // Delegate find to the modal
24
+ this.find = this.modal.find.bind(this.modal);
25
+ };
26
+
27
+
28
+ // Gallery loading
29
+ Bootsy.Area.prototype.showGalleryLoadingAnimation = function() {
30
+ this.find('.bootsy-gallery-loader').fadeIn(200);
31
+ };
32
+
33
+ Bootsy.Area.prototype.hideGalleryLoadingAnimation = function() {
34
+ this.find('.bootsy-gallery-loader').fadeOut(200);
35
+ };
26
36
 
27
- this.refreshGallery = function () {
28
- self.progressBar();
29
- $.ajax({
30
- url: '/bootsy/images',
31
- type: 'GET',
32
- cache: false,
33
- data: {
34
- image_gallery_id: self.imageGalleryModal.data('bootsy-gallery-id')
35
- },
36
- dataType: 'json',
37
- success: function (data) {
38
- // Hide loading spinner
39
- $('.bootsy-spinner img').fadeOut(200);
40
-
41
- // Cache the returned data
42
- var $data = $(data.partial);
43
-
44
- // Retrieve the last added li from the cached data
45
- img = $data.find('ul.thumbnails > li').last();
46
-
47
- if ( img.length ) {
48
- // Thumbnails currently exist in the retrieved data, so hide the message
49
- $('.alert').hide();
50
- } else {
51
- // Thumbnails do not exist in the retrieved data, so show the message
52
- $('.thumbnails li').hide();
53
- $('.alert').fadeIn(100);
54
- }
55
-
56
- if ( self.imageGalleryModal.find('.modal-body').children().length == 0 ) {
57
- // Init the modal content (only loads first time)
58
- self.imageGalleryModal.find('.modal-content').html($data).hide().fadeIn(200);
59
- // Nicer file input
60
- $('.modal-footer #image_image_file').bootstrapFileInput();
61
- } else if ( self.bootsyUploadInit == true ) {
62
- self.bootsyUploadInit = false;
63
- $(img).hide().appendTo(self.imageGalleryModal.find('.modal-body .thumbnails')).fadeIn(200);
64
- } else {
65
- // do nothing
66
- }
67
-
68
- self.imageGalleryModal.find('a.refresh-btn').hide();
69
- self.imageGalleryModal.find('#refresh-gallery').hide();
70
- self.imageGalleryModal.find('input#upload_submit').hide();
71
-
72
-
73
- // Autosubmit on image selection
74
- $('.modal-footer #image_image_file').on('change', function(){
75
- self.progressBar();
76
- self.bootsyUploadInit = true;
77
- $(this).closest('form').submit();
78
- });
79
-
80
- },
81
- error: function (e) {
82
- alert(Bootsy.translations[self.locale].error);
83
- self.imageGalleryModal.find('a.refresh-btn').show();
37
+
38
+ // Upload loading animation
39
+ Bootsy.Area.prototype.showUploadLoadingAnimation = function() {
40
+ this.find('.bootsy-upload-loader').fadeIn(200);
41
+ };
42
+
43
+ Bootsy.Area.prototype.hideUploadLoadingAnimation = function() {
44
+ this.find('.bootsy-upload-loader').fadeOut(200);
45
+ };
46
+
47
+ // Alert for empty gallery
48
+ Bootsy.Area.prototype.showEmptyAlert = function() {
49
+ this.find('.bootsy-empty-alert').fadeIn(200);
50
+ };
51
+
52
+ Bootsy.Area.prototype.hideEmptyAlert = function() {
53
+ this.find('.bootsy-empty-alert').fadeOut(200);
54
+ };
55
+
56
+ // Manual refresh button
57
+ Bootsy.Area.prototype.showRefreshButton = function() {
58
+ this.find('.refresh-btn').fadeIn(200);
59
+ };
60
+
61
+ Bootsy.Area.prototype.hideRefreshButton = function() {
62
+ this.find('.refresh-btn').fadeOut(200);
63
+ };
64
+
65
+
66
+ // Set upload form
67
+ Bootsy.Area.prototype.setUploadForm = function(html) {
68
+ var form;
69
+
70
+ this.find('.modal-footer').html(html);
71
+
72
+ this.hideUploadLoadingAnimation();
73
+
74
+ this.find('.bootsy-upload-form input[type="file"]').bootstrapFileInput();
75
+
76
+ this.uploadInput = this.find('.bootsy-upload-form input[type="file"]');
77
+
78
+ this.uploadInput.change(function() {
79
+ this.showUploadLoadingAnimation();
80
+
81
+ this.uploadInput.closest('form').submit();
82
+ }.bind(this));
83
+ };
84
+
85
+
86
+ // Set image gallery
87
+ Bootsy.Area.prototype.setImageGallery = function() {
88
+ this.showGalleryLoadingAnimation();
89
+
90
+ $.ajax({
91
+ url: '/bootsy/images',
92
+ type: 'GET',
93
+ cache: false,
94
+ data: {
95
+ image_gallery_id: this.modal.data('gallery-id')
96
+ },
97
+ dataType: 'json',
98
+ success: function(data) {
99
+ this.hideGalleryLoadingAnimation();
100
+
101
+ $.each(data.images, function(index, value) {
102
+ this.addImage(value);
103
+ }.bind(this));
104
+
105
+ if (data.images.length == 0) {
106
+ this.showEmptyAlert();
84
107
  }
85
- });
86
- };
87
108
 
88
- this.openImageGallery = function (editor) {
89
- editor.currentView.element.focus(false);
90
- self.caretBookmark = editor.composer.selection.getBookmark();
91
- $('#bootsy_image_gallery').modal('show');
92
- };
109
+ this.setUploadForm(data.form);
93
110
 
94
- this.insertImage = function (image) {
95
- $('#bootsy_image_gallery').modal('hide');
96
- self.editor.currentView.element.focus();
97
- if (self.caretBookmark) {
98
- self.editor.composer.selection.setBookmark(self.caretBookmark);
99
- self.caretBookmark = null;
100
- }
101
- self.editor.composer.commands.exec('insertImage', image);
102
- };
111
+ this.modal.data('gallery-loaded', true);
112
+ }.bind(this),
113
+ error: function(e) {
114
+ alert(Bootsy.translations[this.locale].error);
103
115
 
104
- this.on = function (eventName, callback) {
105
- self.eventCallbacks[eventName].push(callback);
106
- };
116
+ this.showRefreshButton();
117
+ }.bind(this)
118
+ });
119
+ };
107
120
 
108
- this.trigger = function (eventName) {
109
- var callbacks = self.eventCallbacks[eventName];
110
- for(i in callbacks) {
111
- callbacks[i]();
112
- }
113
- self.triggeredEvents.push(eventName);
114
- };
121
+ // Delete image
122
+ Bootsy.Area.prototype.deleteImage = function (id) {
123
+ var image = this.find('.bootsy-image[data-id="' + id + '"]');
115
124
 
116
- this.after = function (eventName, callback) {
117
- if(self.triggeredEvents.indexOf(eventName) != -1) {
118
- callback();
119
- }else{
120
- self.on(eventName, callback);
121
- }
122
- };
125
+ this.hideGalleryLoadingAnimation();
123
126
 
124
- this.alertUnsavedChanges = function () {
125
- if (self.unsavedChanges) {
126
- return Bootsy.translations[self.locale].alert_unsaved;
127
+ image.hide(200, function() {
128
+ image.remove();
129
+
130
+ // Put message back if 0 images
131
+ if (this.find('.bootsy-image').length == 0 ) {
132
+ this.showEmptyAlert();
127
133
  }
128
- };
134
+ }.bind(this));
135
+ };
129
136
 
130
- this.clear = function () {
131
- self.editor.clear();
132
- self.setImageGalleryId('');
133
- };
134
137
 
135
- this.locale = $el.data('bootsy-locale') || $('html').attr('lang') || 'en';
136
- this.caretBookmark = false;
137
- this.unsavedChanges = false;
138
- this.editor = false;
139
- this.eventCallbacks = {'loaded': []};
140
- this.triggeredEvents = [];
141
- this.editorOptions = {locale: this.locale};
142
-
143
- if ($el.data('bootsy-font-styles') === false) this.editorOptions['font-styles'] = false;
144
- if ($el.data('bootsy-emphasis') === false) this.editorOptions.emphasis = false;
145
- if ($el.data('bootsy-lists') === false) this.editorOptions.lists = false;
146
- if ($el.data('bootsy-html') === true) this.editorOptions.html = true;
147
- if ($el.data('bootsy-link') === false) this.editorOptions.link = false;
148
- if ($el.data('bootsy-color') === false) this.editorOptions.color = false;
149
-
150
- if ($el.data('bootsy-alert-unsaved') !== false) {
151
- window.onbeforeunload = this.alertUnsavedChanges;
138
+ // Add image to gallery
139
+ Bootsy.Area.prototype.addImage = function(html) {
140
+ this.hideEmptyAlert();
141
+
142
+ $(html).hide().appendTo(this.find('.bootsy-gallery')).fadeIn(200);
143
+ };
144
+
145
+ // Insert image in the text
146
+ Bootsy.Area.prototype.insertImage = function(image) {
147
+ this.modal.modal('hide');
148
+
149
+ this.editor.currentView.element.focus();
150
+
151
+ if (this.caretBookmark) {
152
+ this.editor.composer.selection.setBookmark(this.caretBookmark);
153
+ this.caretBookmark = null;
152
154
  }
153
155
 
154
- $el.closest('form').submit(function (e) {
155
- self.unsavedChanges = false;
156
- return true;
157
- });
156
+ this.editor.composer.commands.exec('insertImage', image);
157
+ };
158
+
159
+ // Open Bootsy modal
160
+ Bootsy.Area.prototype.openImagesModal = function(editor) {
161
+ editor.currentView.element.focus(false);
162
+
163
+ this.caretBookmark = editor.composer.selection.getBookmark();
164
+
165
+ this.modal.modal('show');
166
+ };
167
+
168
+ // Alert for unsaved changes
169
+ Bootsy.Area.prototype.unsavedChangesAlert = function () {
170
+ if (this.unsavedChanges) {
171
+ return Bootsy.translations[this.locale].alertUnsaved;
172
+ }
173
+ };
174
+
175
+ // Clear everything
176
+ Bootsy.Area.prototype.clear = function () {
177
+ this.editor.clear();
178
+ this.setImageGalleryId('');
179
+ this.modal.data('gallery-loaded', false);
180
+ };
181
+
182
+ // Set the image gallery id
183
+ Bootsy.Area.prototype.setImageGalleryId = function(id) {
184
+ this.modal.data('gallery-id', id);
185
+
186
+ this.$el.siblings('.bootsy_image_gallery_id').val(id);
187
+ };
188
+
189
+
190
+ // Init components
191
+ Bootsy.Area.prototype.init = function() {
192
+ var insert = this.insertImage.bind(this);
193
+
194
+ if ((this.options.image === true) && (this.options.uploader === true)) {
195
+ this.modal.on('click', '.bootsy-image .insert', function(e) {
196
+ var img, imageObject;
197
+ var imagePrefix = '/' + $(this).attr('data-image-size') + '_';
198
+
199
+ if ($(this).data('image-size') === 'original') {
200
+ imagePrefix = '/';
201
+ }
202
+
203
+ img = $(this).parents('.bootsy-image').find('img');
158
204
 
159
- if ($el.data('bootsy-image') !== false) {
160
- if ($el.data('bootsy-uploader') !== false) {
161
- this.editorOptions.image = false;
162
- this.editorOptions.customCommand = true;
163
- this.editorOptions.customCommandCallback = this.openImageGallery;
164
- this.editorOptions.customTemplates = {
165
- customCommand: function (locale, options) {
166
- var size = (options && options.size) ? ' btn-'+options.size : '';
167
- return "<li>" +
168
- "<a class='btn" + size + "' data-wysihtml5-command='customCommand' title='" + locale.image.insert + "' tabindex='-1'><i class='icon-picture'></i></a>" +
169
- "</li>";
170
- }
205
+ imageObject = {
206
+ src: img.attr('src').replace('/thumb_', imagePrefix),
207
+ alt: img.attr('alt').replace('Thumb_', '')
171
208
  };
172
209
 
173
- this.imageGalleryModal = $('#bootsy_image_gallery');
174
- this.imageGalleryModal.find('a.refresh-btn').hide();
210
+ imageObject.align = $(this).data('position');
175
211
 
176
- this.imageGalleryModal.parents('form').after(this.imageGalleryModal);
212
+ insert(imageObject);
213
+ });
177
214
 
178
- this.imageGalleryModal.on('click', 'a[href="#refresh-gallery"]', this.refreshGallery);
215
+ // Let's use the uploader, not the static image modal
216
+ this.options.image = false;
217
+ this.options.customCommand = true;
218
+ this.options.customCommandCallback = this.openImagesModal.bind(this);
219
+ this.options.customTemplates = {
220
+ customCommand: function(locale, options) {
221
+ var size = (options && options.size) ? ' btn-'+options.size : '';
222
+
223
+ return '<li>' +
224
+ '<a class="btn btn-default ' + size + '" data-wysihtml5-command="customCommand" title="' + locale.image.insert + '" tabindex="-1">' +
225
+ '<i class="icon-picture"></i>' +
226
+ '</a>' +
227
+ '</li>';
228
+ }
229
+ };
179
230
 
180
- this.imageGalleryModal.find('a.destroy_btn').click(this.progressBar);
231
+ // In order to avoid form nesting
232
+ this.modal.parents('form').after(this.modal);
181
233
 
182
- this.imageGalleryModal.modal({show: false});
183
- this.imageGalleryModal.on('shown', this.refreshGallery);
234
+ this.modal.on('click', 'a[href="#refresh-gallery"]', this.setImageGallery.bind(this));
184
235
 
185
- this.imageGalleryModal.on('hide', function () {
186
- self.progressBar();
187
- self.editor.currentView.element.focus();
188
- });
236
+ this.modal.on('ajax:before', '.destroy-btn', this.showGalleryLoadingAnimation.bind(this));
189
237
 
190
- this.imageGalleryModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function (e) {
191
- e.stopPropagation();
192
- });
238
+ this.modal.on('ajax:success', '.destroy-btn', function(evt, data) {
239
+ this.deleteImage(data.id);
240
+ }.bind(this));
193
241
 
194
- this.imageGalleryModal.on('click', 'ul.dropdown-menu a.insert', function (e) {
195
- var imagePrefix = "/"+$(this).attr('data-image-size')+"_";
196
- if($(this).data('image-size') == 'original') {
197
- imagePrefix = '/';
198
- }
199
- var img = $(this).parents('li.dropdown').find('img');
200
- var obj = {
201
- src: img.attr('src').replace("/thumb_", imagePrefix),
202
- alt: img.attr('alt').replace("Thumb_", "")
203
- };
242
+ this.modal.on('ajax:success', '.bootsy-upload-form', function(evt, data) {
243
+ this.setImageGalleryId(data.gallery_id);
244
+ this.addImage(data.image);
245
+ this.setUploadForm(data.form);
246
+ }.bind(this));
247
+ }
204
248
 
205
- obj.align = $(this).data('position');
249
+ this.editor = this.$el.wysihtml5($.extend(Bootsy.options, this.options)).data('wysihtml5').editor;
206
250
 
207
- self.insertImage(obj);
208
- });
209
- }
210
- } else {
211
- this.editorOptions.image = false;
251
+ // Mechanism for unsaved changes alert
252
+ if (this.options.alertUnsavedChanges !== false) {
253
+ window.onbeforeunload = this.unsavedChangesAlert.bind(this);
212
254
  }
213
255
 
214
- this.editor = $el.wysihtml5($.extend(Bootsy.editorOptions, this.editorOptions)).data('wysihtml5').editor;
256
+ this.$el.closest('form').submit(function(e) {
257
+ this.unsavedChanges = false;
215
258
 
216
- this.editor.on('change', function () {
217
- self.unsavedChanges = true;
218
- });
259
+ return true;
260
+ }.bind(this));
261
+
262
+ this.editor.on('change', function() {
263
+ this.unsavedChanges = true;
264
+ }.bind(this));
265
+
266
+ this.modal.modal({ show: false });
267
+
268
+ this.modal.on('shown.bs.modal', function() {
269
+ if (this.modal.data('gallery-loaded') !== true) {
270
+ this.setImageGallery();
271
+ }
272
+ }.bind(this));
273
+
274
+ this.modal.on('hide.bs.modal', this.editor.currentView.element.focus);
219
275
 
220
- this.trigger('loaded');
276
+ this.hideRefreshButton();
277
+ this.hideEmptyAlert();
221
278
  };