tramway-admin 1.20.1 → 1.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -2
  3. data/app/assets/javascripts/ckeditor/config.js +4 -3
  4. data/app/assets/javascripts/ckeditor/plugins/youtube/images/icon-hdpi.png +0 -0
  5. data/app/assets/javascripts/ckeditor/plugins/youtube/images/icon.png +0 -0
  6. data/app/assets/javascripts/ckeditor/plugins/youtube/lang/en.js +25 -0
  7. data/app/assets/javascripts/ckeditor/plugins/youtube/lang/ru.js +25 -0
  8. data/app/assets/javascripts/ckeditor/plugins/youtube/plugin.js +449 -0
  9. data/app/helpers/tramway/admin/records_helper.rb +2 -1
  10. data/lib/tramway/admin/version.rb +1 -1
  11. metadata +7 -70
  12. data/app/assets/javascripts/ckeditor/plugins/image/lang/af.js +0 -25
  13. data/app/assets/javascripts/ckeditor/plugins/image/lang/ar.js +0 -25
  14. data/app/assets/javascripts/ckeditor/plugins/image/lang/az.js +0 -25
  15. data/app/assets/javascripts/ckeditor/plugins/image/lang/bg.js +0 -25
  16. data/app/assets/javascripts/ckeditor/plugins/image/lang/bn.js +0 -25
  17. data/app/assets/javascripts/ckeditor/plugins/image/lang/bs.js +0 -25
  18. data/app/assets/javascripts/ckeditor/plugins/image/lang/ca.js +0 -25
  19. data/app/assets/javascripts/ckeditor/plugins/image/lang/cs.js +0 -25
  20. data/app/assets/javascripts/ckeditor/plugins/image/lang/cy.js +0 -25
  21. data/app/assets/javascripts/ckeditor/plugins/image/lang/da.js +0 -25
  22. data/app/assets/javascripts/ckeditor/plugins/image/lang/de-ch.js +0 -25
  23. data/app/assets/javascripts/ckeditor/plugins/image/lang/de.js +0 -25
  24. data/app/assets/javascripts/ckeditor/plugins/image/lang/el.js +0 -25
  25. data/app/assets/javascripts/ckeditor/plugins/image/lang/en-au.js +0 -25
  26. data/app/assets/javascripts/ckeditor/plugins/image/lang/en-ca.js +0 -25
  27. data/app/assets/javascripts/ckeditor/plugins/image/lang/en-gb.js +0 -25
  28. data/app/assets/javascripts/ckeditor/plugins/image/lang/eo.js +0 -25
  29. data/app/assets/javascripts/ckeditor/plugins/image/lang/es-mx.js +0 -25
  30. data/app/assets/javascripts/ckeditor/plugins/image/lang/es.js +0 -25
  31. data/app/assets/javascripts/ckeditor/plugins/image/lang/et.js +0 -25
  32. data/app/assets/javascripts/ckeditor/plugins/image/lang/eu.js +0 -25
  33. data/app/assets/javascripts/ckeditor/plugins/image/lang/fa.js +0 -25
  34. data/app/assets/javascripts/ckeditor/plugins/image/lang/fi.js +0 -25
  35. data/app/assets/javascripts/ckeditor/plugins/image/lang/fo.js +0 -25
  36. data/app/assets/javascripts/ckeditor/plugins/image/lang/fr-ca.js +0 -25
  37. data/app/assets/javascripts/ckeditor/plugins/image/lang/fr.js +0 -25
  38. data/app/assets/javascripts/ckeditor/plugins/image/lang/gl.js +0 -25
  39. data/app/assets/javascripts/ckeditor/plugins/image/lang/gu.js +0 -25
  40. data/app/assets/javascripts/ckeditor/plugins/image/lang/he.js +0 -25
  41. data/app/assets/javascripts/ckeditor/plugins/image/lang/hi.js +0 -25
  42. data/app/assets/javascripts/ckeditor/plugins/image/lang/hr.js +0 -25
  43. data/app/assets/javascripts/ckeditor/plugins/image/lang/hu.js +0 -25
  44. data/app/assets/javascripts/ckeditor/plugins/image/lang/id.js +0 -25
  45. data/app/assets/javascripts/ckeditor/plugins/image/lang/is.js +0 -25
  46. data/app/assets/javascripts/ckeditor/plugins/image/lang/it.js +0 -25
  47. data/app/assets/javascripts/ckeditor/plugins/image/lang/ja.js +0 -25
  48. data/app/assets/javascripts/ckeditor/plugins/image/lang/ka.js +0 -25
  49. data/app/assets/javascripts/ckeditor/plugins/image/lang/km.js +0 -25
  50. data/app/assets/javascripts/ckeditor/plugins/image/lang/ko.js +0 -25
  51. data/app/assets/javascripts/ckeditor/plugins/image/lang/ku.js +0 -25
  52. data/app/assets/javascripts/ckeditor/plugins/image/lang/lt.js +0 -25
  53. data/app/assets/javascripts/ckeditor/plugins/image/lang/lv.js +0 -25
  54. data/app/assets/javascripts/ckeditor/plugins/image/lang/mk.js +0 -25
  55. data/app/assets/javascripts/ckeditor/plugins/image/lang/mn.js +0 -25
  56. data/app/assets/javascripts/ckeditor/plugins/image/lang/ms.js +0 -25
  57. data/app/assets/javascripts/ckeditor/plugins/image/lang/nb.js +0 -25
  58. data/app/assets/javascripts/ckeditor/plugins/image/lang/nl.js +0 -25
  59. data/app/assets/javascripts/ckeditor/plugins/image/lang/no.js +0 -25
  60. data/app/assets/javascripts/ckeditor/plugins/image/lang/oc.js +0 -25
  61. data/app/assets/javascripts/ckeditor/plugins/image/lang/pl.js +0 -25
  62. data/app/assets/javascripts/ckeditor/plugins/image/lang/pt-br.js +0 -25
  63. data/app/assets/javascripts/ckeditor/plugins/image/lang/pt.js +0 -25
  64. data/app/assets/javascripts/ckeditor/plugins/image/lang/ro.js +0 -25
  65. data/app/assets/javascripts/ckeditor/plugins/image/lang/si.js +0 -25
  66. data/app/assets/javascripts/ckeditor/plugins/image/lang/sk.js +0 -25
  67. data/app/assets/javascripts/ckeditor/plugins/image/lang/sl.js +0 -25
  68. data/app/assets/javascripts/ckeditor/plugins/image/lang/sq.js +0 -25
  69. data/app/assets/javascripts/ckeditor/plugins/image/lang/sr-latn.js +0 -25
  70. data/app/assets/javascripts/ckeditor/plugins/image/lang/sr.js +0 -25
  71. data/app/assets/javascripts/ckeditor/plugins/image/lang/sv.js +0 -25
  72. data/app/assets/javascripts/ckeditor/plugins/image/lang/th.js +0 -25
  73. data/app/assets/javascripts/ckeditor/plugins/image/lang/tr.js +0 -25
  74. data/app/assets/javascripts/ckeditor/plugins/image/lang/tt.js +0 -25
  75. data/app/assets/javascripts/ckeditor/plugins/image/lang/ug.js +0 -25
  76. data/app/assets/javascripts/ckeditor/plugins/image/lang/uk.js +0 -25
  77. data/app/assets/javascripts/ckeditor/plugins/image/lang/vi.js +0 -25
  78. data/app/assets/javascripts/ckeditor/plugins/image/lang/zh-cn.js +0 -25
  79. data/app/assets/javascripts/ckeditor/plugins/image/lang/zh.js +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6aee5db3732b7fc7b50bd8f3ea9c8c0a3995c2b8c672cad75f81835e67672a58
