tramway-admin 1.20.1 → 1.20.2

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