thredded 0.12.4 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -33
- data/app/assets/javascripts/thredded/components/currently_online.es6 +28 -21
- data/app/assets/javascripts/thredded/components/flash_messages.es6 +5 -7
- data/app/assets/javascripts/thredded/components/mention_autocompletion.es6 +39 -0
- data/app/assets/javascripts/thredded/components/post_form.es6 +28 -33
- data/app/assets/javascripts/thredded/components/preview_area.es6 +27 -23
- data/app/assets/javascripts/thredded/components/quote_post.es6 +5 -1
- data/app/assets/javascripts/thredded/components/time_stamps.es6 +24 -9
- data/app/assets/javascripts/thredded/components/topic_form.es6 +72 -54
- data/app/assets/javascripts/thredded/components/topics.es6 +28 -19
- data/app/assets/javascripts/thredded/components/turboforms.es6 +23 -13
- data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +33 -31
- data/app/assets/javascripts/thredded/components/user_textcomplete.es6 +47 -0
- data/app/assets/javascripts/thredded/components/users_select.es6 +102 -52
- data/app/assets/javascripts/thredded/core/debounce.es6 +1 -1
- data/app/assets/javascripts/thredded/core/escape_html.es6 +7 -0
- data/app/assets/javascripts/thredded/core/hide_soft_keyboard.es6 +1 -1
- data/app/assets/javascripts/thredded/core/on_page_load.es6 +1 -1
- data/app/assets/javascripts/thredded/core/serialize_form.es6 +9 -0
- data/app/assets/javascripts/thredded/dependencies.js +2 -5
- data/app/assets/javascripts/thredded/dependencies/textcomplete.js +1 -0
- data/app/assets/javascripts/thredded/dependencies/timeago.js +1 -0
- data/app/assets/javascripts/thredded/dependencies/ujs.js +1 -1
- data/app/assets/stylesheets/thredded/_dependencies.scss +0 -1
- data/app/assets/stylesheets/thredded/_thredded.scss +0 -1
- data/app/assets/stylesheets/thredded/components/_mention-autocomplete.scss +15 -2
- data/app/controllers/concerns/thredded/new_private_topic_params.rb +2 -2
- data/app/controllers/thredded/autocomplete_users_controller.rb +0 -1
- data/app/forms/thredded/private_topic_form.rb +46 -2
- data/app/helpers/thredded/application_helper.rb +12 -14
- data/app/views/thredded/private_topics/_form.html.erb +7 -6
- data/app/views/thredded/topics/_topic.html.erb +2 -2
- data/config/locales/pl.yml +1 -1
- data/lib/thredded.rb +1 -3
- data/lib/thredded/version.rb +1 -1
- data/vendor/assets/javascripts/textcomplete.min.js +1 -0
- metadata +12 -37
- data/app/assets/javascripts/thredded/core/mention_autocompletion.es6 +0 -54
- data/app/assets/javascripts/thredded/dependencies/jquery.js +0 -1
- data/app/assets/stylesheets/thredded/components/_select2.scss +0 -112
- data/vendor/assets/javascripts/jquery.textcomplete.js +0 -1488
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 633ce6690d9ffc55e74596d44c9c6547778700e6
|
4
|
+
data.tar.gz: ab7417716f223e806bf189263da331ebe9b1635f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a513cd6fd50b5b1e3dc4f3af5a3d81719b942df9ef66f27f32c9e874ea1784ec39bd41752c94694bdf80b59fa24b1d203dcb31322d7294f43d1aefd79781197a
|
7
|
+
data.tar.gz: 6ff341b70414e6fdbcb79faf28c97290dae8cedb4be683171ef33fad0453d7b3ac012447d535f460d12cb52f9f3b01a6dfcc09a02f2b875237d56baab00479e1
|
data/README.md
CHANGED
@@ -47,7 +47,6 @@ Table of Contents
|
|
47
47
|
* [Reference your paths so that Thredded can find them](#reference-your-paths-so-that-thredded-can-find-them)
|
48
48
|
* [Add Thredded styles](#add-thredded-styles)
|
49
49
|
* [Add Thredded JavaScripts](#add-thredded-javascripts)
|
50
|
-
* [jQuery version](#jquery-version)
|
51
50
|
* [User profile page](#user-profile-page)
|
52
51
|
* [Customizing views](#customizing-views)
|
53
52
|
* [View hooks](#view-hooks)
|
@@ -99,7 +98,7 @@ Then, see the rest of this Readme for more information about using and customizi
|
|
99
98
|
Add the gem to your Gemfile:
|
100
99
|
|
101
100
|
```ruby
|
102
|
-
gem 'thredded', '~> 0.
|
101
|
+
gem 'thredded', '~> 0.13.0'
|
103
102
|
```
|
104
103
|
|
105
104
|
Add the Thredded [initializer] to your parent app by running the install generator.
|
@@ -230,27 +229,38 @@ Include thredded JavaScripts in your `application.js`:
|
|
230
229
|
|
231
230
|
Thredded is fully compatible with deferred and async script loading.
|
232
231
|
|
233
|
-
#####
|
232
|
+
##### Rails UJS version
|
234
233
|
|
235
|
-
|
236
|
-
|
237
|
-
but if you want to use jQuery v1 or v2, then you need to create a file at
|
238
|
-
`app/assets/javascripts/thredded/dependencies/jquery.js` which contains just `//= require jquery`
|
239
|
-
or `// require jquery2`. If you are not loading jQuery in your app, or if you are already using jQuery v3, then you don't need to do do this (You also don't need to worry about this if you are using the default ["Standalone" layout](#standalone-layout))
|
234
|
+
By default, thredded loads `rails-ujs`. If you're using Rails before v5.1, you need to add `rails-ujs` to
|
235
|
+
your Gemfile.
|
240
236
|
|
241
|
-
|
237
|
+
If you'd like it to use `jquery_ujs` instead, run this command from your app directory:
|
242
238
|
|
243
|
-
|
239
|
+
```bash
|
240
|
+
mkdir -p app/assets/javascripts/thredded/dependencies/
|
241
|
+
printf '//= require jquery3\n//= require jquery_ujs\n' > app/assets/javascripts/thredded/dependencies/ujs.js
|
242
|
+
```
|
244
243
|
|
245
|
-
|
246
|
-
|
244
|
+
##### Timeago version
|
245
|
+
|
246
|
+
By default, thredded loads `timeago.js`.
|
247
|
+
|
248
|
+
If you'd like to use `jquery.timeago` or `rails-timeago` instead, run this command from your app directory:
|
247
249
|
|
248
250
|
```bash
|
249
251
|
mkdir -p app/assets/javascripts/thredded/dependencies/
|
250
|
-
echo '//= require
|
252
|
+
echo '//= require jquery.timeago' > app/assets/javascripts/thredded/dependencies/timeago.js
|
251
253
|
```
|
252
254
|
|
253
|
-
|
255
|
+
You will also need to adjust the `//= require` statements for timeago locales if your site is translated into multiple
|
256
|
+
languages. For `jquery.timeago`, these need to be require after `thredded/dependencies` but before `thredded/thredded`.
|
257
|
+
E.g. for Brazilian Portuguese with jquery.timeago:
|
258
|
+
|
259
|
+
```js
|
260
|
+
//= require thredded/dependencies
|
261
|
+
//= require locales/jquery.timeago.pt-br
|
262
|
+
//= require thredded/thredded
|
263
|
+
```
|
254
264
|
|
255
265
|
#### Thredded page title and ID
|
256
266
|
|
@@ -334,21 +344,11 @@ $thredded-brand: #9c27b0;
|
|
334
344
|
@import "thredded";
|
335
345
|
```
|
336
346
|
|
337
|
-
The `@import "thredded"` directive above will import thredded styles and the [dependencies][thredded-scss-dependencies]
|
338
|
-
(currently just "select2" from [select2-rails]). If you already include your own styles for any of thredded
|
339
|
-
dependencies, you can import just the thredded styles alone like this:
|
340
|
-
|
341
|
-
```scss
|
342
|
-
// application.scss
|
343
|
-
@import "thredded/thredded";
|
344
|
-
```
|
345
|
-
|
346
347
|
If you are writing a Thredded plugin, import the [`thredded/base`][thredded-scss-base] Sass package instead.
|
347
348
|
The `base` package only defines variables, mixins, and %-placeholders, so it can be imported safely without producing
|
348
349
|
any duplicate CSS.
|
349
350
|
|
350
351
|
[thredded-scss-dependencies]: https://github.com/thredded/thredded/blob/master/app/assets/stylesheets/thredded/_dependencies.scss
|
351
|
-
[select2-rails]: https://github.com/argerim/select2-rails
|
352
352
|
[thredded-scss-base]: https://github.com/thredded/thredded/blob/master/app/assets/stylesheets/thredded/_base.scss
|
353
353
|
|
354
354
|
### Email and other notifications
|
@@ -384,13 +384,10 @@ Here are the steps to ensure the best support for your language if it isn't Engl
|
|
384
384
|
|
385
385
|
1. Add `rails-i18n` and `kaminari-i18n` to your Gemfile.
|
386
386
|
|
387
|
-
2. Require the translations for
|
388
|
-
(included in `thredded/dependencies`). E.g. for Brazilian Portuguese:
|
387
|
+
2. Require the translations for timeago.js in your JavaScript. E.g. for Brazilian Portuguese:
|
389
388
|
|
390
389
|
```js
|
391
|
-
//= require
|
392
|
-
//= require locales/jquery.timeago.pt-br
|
393
|
-
//= require thredded/thredded
|
390
|
+
//= require timeago/locales/pt_BR
|
394
391
|
```
|
395
392
|
|
396
393
|
3. To generate URL slugs for messageboards, categories, and topics with support for more language than English,
|
@@ -640,8 +637,8 @@ To achieve the above, all the Thredded code must register onload via
|
|
640
637
|
|
641
638
|
```js
|
642
639
|
window.Thredded.onPageLoad(() => {
|
643
|
-
// Initialize widgets
|
644
|
-
|
640
|
+
// Initialize widgets
|
641
|
+
autosize('textarea');
|
645
642
|
});
|
646
643
|
```
|
647
644
|
|
@@ -657,8 +654,8 @@ e.g.:
|
|
657
654
|
|
658
655
|
```js
|
659
656
|
document.addEventListener('turbolinks:before-cache', () => {
|
660
|
-
// Destroy widgets
|
661
|
-
|
657
|
+
// Destroy widgets
|
658
|
+
autosize.destroy('textarea');
|
662
659
|
});
|
663
660
|
```
|
664
661
|
|
@@ -1,25 +1,32 @@
|
|
1
|
-
|
1
|
+
//= require thredded/core/on_page_load
|
2
|
+
|
3
|
+
(() => {
|
4
|
+
const Thredded = window.Thredded;
|
5
|
+
|
2
6
|
const COMPONENT_SELECTOR = '[data-thredded-currently-online]';
|
7
|
+
const EXPANDED_CLASS = 'thredded--is-expanded';
|
8
|
+
|
9
|
+
const handleMouseEnter = (evt) => {
|
10
|
+
evt.target.classList.add(EXPANDED_CLASS);
|
11
|
+
};
|
12
|
+
|
13
|
+
const handleMouseLeave = (evt) => {
|
14
|
+
evt.target.classList.remove(EXPANDED_CLASS);
|
15
|
+
};
|
16
|
+
|
17
|
+
const handleTouchStart = (evt) => {
|
18
|
+
evt.target.classList.toggle(EXPANDED_CLASS);
|
19
|
+
};
|
3
20
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
}).
|
10
|
-
on('mouseleave', function(e) {
|
11
|
-
$(this).removeClass('thredded--is-expanded');
|
12
|
-
}).
|
13
|
-
on('touchstart', function(e) {
|
14
|
-
$(this).toggleClass('thredded--is-expanded');
|
15
|
-
});
|
16
|
-
}
|
17
|
-
}
|
21
|
+
const initCurrentlyOnline = (node) => {
|
22
|
+
node.addEventListener('mouseenter', handleMouseEnter);
|
23
|
+
node.addEventListener('mouseleave', handleMouseLeave);
|
24
|
+
node.addEventListener('touchstart', handleTouchStart);
|
25
|
+
};
|
18
26
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
}
|
27
|
+
Thredded.onPageLoad(() => {
|
28
|
+
Array.prototype.forEach.call(document.querySelectorAll(COMPONENT_SELECTOR), (node) => {
|
29
|
+
initCurrentlyOnline(node);
|
30
|
+
});
|
24
31
|
});
|
25
|
-
})(
|
32
|
+
})();
|
@@ -1,11 +1,9 @@
|
|
1
|
-
((
|
1
|
+
(() => {
|
2
2
|
const COMPONENT_SELECTOR = '[data-thredded-flash-message]';
|
3
3
|
|
4
|
-
const destroy = () => {
|
5
|
-
$(COMPONENT_SELECTOR).remove();
|
6
|
-
};
|
7
|
-
|
8
4
|
document.addEventListener('turbolinks:before-cache', () => {
|
9
|
-
|
5
|
+
Array.prototype.forEach.call(document.querySelectorAll(COMPONENT_SELECTOR), (node) => {
|
6
|
+
node.parentNode.removeChild(node);
|
7
|
+
});
|
10
8
|
});
|
11
|
-
})(
|
9
|
+
})();
|
@@ -0,0 +1,39 @@
|
|
1
|
+
//= require thredded/components/user_textcomplete
|
2
|
+
|
3
|
+
const ThreddedMentionAutocompletion = {
|
4
|
+
MATCH_RE: /(^@|\s@)"?([\w.,\- ()]+)$/,
|
5
|
+
DROPDOWN_MAX_COUNT: 6,
|
6
|
+
|
7
|
+
init(form, textarea) {
|
8
|
+
const editor = new Textcomplete.editors.Textarea(textarea);
|
9
|
+
const textcomplete = new Textcomplete(editor, {
|
10
|
+
dropdown: {
|
11
|
+
className: Thredded.UserTextcomplete.DROPDOWN_CLASS_NAME,
|
12
|
+
maxCount: ThreddedMentionAutocompletion.DROPDOWN_MAX_COUNT
|
13
|
+
},
|
14
|
+
});
|
15
|
+
textcomplete.on('rendered', function() {
|
16
|
+
if (textcomplete.dropdown.items.length) {
|
17
|
+
textcomplete.dropdown.items[0].activate();
|
18
|
+
}
|
19
|
+
});
|
20
|
+
textcomplete.register([{
|
21
|
+
match: ThreddedMentionAutocompletion.MATCH_RE,
|
22
|
+
search: Thredded.UserTextcomplete.searchFn({
|
23
|
+
url: form.getAttribute('data-autocomplete-url'),
|
24
|
+
autocompleteMinLength: parseInt(form.getAttribute('data-autocomplete-min-length'), 10)
|
25
|
+
}),
|
26
|
+
template: Thredded.UserTextcomplete.formatUser,
|
27
|
+
replace ({name, match}) {
|
28
|
+
let prefix = match[1];
|
29
|
+
if (/[., ()]/.test(name)) {
|
30
|
+
return `${prefix}"${name}" `
|
31
|
+
} else {
|
32
|
+
return `${prefix}${name} `
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}]);
|
36
|
+
}
|
37
|
+
};
|
38
|
+
|
39
|
+
window.ThreddedMentionAutocompletion = ThreddedMentionAutocompletion;
|
@@ -1,42 +1,37 @@
|
|
1
|
-
//= require
|
1
|
+
//= require autosize
|
2
|
+
//= require thredded/core/on_page_load
|
3
|
+
//= require thredded/components/mention_autocompletion
|
4
|
+
//= require thredded/components/preview_area
|
2
5
|
|
3
|
-
((
|
4
|
-
const
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
this.textareaSelector = 'textarea';
|
9
|
-
}
|
6
|
+
(() => {
|
7
|
+
const Thredded = window.Thredded;
|
8
|
+
const ThreddedMentionAutocompletion = window.ThreddedMentionAutocompletion;
|
9
|
+
const ThreddedPreviewArea = window.ThreddedPreviewArea;
|
10
|
+
const autosize = window.autosize;
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
this.autosize($textarea);
|
14
|
-
$nodes.each(function() {
|
15
|
-
new ThreddedPreviewArea($(this));
|
16
|
-
});
|
17
|
-
new ThreddedMentionAutocompletion($).init($nodes);
|
18
|
-
}
|
12
|
+
const COMPONENT_SELECTOR = '[data-thredded-post-form]';
|
13
|
+
const CONTENT_TEXTAREA_SELECTOR = 'textarea[name$="[content]"]';
|
19
14
|
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
const initPostForm = (form) => {
|
16
|
+
const textarea = form.querySelector(CONTENT_TEXTAREA_SELECTOR);
|
17
|
+
autosize(textarea);
|
18
|
+
new ThreddedPreviewArea(form, textarea);
|
19
|
+
ThreddedMentionAutocompletion.init(form, textarea);
|
20
|
+
};
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
22
|
+
const destroyPostForm = (form) => {
|
23
|
+
autosize.destroy(form.querySelector(CONTENT_TEXTAREA_SELECTOR));
|
24
|
+
};
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
26
|
+
Thredded.onPageLoad(() => {
|
27
|
+
Array.prototype.forEach.call(document.querySelectorAll(COMPONENT_SELECTOR), (node) => {
|
28
|
+
initPostForm(node);
|
29
|
+
});
|
34
30
|
});
|
35
31
|
|
36
32
|
document.addEventListener('turbolinks:before-cache', () => {
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
}
|
33
|
+
Array.prototype.forEach.call(document.querySelectorAll(COMPONENT_SELECTOR), (node) => {
|
34
|
+
destroyPostForm(node);
|
35
|
+
});
|
41
36
|
});
|
42
|
-
})(
|
37
|
+
})();
|
@@ -1,28 +1,28 @@
|
|
1
|
-
//= require
|
1
|
+
//= require thredded/core/serialize_form
|
2
2
|
|
3
|
-
(
|
3
|
+
(() => {
|
4
4
|
const PREVIEW_AREA_SELECTOR = '[data-thredded-preview-area]';
|
5
5
|
const PREVIEW_AREA_POST_SELECTOR = '[data-thredded-preview-area-post]';
|
6
6
|
|
7
7
|
class ThreddedPreviewArea {
|
8
8
|
|
9
|
-
constructor(
|
10
|
-
const
|
11
|
-
if (
|
12
|
-
this
|
13
|
-
|
14
|
-
this.
|
15
|
-
this.preview = $preview.get(0);
|
16
|
-
this.previewPost = $form.find(PREVIEW_AREA_POST_SELECTOR).get(0);
|
9
|
+
constructor(form, textarea) {
|
10
|
+
const preview = form.querySelector(PREVIEW_AREA_SELECTOR);
|
11
|
+
if (!preview || !textarea) return;
|
12
|
+
this.form = form;
|
13
|
+
this.preview = preview;
|
14
|
+
this.previewPost = form.querySelector(PREVIEW_AREA_POST_SELECTOR);
|
17
15
|
this.previewUrl = this.preview.getAttribute('data-thredded-preview-url');
|
18
16
|
|
17
|
+
let prevValue = null;
|
19
18
|
const onChange = Thredded.debounce(() => {
|
20
|
-
|
19
|
+
if (prevValue !== textarea.value) {
|
20
|
+
this.updatePreview();
|
21
|
+
prevValue = textarea.value;
|
22
|
+
}
|
21
23
|
}, 200, false);
|
22
24
|
|
23
|
-
|
24
|
-
// Listen to the jQuery change event as that's what is triggered by plugins such as jQuery.textcomplete.
|
25
|
-
$textarea.on('change', onChange);
|
25
|
+
textarea.addEventListener('input', onChange, false);
|
26
26
|
|
27
27
|
this.requestId = 0;
|
28
28
|
}
|
@@ -30,16 +30,20 @@
|
|
30
30
|
updatePreview() {
|
31
31
|
this.requestId++;
|
32
32
|
const requestId = this.requestId;
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
if (
|
33
|
+
const request = new XMLHttpRequest();
|
34
|
+
request.open(this.form.method, this.previewUrl, /* async */ true);
|
35
|
+
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
36
|
+
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
37
|
+
request.onload = () => {
|
38
|
+
if (
|
39
|
+
// Ignore server errors
|
40
|
+
request.status >= 200 && request.status < 400 &&
|
39
41
|
// Ignore older responses received out-of-order
|
40
|
-
this.
|
42
|
+
requestId === this.requestId) {
|
43
|
+
this.onPreviewResponse(request.responseText);
|
41
44
|
}
|
42
|
-
}
|
45
|
+
};
|
46
|
+
request.send(Thredded.serializeForm(this.form));
|
43
47
|
}
|
44
48
|
|
45
49
|
onPreviewResponse(data) {
|
@@ -49,4 +53,4 @@
|
|
49
53
|
}
|
50
54
|
|
51
55
|
window.ThreddedPreviewArea = ThreddedPreviewArea;
|
52
|
-
})(
|
56
|
+
})();
|
@@ -1,5 +1,9 @@
|
|
1
|
+
//= require thredded/core/on_page_load
|
2
|
+
|
1
3
|
(function() {
|
2
|
-
window.Thredded
|
4
|
+
const Thredded = window.Thredded;
|
5
|
+
|
6
|
+
Thredded.onPageLoad(() => {
|
3
7
|
Array.prototype.forEach.call(document.querySelectorAll('[data-thredded-quote-post]'), (el) => {
|
4
8
|
el.addEventListener('click', onClick);
|
5
9
|
});
|
@@ -1,10 +1,25 @@
|
|
1
|
-
((
|
1
|
+
(() => {
|
2
2
|
const COMPONENT_SELECTOR = '#thredded--container [data-time-ago]';
|
3
|
-
|
4
|
-
window
|
5
|
-
const
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
const Thredded = window.Thredded;
|
4
|
+
if ('timeago' in window) {
|
5
|
+
const timeago = window.timeago;
|
6
|
+
Thredded.onPageLoad(() => {
|
7
|
+
const threddedContainer = document.querySelector('#thredded--container');
|
8
|
+
if (!threddedContainer) return;
|
9
|
+
timeago().render(
|
10
|
+
document.querySelectorAll(COMPONENT_SELECTOR),
|
11
|
+
threddedContainer.getAttribute('data-thredded-locale'));
|
12
|
+
});
|
13
|
+
document.addEventListener('turbolinks:before-cache', () => {
|
14
|
+
timeago.cancel();
|
15
|
+
});
|
16
|
+
} else if ('jQuery' in window && 'timeago' in jQuery.fn) {
|
17
|
+
const $ = window.jQuery;
|
18
|
+
Thredded.onPageLoad(() => {
|
19
|
+
const allowFutureWas = $.timeago.settings.allowFuture;
|
20
|
+
$.timeago.settings.allowFuture = true;
|
21
|
+
$(COMPONENT_SELECTOR).timeago();
|
22
|
+
$.timeago.settings.allowFuture = allowFutureWas;
|
23
|
+
});
|
24
|
+
}
|
25
|
+
})();
|
@@ -1,69 +1,87 @@
|
|
1
|
-
|
1
|
+
//= require autosize
|
2
|
+
//= require thredded/core/on_page_load
|
3
|
+
//= require thredded/components/mention_autocompletion
|
4
|
+
//= require thredded/components/preview_area
|
5
|
+
|
6
|
+
(() => {
|
7
|
+
const Thredded = window.Thredded;
|
8
|
+
const ThreddedMentionAutocompletion = window.ThreddedMentionAutocompletion;
|
9
|
+
const ThreddedPreviewArea = window.ThreddedPreviewArea;
|
10
|
+
const autosize = window.autosize;
|
11
|
+
|
2
12
|
const COMPONENT_SELECTOR = '[data-thredded-topic-form]';
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
this.expandedSelector = 'form.thredded--is-expanded';
|
9
|
-
this.escapeElements = 'input, textarea';
|
10
|
-
this.escapeKeyCode = 27;
|
11
|
-
}
|
13
|
+
const TITLE_SELECTOR = '[name$="topic[title]"]';
|
14
|
+
const CONTENT_TEXTAREA_SELECTOR = 'textarea[name$="[content]"]';
|
15
|
+
const COMPACT_CLASS = 'thredded--is-compact';
|
16
|
+
const EXPANDED_CLASS = 'thredded--is-expanded';
|
17
|
+
const ESCAPE_KEY_CODE = 27;
|
12
18
|
|
13
|
-
|
14
|
-
|
19
|
+
const initTopicForm = (form) => {
|
20
|
+
const textarea = form.querySelector(CONTENT_TEXTAREA_SELECTOR);
|
21
|
+
autosize(textarea);
|
22
|
+
new ThreddedPreviewArea(form, textarea);
|
23
|
+
ThreddedMentionAutocompletion.init(form, textarea);
|
24
|
+
|
25
|
+
if (!form.classList.contains(COMPACT_CLASS)) {
|
26
|
+
return;
|
15
27
|
}
|
16
28
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
29
|
+
const title = form.querySelector(TITLE_SELECTOR);
|
30
|
+
title.addEventListener('focus', () => {
|
31
|
+
toggleExpanded(form, true);
|
32
|
+
});
|
33
|
+
|
34
|
+
[title, textarea].forEach((node) => {
|
35
|
+
// Un-expand on Escape key.
|
36
|
+
node.addEventListener('keydown', (evt) => {
|
37
|
+
if (evt.keyCode === ESCAPE_KEY_CODE) {
|
38
|
+
evt.target.blur();
|
39
|
+
toggleExpanded(form, false);
|
40
|
+
}
|
21
41
|
});
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
if (
|
29
|
-
|
30
|
-
e.target.blur();
|
42
|
+
|
43
|
+
// Un-expand on blur if the new focus element is outside of the same form and
|
44
|
+
// all the form inputs are empty.
|
45
|
+
node.addEventListener('blur', () => {
|
46
|
+
// This listener will be fired right after the blur event has finished.
|
47
|
+
const listener = (evt) => {
|
48
|
+
if (!form.contains(evt.target) && !title.value && !textarea.value) {
|
49
|
+
toggleExpanded(form, false);
|
31
50
|
}
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
$blurredElForm.find(this.escapeElements).is(function() {
|
41
|
-
return !this.value;
|
42
|
-
})) {
|
43
|
-
this.toggleExpanded(blurredEl, false);
|
44
|
-
}
|
45
|
-
})
|
46
|
-
});
|
47
|
-
}
|
51
|
+
document.body.removeEventListener('touchend', listener);
|
52
|
+
document.body.removeEventListener('mouseup', listener);
|
53
|
+
};
|
54
|
+
document.body.addEventListener('mouseup', listener);
|
55
|
+
document.body.addEventListener('touchend', listener);
|
56
|
+
})
|
57
|
+
});
|
58
|
+
};
|
48
59
|
|
49
|
-
|
50
|
-
|
60
|
+
const toggleExpanded = (form, expand) => {
|
61
|
+
if (expand) {
|
62
|
+
form.classList.remove(COMPACT_CLASS);
|
63
|
+
form.classList.add(EXPANDED_CLASS);
|
64
|
+
} else {
|
65
|
+
form.classList.remove(EXPANDED_CLASS);
|
66
|
+
form.classList.add(COMPACT_CLASS);
|
51
67
|
}
|
52
|
-
}
|
68
|
+
};
|
53
69
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
70
|
+
const destroyTopicForm = (form) => {
|
71
|
+
autosize.destroy(form.querySelector(CONTENT_TEXTAREA_SELECTOR));
|
72
|
+
};
|
73
|
+
|
74
|
+
Thredded.onPageLoad(() => {
|
75
|
+
Array.prototype.forEach.call(document.querySelectorAll(COMPONENT_SELECTOR), (node) => {
|
76
|
+
initTopicForm(node);
|
77
|
+
});
|
59
78
|
});
|
60
79
|
|
61
80
|
document.addEventListener('turbolinks:before-cache', () => {
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}
|
81
|
+
Array.prototype.forEach.call(document.querySelectorAll(COMPONENT_SELECTOR), (node) => {
|
82
|
+
destroyTopicForm(node);
|
83
|
+
});
|
66
84
|
});
|
67
|
-
})(
|
85
|
+
})();
|
68
86
|
|
69
87
|
|