4
- data.tar.gz: 65d394e432da53939aa369352bea71ce381a01bc13d5520eba4998e9680a3571
3
+ metadata.gz: 2a2390d02f234a6031e5d73c8bb61f41bd5c1a77283c37dbb41f1fed9dc1186d
4
+ data.tar.gz: 7e60ff75d36704556651ccc50da1eb734ae60df9a27ef12d79fd88acedf0f668
5
5
  SHA512:
6
- metadata.gz: bf76db73861ba917c79e4e876c2e6570d323d9e58fc25e3428106ddff283e3bb4ce9b07688e88f15ea4112462a2c07f1be539880585fc4efda30cca339f98888
7
- data.tar.gz: 0bd22bce1018e38c3905239e57652148530f8230bd0310246b568d19162e834d0788582a461aa624ff050a280e2b36e7911f635bd14264c3998046653d88ada8
6
+ metadata.gz: 291eb2087dad80bcc5856234ed3a239a4dd60b083305723610f2434e163a16907b1c5fab842facb36e1925347ddf6d5a346f4ce73a5de611a9857ff8bac258e1
7
+ data.tar.gz: 7568b0bbb7222425137630a3b969b07b4cfdea6b5a6a766a6ba0840f0683b9b47175e0cadb6a22d39f43bf2a958e2fd6dd600c161469eb403aae24db766cf2b3
data/README.md CHANGED
@@ -66,6 +66,19 @@ $> Tramway::User::User.create! email: 'your@email.com', password: '123456789', r
66
66
  ::Tramway::Auth.root_path = '/admin' # you need it to redirect in the admin panel after admin signed_in
