Skip to content
This repository was archived by the owner on Jul 14, 2022. It is now read-only.

Commit f0f85f7

Browse files
Merge pull request #95 from bendyworks/model
Add additional configuration
2 parents dd7ba5d + adef3c0 commit f0f85f7

File tree

2 files changed

+167
-46
lines changed

2 files changed

+167
-46
lines changed

README.md

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ A small demo app demonstrating a working setup for Rails 3.2 ([demo](http://murm
2929
### Add the gem to your Gemfile
3030

3131
gem 'tinymce-rails-imageupload', '~> 4.0.0.beta'
32-
32+
3333
# or use git
34-
34+
3535
gem 'tinymce-rails-imageupload', github: 'PerfectlyNormal/tinymce-rails-imageupload'
3636

3737
### Set up TinyMCE as you would normally, but in the call to `.tinymce()`, add
@@ -41,6 +41,20 @@ A small demo app demonstrating a working setup for Rails 3.2 ([demo](http://murm
4141

4242
and the rest should happen automatically.
4343

44+
You can also globally have imageupload globally disabled but enabled on specific instances.
45+
46+
~~~yml
47+
# tinymce.yml
48+
toolbar: bold italic underline | uploadimage
49+
plugins:
50+
- uploadimage
51+
uploadimage: false
52+
~~~
53+
54+
~~~erb
55+
<%= tinymce uploadimage: true %>
56+
~~~
57+
4458
### Set up upload URL and handler
4559

4660
The plugin defaults to POSTing to `/tinymce_assets`. You may modify it by
@@ -51,10 +65,6 @@ Set it up using something similar in `routes.rb`:
5165

5266
post '/tinymce_assets' => 'tinymce_assets#create'
5367

54-
The plugin will relay option `uploadimage_hint` in the call to `.tinymce()`
55-
to the POSTed URL as param `hint`. You may use this to relay any hints
56-
you wish (for example, blog post ID #) to the controller.
57-
5868
This action gets called with a file parameter creatively called `file`,
5969
and must respond with JSON, containing the URL to the image.
6070

@@ -76,19 +86,81 @@ Example:
7686
end
7787
end
7888

89+
7990
If the JSON response contains a `width` and/or `height` key,
8091
those will be used in the inserted HTML (`<img src="..." width="..." height="...">`),
8192
but if those are not present, the inserted HTML is just `<img src="...">`.
8293

94+
### Hint param
95+
96+
Per request `hint` data can be sent to the `create` action through the call to `.tinymce()` or `tinymce.yml`. You may use this to relay any hints you wish (for example, blog post ID #) to the controller.
97+
98+
- `uploadimage_hint_key` - override the hint key. Default is `hint`.
99+
- `uploadimage_hint` - hint value.
100+
101+
Example:
102+
103+
~~~erb
104+
<%= tinymce uploadimage_hint_key: 'post_id', uploadimage_hint: @post.id %>
105+
~~~
106+
107+
Would result in a `params` object that looks like this:
108+
109+
~~~ruby
110+
{
111+
"post_id": 1,
112+
"file": ...,
113+
// ...
114+
}
115+
~~~
116+
117+
### Model attributes
118+
119+
Params can be sent in a more standard attributes format by setting `uploadimage_model`.
120+
121+
- `uploadimage_model` - nest attributes within model namespace.
122+
123+
Example:
124+
125+
~~~erb
126+
<%= tinymce uploadimage_model: 'post' %>
127+
~~~
128+
129+
Would result in a `params` object that looks like this:
130+
131+
~~~ruby
132+
{
133+
"post": {
134+
"file": ...,
135+
// ...
136+
},
137+
}
138+
~~~
139+
83140
### Default class for img tag
84141

85142
By default the plugin doesn't assign any class to the img tag.
86143
You can set the class(es) by supplying the `uploadimage_default_img_class`
87144
option in the call to `.tinymce()`.
88145

89-
`class="..."` will only be added to the img tag if a default is specified.
146+
`class="..."` will only be added to the img tag if a default or custom class is specified.
90147
Otherwise the inserted HTML is just `<img src="...">`.
91148

149+
### Custom classes
150+
151+
You can set `image_class_list` to an array of `title`, `value` objects to provide uploaders a pre-defined list of CSS classes to apply.
152+
153+
~~~yml
154+
# tinymce.yml
155+
image_class_list:
156+
- title: 'Center'
157+
value: 'img-center'
158+
- title: 'Left thumbnail'
159+
value: 'img-left img-thumbnail'
160+
- title: 'Right thumbnail'
161+
value: 'img-right img-thumbnail'
162+
~~~
163+
92164
## Asset Pipeline
93165

94166
Several people have had trouble with asset precompilation using the asset pipeline, both for the locales, and the plugin itself.

app/assets/javascripts/tinymce/plugins/uploadimage/plugin.js

Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,44 @@
77
iframe,
88
win,
99
throbber,
10+
selected_class = '',
1011
editor = ed;
1112

1213
function showDialog() {
14+
var classList = getClassList();
15+
var body = [
16+
{type: 'iframe', url: 'javascript:void(0)'},
17+
{type: 'textbox', name: 'file', label: ed.translate('Choose an image'), subtype: 'file'},
18+
{type: 'textbox', name: 'alt', label: ed.translate('Image description')}
19+
];
20+
21+
if (classList.length > 0) {
22+
selected_class = classList[0].value;
23+
body = body.concat([
24+
{
25+
type: 'listbox',
26+
name: 'class',
27+
label: ed.translate('Class'),
28+
values: classList,
29+
onSelect: function(e) {
30+
selected_class = this.value();
31+
}
32+
}
33+
]);
34+
}
35+
36+
body = body.concat([
37+
{type: 'container', classes: 'error', html: "<p style='color: #b94a48;'>&nbsp;</p>"},
38+
39+
// Trick TinyMCE to add a empty div that "preloads" the throbber image
40+
{type: 'container', classes: 'throbber'}
41+
]);
42+
1343
win = editor.windowManager.open({
1444
title: ed.translate('Insert an image from your computer'),
1545
width: 520 + parseInt(editor.getLang('uploadimage.delta_width', 0), 10),
1646
height: 180 + parseInt(editor.getLang('uploadimage.delta_height', 0), 10),
17-
body: [
18-
{type: 'iframe', url: 'javascript:void(0)'},
19-
{type: 'textbox', name: 'file', label: ed.translate('Choose an image'), subtype: 'file'},
20-
{type: 'textbox', name: 'alt', label: ed.translate('Image description')},
21-
{type: 'container', classes: 'error', html: "<p style='color: #b94a48;'>&nbsp;</p>"},
22-
23-
// Trick TinyMCE to add a empty div that "preloads" the throbber image
24-
{type: 'container', classes: 'throbber'},
25-
],
47+
body: body,
2648
buttons: [
2749
{
2850
text: ed.translate('Insert'),
@@ -38,10 +60,6 @@
3860
plugin_url: url
3961
});
4062

41-
// TinyMCE likes pointless submit handlers
42-
win.off('submit');
43-
win.on('submit', insertImage);
44-
4563
/* WHY DO YOU HATE <form>, TINYMCE!? */
4664
iframe = win.find("iframe")[0];
4765
form = createElement('form', {
@@ -59,7 +77,7 @@
5977
// Create some needed hidden inputs
6078
form.appendChild(createElement('input', {type: "hidden", name: "utf8", value: "✓"}));
6179
form.appendChild(createElement('input', {type: 'hidden', name: 'authenticity_token', value: getMetaContents('csrf-token')}));
62-
form.appendChild(createElement('input', {type: 'hidden', name: 'hint', value: ed.getParam("uploadimage_hint", "")}));
80+
form.appendChild(createElement('input', {type: 'hidden', name: hintName(), value: hintValue()}));
6381

6482
var el = win.getEl();
6583
var body = document.getElementById(el.id + "-body");
@@ -77,7 +95,7 @@
7795

7896
if(ctrl.tagName.toLowerCase() == 'input' && ctrl.type != "hidden") {
7997
if(ctrl.type == "file") {
80-
ctrl.name = "file";
98+
ctrl.name = inputName('file');
8199

82100
// Hack styles
83101
tinymce.DOM.setStyles(ctrl, {
@@ -86,16 +104,32 @@
86104
'webkitBoxShadow': 'none',
87105
});
88106
} else {
89-
ctrl.name = "alt";
107+
ctrl.name = inputName('alt');
90108
}
91109
}
92110
}
93111

94112
body.appendChild(form);
95113
}
96114

115+
function hintName() {
116+
return inputName(ed.getParam('uploadimage_hint_key', 'hint'));
117+
}
118+
119+
function hintValue() {
120+
return ed.getParam('uploadimage_hint', '');
121+
}
122+
123+
function inputName(name) {
124+
if (ed.getParam('uploadimage_model', false)) {
125+
return ed.getParam('uploadimage_model') + '[' + name + ']';
126+
} else {
127+
return name;
128+
}
129+
}
130+
97131
function insertImage() {
98-
if(getInputValue("file") == "") {
132+
if(getInputValue(inputName('file')) == "") {
99133
return handleError('You must choose a file');
100134
}
101135

@@ -128,7 +162,7 @@
128162
var target = iframe.getEl();
129163
if(target.document || target.contentDocument) {
130164
var doc = target.contentDocument || target.contentWindow.document;
131-
if(String(doc.contentType).includes("html")) {
165+
if(String(doc.contentType).indexOf("html") > -1) {
132166
handleResponse(doc.getElementsByTagName("body")[0].innerHTML);
133167
} else {
134168
handleResponse(doc.getElementsByTagName("pre")[0].innerHTML);
@@ -180,19 +214,20 @@
180214
}
181215

182216
function buildHTML(json) {
217+
var image = json[ed.getParam('uploadimage_model', 'image')];
183218
var default_class = ed.getParam("uploadimage_default_img_class", "");
184219
var figure = ed.getParam("uploadimage_figure", false);
185-
var alt_text = getInputValue("alt");
220+
var alt_text = getInputValue(inputName('alt'));
186221

187-
var imgstr = "<img src='" + json["image"]["url"] + "'";
222+
var imgstr = "<img src='" + image["url"] + "'";
188223

189224
if(default_class != "")
190-
imgstr += " class='" + default_class + "'";
225+
imgstr += " class='" + default_class + ' ' + selected_class + "'";
191226

192-
if(json["image"]["height"])
193-
imgstr += " height='" + json["image"]["height"] + "'";
194-
if(json["image"]["width"])
195-
imgstr += " width='" + json["image"]["width"] + "'";
227+
if(image["height"])
228+
imgstr += " height='" + image["height"] + "'";
229+
if(image["width"])
230+
imgstr += " width='" + image["width"] + "'";
196231

197232
imgstr += " alt='" + alt_text + "'/>";
198233

@@ -237,20 +272,34 @@
237272
return null;
238273
}
239274

240-
// Add a button that opens a window
241-
editor.addButton('uploadimage', {
242-
tooltip: ed.translate('Insert an image from your computer'),
243-
icon : 'image',
244-
onclick: showDialog
245-
});
246-
247-
// Adds a menu item to the tools menu
248-
editor.addMenuItem('uploadimage', {
249-
text: ed.translate('Insert an image from your computer'),
250-
icon : 'image',
251-
context: 'insert',
252-
onclick: showDialog
253-
});
275+
function getClassList() {
276+
var config = ed.getParam('image_class_list', []);
277+
var values = [];
278+
for (var i = 0; i < config.length; i++) {
279+
values[i] = {
280+
text: config[i]['title'],
281+
value: config[i]['value']
282+
};
283+
}
284+
return values;
285+
};
286+
287+
if (editor.getParam('uploadimage', true)) {
288+
// Add a button that opens a window
289+
editor.addButton('uploadimage', {
290+
tooltip: ed.translate('Insert an image from your computer'),
291+
icon : 'image',
292+
onclick: showDialog
293+
});
294+
295+
// Adds a menu item to the tools menu
296+
editor.addMenuItem('uploadimage', {
297+
text: ed.translate('Insert an image from your computer'),
298+
icon : 'image',
299+
context: 'insert',
300+
onclick: showDialog
301+
});
302+
}
254303
}
255304
});
256305

0 commit comments

Comments
 (0)