diff --git a/src/static/ckeditor/plugins/html5audio/dialogs/html5audio.js b/src/static/ckeditor/plugins/html5audio/dialogs/html5audio.js
new file mode 100755
index 00000000..fc3d8ecc
--- /dev/null
+++ b/src/static/ckeditor/plugins/html5audio/dialogs/html5audio.js
@@ -0,0 +1,152 @@
+CKEDITOR.dialog.add( 'html5audio', function( editor ) {
+ return {
+ title: editor.lang.html5audio.title,
+ minWidth: 500,
+ minHeight: 100,
+ contents: [ {
+ id: 'info',
+ label: editor.lang.html5audio.infoLabel,
+ elements: [ {
+ type: 'vbox',
+ padding: 0,
+ children: [ {
+ type: 'hbox',
+ widths: [ '365px', '110px' ],
+ align: 'right',
+ children: [ {
+ type: 'text',
+ id: 'url',
+ label: editor.lang.common.url,
+ required: true,
+ validate: CKEDITOR.dialog.validate.notEmpty( editor.lang.html5audio.urlMissing ),
+ setup: function( widget ) {
+ this.setValue( widget.data.src );
+ },
+ commit: function( widget ) {
+ widget.setData( 'src', this.getValue() );
+ }
+ },
+ {
+ type: 'button',
+ id: 'browse',
+ // v-align with the 'txtUrl' field.
+ // TODO: We need something better than a fixed size here.
+ style: 'display:inline-block;margin-top:14px;',
+ align: 'center',
+ label: editor.lang.common.browseServer,
+ hidden: true,
+ filebrowser: 'info:url'
+ } ]
+ } ]
+ },
+ {
+ type: 'hbox',
+ id: 'alignment',
+ children: [ {
+ type: 'radio',
+ id: 'align',
+ label: editor.lang.common.align,
+ items: [
+ [editor.lang.common.alignCenter, 'center'],
+ [editor.lang.common.alignLeft, 'left'],
+ [editor.lang.common.alignRight, 'right'],
+ [editor.lang.common.alignNone, 'none']
+ ],
+ 'default': 'center',
+ setup: function( widget ) {
+ if ( widget.data.align ) {
+ this.setValue( widget.data.align );
+ }
+ },
+ commit: function( widget ) {
+ widget.setData( 'align', this.getValue() );
+ }
+ } ]
+ } ]
+ },
+ {
+ id: 'Upload',
+ hidden: true,
+ filebrowser: 'uploadButton',
+ label: editor.lang.html5audio.upload,
+ elements: [ {
+ type: 'file',
+ id: 'upload',
+ label: editor.lang.html5audio.btnUpload,
+ style: 'height:40px',
+ size: 38
+ },
+ {
+ type: 'fileButton',
+ id: 'uploadButton',
+ filebrowser: 'info:url',
+ label: editor.lang.html5audio.btnUpload,
+ 'for': [ 'Upload', 'upload' ]
+ } ]
+ },
+ {
+ id: 'advanced',
+ label: editor.lang.html5audio.advanced,
+ elements: [ {
+ type: 'vbox',
+ padding: 10,
+ children: [ {
+ type: 'hbox',
+ children: [ {
+ type: 'radio',
+ id: 'autoplay',
+ label: editor.lang.html5audio.autoplay,
+ items: [
+ [editor.lang.html5audio.yes, 'yes'],
+ [editor.lang.html5audio.no, 'no']
+ ],
+ 'default': 'no',
+ setup: function( widget ) {
+ if ( widget.data.autoplay ) {
+ this.setValue( widget.data.autoplay );
+ }
+ },
+ commit: function( widget ) {
+ widget.setData( 'autoplay', this.getValue() );
+ }
+ },
+ {
+ type: 'radio',
+ id: 'allowdownload',
+ label: editor.lang.html5audio.allowdownload,
+ items: [
+ [editor.lang.html5audio.yes, 'yes'],
+ [editor.lang.html5audio.no, 'no']
+ ],
+ 'default': 'no',
+ setup: function( widget ) {
+ if ( widget.data.allowdownload ) {
+ this.setValue(widget.data.allowdownload);
+ }
+ },
+ commit: function( widget ) {
+ widget.setData( 'allowdownload', this.getValue() );
+ }
+ } ]
+ },
+ {
+ type: 'hbox',
+ children: [ {
+ type: "text",
+ id: 'advisorytitle',
+ label: editor.lang.html5audio.advisorytitle,
+ 'default': '',
+ setup: function( widget ) {
+ if ( widget.data.advisorytitle ) {
+ this.setValue(widget.data.advisorytitle);
+ }
+ },
+ commit: function( widget ) {
+ widget.setData( 'advisorytitle', this.getValue() );
+ }
+ } ]
+ } ]
+ } ]
+ } ]
+ };
+} );
diff --git a/src/static/ckeditor/plugins/html5audio/icons/hidpi/html5audio.png b/src/static/ckeditor/plugins/html5audio/icons/hidpi/html5audio.png
new file mode 100644
index 00000000..16f07e72
Binary files /dev/null and b/src/static/ckeditor/plugins/html5audio/icons/hidpi/html5audio.png differ
diff --git a/src/static/ckeditor/plugins/html5audio/icons/html5audio.png b/src/static/ckeditor/plugins/html5audio/icons/html5audio.png
new file mode 100644
index 00000000..59e5fb23
Binary files /dev/null and b/src/static/ckeditor/plugins/html5audio/icons/html5audio.png differ
diff --git a/src/static/ckeditor/plugins/html5audio/lang/en.js b/src/static/ckeditor/plugins/html5audio/lang/en.js
new file mode 100755
index 00000000..fd3bb4f0
--- /dev/null
+++ b/src/static/ckeditor/plugins/html5audio/lang/en.js
@@ -0,0 +1,15 @@
+CKEDITOR.plugins.setLang( 'html5audio', 'en', {
+ button: 'Insert HTML5 audio',
+ title: 'HTML5 audio',
+ infoLabel: 'Audio info',
+ urlMissing: 'Audio source URL is missing.',
+ audioProperties: 'Audio properties',
+ upload: 'Upload',
+ btnUpload: 'Send it to the server',
+ advanced: 'Advanced',
+ autoplay: 'Autoplay?',
+ allowdownload: 'Allow download?',
+ advisorytitle: 'Advisory title',
+ yes: 'Yes',
+ no: 'No'
+} );
diff --git a/src/static/ckeditor/plugins/html5audio/lang/zh-cn.js b/src/static/ckeditor/plugins/html5audio/lang/zh-cn.js
new file mode 100644
index 00000000..a64ac1c3
--- /dev/null
+++ b/src/static/ckeditor/plugins/html5audio/lang/zh-cn.js
@@ -0,0 +1,15 @@
+CKEDITOR.plugins.setLang( 'html5audio', 'zh-cn', {
+ button: '插入HTML5音频',
+ title: 'HTML5 音频',
+ infoLabel: '音频信息',
+ urlMissing: '音频URL',
+ audioProperties: '音频属性',
+ upload: '上传',
+ btnUpload: '上传到服务器',
+ advanced: '高级',
+ autoplay: '自动播放?',
+ allowdownload: '允许下载?',
+ advisorytitle: '提示语',
+ yes: '是',
+ no: '否'
+} );
diff --git a/src/static/ckeditor/plugins/html5audio/plugin.js b/src/static/ckeditor/plugins/html5audio/plugin.js
new file mode 100755
index 00000000..5e8cf0d4
--- /dev/null
+++ b/src/static/ckeditor/plugins/html5audio/plugin.js
@@ -0,0 +1,139 @@
+CKEDITOR.plugins.add( 'html5audio', {
+ requires: 'widget',
+ lang: 'bg,ca,de,de-ch,el,en,eu,es,fr,ru,uk,uz,zh-cn,fa,pl',
+ icons: 'html5audio',
+ hidpi: true,
+ init: function( editor ) {
+ editor.widgets.add( 'html5audio', {
+ button: editor.lang.html5audio.button,
+ template: '
', // We add the audio element when needed in the data function, to avoid having an undefined src attribute.
+ // See issue #9 on github: https://github.com/iametza/ckeditor-html5-audio/issues/9
+ editables: {},
+ /*
+ * Allowed content rules (http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules):
+ * - div-s with text-align,float,margin-left,margin-right inline style rules and required ckeditor-html5-audio class.
+ * - audio tags with src and controls attributes.
+ */
+ allowedContent: 'div(!ckeditor-html5-audio){text-align,float,margin-left,margin-right}; audio[src,controls,controlslist,autoplay];',
+ requiredContent: 'div(ckeditor-html5-audio); audio[src,controls];',
+ upcast: function( element ) {
+ return element.name === 'div' && element.hasClass( 'ckeditor-html5-audio' );
+ },
+ dialog: 'html5audio',
+ init: function() {
+ var audioElement = this.element.findOne( 'audio' );
+ var src = '';
+ var autoplay = '';
+ var align = this.element.getStyle( 'text-align' );
+ var allowdownload = false;
+ var advisorytitle = '';
+
+ // If there's a child (the audio element)
+ if ( audioElement ) {
+ // get it's attributes.
+ src = audioElement.getAttribute( 'src' );
+ autoplay = audioElement.getAttribute( 'autoplay' );
+ allowdownload = !audioElement.getAttribute( 'controlslist' );
+ advisorytitle = audioElement.getAttribute( 'title' );
+ }
+
+ if ( src ) {
+ this.setData( 'src', src );
+
+ if ( align ) {
+ this.setData( 'align', align );
+ } else {
+ this.setData( 'align', 'none' );
+ }
+
+ if ( autoplay ) {
+ this.setData( 'autoplay', 'yes' );
+ }
+
+ if ( allowdownload ) {
+ this.setData( 'allowdownload', 'yes' );
+ }
+
+ if ( advisorytitle ) {
+ this.setData( 'advisorytitle', advisorytitle );
+ }
+ }
+ },
+ data: function() {
+ var audioElement = this.element.findOne( 'audio' );
+ // If there is an audio source
+ if ( this.data.src ) {
+ // and there isn't a child (the audio element)
+ if ( !audioElement ) {
+ // Create a new