67
67
  ```
68
68
 
69
+ By default users with role `admin` have access to all models used as arguments in method `::Tramway::Admin.set_available_models`. If you want specify models by roles, use them as keys
70
+
71
+ ```ruby
72
+ ::Tramway::Admin.set_available_models ::Tramway::Event::Event, ::Tramway::Event::ParticipantFormField,
73
+ ::Tramway::Event::Participant, ::Tramway::Landing::Block, ::Tramway::User::User,
74
+ ::Tramway::Profiles::SocialNetwork, project: #{project_name_which_you_used_in_application_name}, role: :admin
75
+
76
+ ::Tramway::Admin.set_available_models ::Tramway::Event::Event, ::Tramway::Event::ParticipantFormField,
77
+ ::Tramway::Event::Participant, project: #{project_name_which_you_used_in_application_name}, role: :another_role
78
+ ```
79
+
80
+ Here docs about changing roles of `Tramway::User::User` model [Readme](https://github.com/ulmic/tramway-dev/tree/develop/tramway#if-you-want-to-edit-roles-to-the-tramwayuseruser-class)
81
+
69
82
  Run server `rails s`
70
83
  Launch `localhost:3000/admin`
71
84
 
@@ -95,9 +108,11 @@ To add notification to application, you need just set queries in initializers.
95
108
  ```ruby
96
109
  ::Tramway::Admin.set_notificable_queries :"#{your_title}" => -> { your_query }
97
110
 
98
- # Example from tramway-event gem
111
+ # Example from tramway-event gem (you also can push context variables here)
99
112
 
100
- ::Tramway::Admin.set_notificable_queries new_participants: -> { ::Tramway::Event::Participant.active.where(participation_state: :requested) }
113
+ ::Tramway::Admin.set_notificable_queries new_participants: -> (current_user) do
114
+ ::Tramway::Event::Participant.active.where(participation_state: :requested).send "#{current_user}_scope", current_user.id
115
+ end
101
116
  ```
102
117
 
103
118
  ## Contributing
@@ -1,4 +1,5 @@
1
1
  CKEDITOR.editorConfig = function( config ) {
2
+ config.extraPlugins = 'youtube';
2
3
  config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
3
4
  config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
4
5
  config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
@@ -11,12 +12,12 @@ CKEDITOR.editorConfig = function( config ) {
11
12
  { name: 'document', groups: [ 'mode', 'document', 'doctools' ], items: [ 'Source'] },
12
13
  { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
13
14
  { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
14
- { name: 'insert', items: [ 'Image', 'Flash', 'Table', 'HorizontalRule', 'SpecialChar' ] },
15
+ { name: 'insert', items: [ 'Youtube', 'Image', 'Flash', 'Table', 'HorizontalRule', 'SpecialChar'] },
15
16
  { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
16
17
  '/',
17
18
  { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
18
19
  { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
19
- { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] }
20
+ { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
20
21
  ];
21
22
 
22
23
  config.toolbar_mini = [
@@ -25,5 +26,5 @@ CKEDITOR.editorConfig = function( config ) {
25
26
  { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
26
27
  { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
27
28
  { name: 'insert', items: [ 'Image', 'Table', 'HorizontalRule', 'SpecialChar' ] }
28
- ];
29
+ ];
29
30
  };
@@ -0,0 +1,25 @@
1
+ CKEDITOR.plugins.setLang('youtube', 'en', {
2
+ button : 'Embed YouTube Video',
3
+ title : 'Embed YouTube Video',
4
+ txtEmbed : 'Paste Embed Code Here',
5
+ txtUrl : 'Paste YouTube Video URL',
6
+ txtWidth : 'Width',
7
+ txtHeight : 'Height',
8
+ chkRelated : 'Show suggested videos at the video\'s end',
9
+ txtStartAt : 'Start at (ss or mm:ss or hh:mm:ss)',
10
+ chkPrivacy : 'Enable privacy-enhanced mode',
11
+ chkOlderCode : 'Use old embed code',
12
+ chkAutoplay: 'Autoplay',
13
+ chkControls: 'Show player controls',
14
+ noCode : 'You must input an embed code or URL',
15
+ invalidEmbed : 'The embed code you\'ve entered doesn\'t appear to be valid',
16
+ invalidUrl : 'The URL you\'ve entered doesn\'t appear to be valid',
17
+ or : 'or',
18
+ noWidth : 'You must inform the width',
19
+ invalidWidth : 'Inform a valid width',
20
+ noHeight : 'You must inform the height',
21
+ invalidHeight : 'Inform a valid height',
22
+ invalidTime : 'Inform a valid start time',
23
+ txtResponsive : 'Make Responsive (ignore width and height, fit to width)',
24
+ txtNoEmbed : 'Video image and link only'
25
+ });
@@ -0,0 +1,25 @@
1
+ CKEDITOR.plugins.setLang('youtube', 'ru', {
2
+ button : 'Вставить YouTube видео',
3
+ title : 'Вставить YouTube видео',
4
+ txtEmbed : 'Вставьте HTML-код сюда',
5
+ txtUrl : 'Вставьте адрес видео (URL)',
6
+ txtWidth : 'Ширина',
7
+ txtHeight : 'Высота',
8
+ chkRelated : 'Показать похожие видео после завершения просмотра',
9
+ txtStartAt : 'Начать с (сс или мм:сс или чч:мм:сс)',
10
+ chkPrivacy : 'Включить режим повышенной конфиденциальности',
11
+ chkOlderCode : 'Использовать старый код вставки',
12
+ chkAutoplay: 'Автозапуск',
13
+ chkControls: 'Показать панель управления',
14
+ noCode : 'Вы должны ввести HTML-код или адрес',
15
+ invalidEmbed : 'Ваш HTML-код не похож на правильный',
16
+ invalidUrl : 'Ваш адрес видео не похож на правильный',
17
+ or : 'или',
18
+ noWidth : 'Вы должны указать ширину',
19
+ invalidWidth : 'Укажите правильную ширину',
20
+ noHeight : 'Вы должны указать высоту',
21
+ invalidHeight : 'Укажите правильную высоту',
22
+ invalidTime : 'Укажите правильное время начала',
23
+ txtResponsive : 'Растягиваемое видео',
24
+ txtNoEmbed : 'Не встраивать видео (обложка-ссылка на YouTube)'
25
+ });
@@ -0,0 +1,449 @@
1
+ /*
2
+ * Youtube Embed Plugin
3
+ *
4
+ * @author Jonnas Fonini <jonnasfonini@gmail.com>
5
+ * @version 2.1.14
6
+ */
7
+ (function () {
8
+ CKEDITOR.plugins.add('youtube', {
9
+ lang: [ 'en', 'bg', 'pt', 'pt-br', 'ja', 'hu', 'it', 'fr', 'tr', 'ru', 'de', 'ar', 'nl', 'pl', 'vi', 'zh', 'el', 'he', 'es', 'nb', 'nn', 'fi', 'et', 'sk', 'cs', 'ko', 'eu', 'uk'],
10
+ init: function (editor) {
11
+ editor.addCommand('youtube', new CKEDITOR.dialogCommand('youtube', {
12
+ allowedContent: 'div{*}(*); iframe{*}[!width,!height,!src,!frameborder,!allowfullscreen,!allow]; object param[*]; a[*]; img[*]'
13
+ }));
14
+
15
+ editor.ui.addButton('Youtube', {
16
+ label : editor.lang.youtube.button,
17
+ toolbar : 'insert',
18
+ command : 'youtube',
19
+ icon : this.path + 'images/icon.png'
20
+ });
21
+
22
+ CKEDITOR.dialog.add('youtube', function (instance) {
23
+ var video,
24
+ disabled = editor.config.youtube_disabled_fields || [];
25
+
26
+ return {
27
+ title : editor.lang.youtube.title,
28
+ minWidth : 510,
29
+ minHeight : 200,
30
+ onShow: function () {
31
+ for (var i = 0; i < disabled.length; i++) {
32
+ this.getContentElement('youtubePlugin', disabled[i]).disable();
33
+ }
34
+ },
35
+ contents :
36
+ [{
37
+ id : 'youtubePlugin',
38
+ expand : true,
39
+ elements :
40
+ [{
41
+ id : 'txtEmbed',
42
+ type : 'textarea',
43
+ label : editor.lang.youtube.txtEmbed,
44
+ onChange : function (api) {
45
+ handleEmbedChange(this, api);
46
+ },
47
+ onKeyUp : function (api) {
48
+ handleEmbedChange(this, api);
49
+ },
50
+ validate : function () {
51
+ if (this.isEnabled()) {
52
+ if (!this.getValue()) {
53
+ alert(editor.lang.youtube.noCode);
54
+ return false;
55
+ }
56
+ else
57
+ if (this.getValue().length === 0 || this.getValue().indexOf('//') === -1) {
58
+ alert(editor.lang.youtube.invalidEmbed);
59
+ return false;
60
+ }
61
+ }
62
+ }
63
+ },
64
+ {
65
+ type : 'html',
66
+ html : editor.lang.youtube.or + '<hr>'
67
+ },
68
+ {
69
+ type : 'hbox',
70
+ widths : [ '70%', '15%', '15%' ],
71
+ children :
72
+ [
73
+ {
74
+ id : 'txtUrl',
75
+ type : 'text',
76
+ label : editor.lang.youtube.txtUrl,
77
+ onChange : function (api) {
78
+ handleLinkChange(this, api);
79
+ },
80
+ onKeyUp : function (api) {
81
+ handleLinkChange(this, api);
82
+ },
83
+ validate : function () {
84
+ if (this.isEnabled()) {
85
+ if (!this.getValue()) {
86
+ alert(editor.lang.youtube.noCode);
87
+ return false;
88
+ }
89
+ else{
90
+ video = ytVidId(this.getValue());
91
+
92
+ if (this.getValue().length === 0 || video === false)
93
+ {
94
+ alert(editor.lang.youtube.invalidUrl);
95
+ return false;
96
+ }
97
+ }
98
+ }
99
+ }
100
+ },
101
+ {
102
+ type : 'text',
103
+ id : 'txtWidth',
104
+ width : '60px',
105
+ label : editor.lang.youtube.txtWidth,
106
+ 'default' : editor.config.youtube_width != null ? editor.config.youtube_width : '640',
107
+ validate : function () {
108
+ if (this.getValue()) {
109
+ var width = parseInt (this.getValue()) || 0;
110
+
111
+ if (width === 0) {
112
+ alert(editor.lang.youtube.invalidWidth);
113
+ return false;
114
+ }
115
+ }
116
+ else {
117
+ alert(editor.lang.youtube.noWidth);
118
+ return false;
119
+ }
120
+ }
121
+ },
122
+ {
123
+ type : 'text',
124
+ id : 'txtHeight',
125
+ width : '60px',
126
+ label : editor.lang.youtube.txtHeight,
127
+ 'default' : editor.config.youtube_height != null ? editor.config.youtube_height : '360',
128
+ validate : function () {
129
+ if (this.getValue()) {
130
+ var height = parseInt(this.getValue()) || 0;
131
+
132
+ if (height === 0) {
133
+ alert(editor.lang.youtube.invalidHeight);
134
+ return false;
135
+ }
136
+ }
137
+ else {
138
+ alert(editor.lang.youtube.noHeight);
139
+ return false;
140
+ }
141
+ }
142
+ }
143
+ ]
144
+ },
145
+ {
146
+ type : 'hbox',
147
+ widths : [ '55%', '45%' ],
148
+ children :
149
+ [
150
+ {
151
+ id : 'chkResponsive',
152
+ type : 'checkbox',
153
+ label : editor.lang.youtube.txtResponsive,
154
+ 'default' : editor.config.youtube_responsive != null ? editor.config.youtube_responsive : false
155
+ },
156
+ {
157
+ id : 'chkNoEmbed',
158
+ type : 'checkbox',
159
+ label : editor.lang.youtube.txtNoEmbed,
160
+ 'default' : editor.config.youtube_noembed != null ? editor.config.youtube_noembed : false
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ type : 'hbox',
166
+ widths : [ '55%', '45%' ],
167
+ children :
168
+ [
169
+ {
170
+ id : 'chkRelated',
171
+ type : 'checkbox',
172
+ 'default' : editor.config.youtube_related != null ? editor.config.youtube_related : true,
173
+ label : editor.lang.youtube.chkRelated
174
+ },
175
+ {
176
+ id : 'chkOlderCode',
177
+ type : 'checkbox',
178
+ 'default' : editor.config.youtube_older != null ? editor.config.youtube_older : false,
179
+ label : editor.lang.youtube.chkOlderCode
180
+ }
181
+ ]
182
+ },
183
+ {
184
+ type : 'hbox',
185
+ widths : [ '55%', '45%' ],
186
+ children :
187
+ [
188
+ {
189
+ id : 'chkPrivacy',
190
+ type : 'checkbox',
191
+ label : editor.lang.youtube.chkPrivacy,
192
+ 'default' : editor.config.youtube_privacy != null ? editor.config.youtube_privacy : false
193
+ },
194
+ {
195
+ id : 'chkAutoplay',
196
+ type : 'checkbox',
197
+ 'default' : editor.config.youtube_autoplay != null ? editor.config.youtube_autoplay : false,
198
+ label : editor.lang.youtube.chkAutoplay
199
+ }
200
+ ]
201
+ },
202
+ {
203
+ type : 'hbox',
204
+ widths : [ '55%', '45%'],
205
+ children :
206
+ [
207
+ {
208
+ id : 'txtStartAt',
209
+ type : 'text',
210
+ label : editor.lang.youtube.txtStartAt,
211
+ validate : function () {
212
+ if (this.getValue()) {
213
+ var str = this.getValue();
214
+
215
+ if (!/^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$/i.test(str)) {
216
+ alert(editor.lang.youtube.invalidTime);
217
+ return false;
218
+ }
219
+ }
220
+ }
221
+ },
222
+ {
223
+ id : 'chkControls',
224
+ type : 'checkbox',
225
+ 'default' : editor.config.youtube_controls != null ? editor.config.youtube_controls : true,
226
+ label : editor.lang.youtube.chkControls
227
+ }
228
+ ]
229
+ }
230
+ ]
231
+ }
232
+ ],
233
+ onOk: function()
234
+ {
235
+ var content = '';
236
+ var responsiveStyle = '';
237
+
238
+ if (this.getContentElement('youtubePlugin', 'txtEmbed').isEnabled()) {
239
+ content = this.getValueOf('youtubePlugin', 'txtEmbed');
240
+ }
241
+ else {
242
+ var url = 'https://', params = [], startSecs, paramAutoplay='';
243
+ var width = this.getValueOf('youtubePlugin', 'txtWidth');
244
+ var height = this.getValueOf('youtubePlugin', 'txtHeight');
245
+
246
+ if (this.getContentElement('youtubePlugin', 'chkPrivacy').getValue() === true) {
247
+ url += 'www.youtube-nocookie.com/';
248
+ }
249
+ else {
250
+ url += 'www.youtube.com/';
251
+ }
252
+
253
+ url += 'embed/' + video;
254
+
255
+ if (this.getContentElement('youtubePlugin', 'chkRelated').getValue() === false) {
256
+ params.push('rel=0');
257
+ }
258
+
259
+ if (this.getContentElement('youtubePlugin', 'chkAutoplay').getValue() === true) {
260
+ params.push('autoplay=1');
261
+ paramAutoplay='autoplay';
262
+ }
263
+
264
+ if (this.getContentElement('youtubePlugin', 'chkControls').getValue() === false) {
265
+ params.push('controls=0');
266
+ }
267
+
268
+ startSecs = this.getValueOf('youtubePlugin', 'txtStartAt');
269
+
270
+ if (startSecs) {
271
+ var seconds = hmsToSeconds(startSecs);
272
+
273
+ params.push('start=' + seconds);
274
+ }
275
+
276
+ if (params.length > 0) {
277
+ url = url + '?' + params.join('&');
278
+ }
279
+
280
+ if (this.getContentElement('youtubePlugin', 'chkResponsive').getValue() === true) {
281
+ content += '<div class="youtube-embed-wrapper" style="position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden">';
282
+ responsiveStyle = 'style="position:absolute;top:0;left:0;width:100%;height:100%"';
283
+ }
284
+
285
+ if (this.getContentElement('youtubePlugin', 'chkOlderCode').getValue() === true) {
286
+ url = url.replace('embed/', 'v/');
287
+ url = url.replace(/&/g, '&amp;');
288
+
289
+ if (url.indexOf('?') === -1) {
290
+ url += '?';
291
+ }
292
+ else {
293
+ url += '&amp;';
294
+ }
295
+ url += 'hl=' + (this.getParentEditor().config.language ? this.getParentEditor().config.language : 'en') + '&amp;version=3';
296
+
297
+ content += '<object width="' + width + '" height="' + height + '" ' + responsiveStyle + '>';
298
+ content += '<param name="movie" value="' + url + '"></param>';
299
+ content += '<param name="allowFullScreen" value="true"></param>';
300
+ content += '<param name="allowscriptaccess" value="always"></param>';
301
+ content += '<embed src="' + url + '" type="application/x-shockwave-flash" ';
302
+ content += 'width="' + width + '" height="' + height + '" '+ responsiveStyle + ' allowscriptaccess="always" ';
303
+ content += 'allowfullscreen="true"></embed>';
304
+ content += '</object>';
305
+ }
306
+ else
307
+ if (this.getContentElement('youtubePlugin', 'chkNoEmbed').getValue() === true) {
308
+ var imgSrc = 'https://img.youtube.com/vi/' + video + '/sddefault.jpg';
309
+ content += '<a href="' + url + '" ><img width="' + width + '" height="' + height + '" src="' + imgSrc + '" ' + responsiveStyle + '/></a>';
310
+ }
311
+ else {
312
+ content += '<iframe ' + (paramAutoplay ? 'allow="' + paramAutoplay + ';" ' : '') + 'width="' + width + '" height="' + height + '" src="' + url + '" ' + responsiveStyle;
313
+ content += 'frameborder="0" allowfullscreen></iframe>';
314
+ }
315
+
316
+ if (this.getContentElement('youtubePlugin', 'chkResponsive').getValue() === true) {
317
+ content += '</div>';
318
+ }
319
+ }
320
+
321
+ var element = CKEDITOR.dom.element.createFromHtml(content);
322
+ var instance = this.getParentEditor();
323
+ instance.insertElement(element);
324
+ }
325
+ };
326
+ });
327
+ }
328
+ });
329
+ })();
330
+
331
+ function handleLinkChange(el, api) {
332
+ var video = ytVidId(el.getValue());
333
+ var time = ytVidTime(el.getValue());
334
+
335
+ if (el.getValue().length > 0) {
336
+ el.getDialog().getContentElement('youtubePlugin', 'txtEmbed').disable();
337
+ }
338
+ else if (!disabled.length || !disabled.includes('txtEmbed')) {
339
+ el.getDialog().getContentElement('youtubePlugin', 'txtEmbed').enable();
340
+ }
341
+
342
+ if (video && time) {
343
+ var seconds = timeParamToSeconds(time);
344
+ var hms = secondsToHms(seconds);
345
+ el.getDialog().getContentElement('youtubePlugin', 'txtStartAt').setValue(hms);
346
+ }
347
+ }
348
+
349
+ function handleEmbedChange(el, api) {
350
+ if (el.getValue().length > 0) {
351
+ el.getDialog().getContentElement('youtubePlugin', 'txtUrl').disable();
352
+ }
353
+ else {
354
+ el.getDialog().getContentElement('youtubePlugin', 'txtUrl').enable();
355
+ }
356
+ }
357
+
358
+
359
+ /**
360
+ * JavaScript function to match (and return) the video Id
361
+ * of any valid Youtube Url, given as input string.
362
+ * @author: Stephan Schmitz <eyecatchup@gmail.com>
363
+ * @url: http://stackoverflow.com/a/10315969/624466
364
+ */
365
+ function ytVidId(url) {
366
+ var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
367
+ return (url.match(p)) ? RegExp.$1 : false;
368
+ }
369
+
370
+ /**
371
+ * Matches and returns time param in YouTube Urls.
372
+ */
373
+ function ytVidTime(url) {
374
+ var p = /t=([0-9hms]+)/;
375
+ return (url.match(p)) ? RegExp.$1 : false;
376
+ }
377
+
378
+ /**
379
+ * Converts time in hms format to seconds only
380
+ */
381
+ function hmsToSeconds(time) {
382
+ var arr = time.split(':'), s = 0, m = 1;
383
+
384
+ while (arr.length > 0) {
385
+ s += m * parseInt(arr.pop(), 10);
386
+ m *= 60;
387
+ }
388
+
389
+ return s;
390
+ }
391
+
392
+ /**
393
+ * Converts seconds to hms format
394
+ */
395
+ function secondsToHms(seconds) {
396
+ var h = Math.floor(seconds / 3600);
397
+ var m = Math.floor((seconds / 60) % 60);
398
+ var s = seconds % 60;
399
+
400
+ var pad = function (n) {
401
+ n = String(n);
402
+ return n.length >= 2 ? n : "0" + n;
403
+ };
404
+
405
+ if (h > 0) {
406
+ return pad(h) + ':' + pad(m) + ':' + pad(s);
407
+ }
408
+ else {
409
+ return pad(m) + ':' + pad(s);
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Converts time in youtube t-param format to seconds
415
+ */
416
+ function timeParamToSeconds(param) {
417
+ var componentValue = function (si) {
418
+ var regex = new RegExp('(\\d+)' + si);
419
+ return param.match(regex) ? parseInt(RegExp.$1, 10) : 0;
420
+ };
421
+
422
+ return componentValue('h') * 3600
423
+ + componentValue('m') * 60
424
+ + componentValue('s');
425
+ }
426
+
427
+ /**
428
+ * Converts seconds into youtube t-param value, e.g. 1h4m30s
429
+ */
430
+ function secondsToTimeParam(seconds) {
431
+ var h = Math.floor(seconds / 3600);
432
+ var m = Math.floor((seconds / 60) % 60);
433
+ var s = seconds % 60;
434
+ var param = '';
435
+
436
+ if (h > 0) {
437
+ param += h + 'h';
438
+ }
439
+
440
+ if (m > 0) {
441
+ param += m + 'm';
442
+ }
443
+
444
+ if (s > 0) {
445
+ param += s + 's';
446
+ }
447
+
448
+ return param;
449
+ }