text: CKEDITOR.dialog.add('audio', function (editor) {
      var lang = editor.lang.audio;
      
      function commitValue(audioNode, extraStyles) {
          var value = this.getValue();
          
          if (!value && this.id == 'id')
              value = generateId();
          
          audioNode.setAttribute(this.id, value);
          
          if (!value)
              return;
          switch (this.id) {
              case 'poster':
                  extraStyles.backgroundImage = 'url(' + value + ')';
                  break;
              case 'width':
                  extraStyles.width = value + 'px';
                  break;
              case 'height':
                  extraStyles.height = value + 'px';
                  break;
          }
      }
      
      function commitSrc(audioNode, extraStyles, audios) {
          var match = this.id.match(/(\w+)(\d)/),
              id = match[1],
              number = parseInt(match[2], 10);
          
          var audio = audios[number] || (audios[number] = {});
          audio[id] = this.getValue();
      }
      
      function loadValue(audioNode) {
          if (audioNode)
              this.setValue(audioNode.getAttribute(this.id));
          else {
              if (this.id == 'id')
                  this.setValue(generateId());
          }
      }
      
      function loadSrc(audioNode, audios) {
          var match = this.id.match(/(\w+)(\d)/),
              id = match[1],
              number = parseInt(match[2], 10);
          
          var audio = audios[number];
          if (!audio)
              return;
          this.setValue(audio[id]);
      }
      
      function generateId() {
          var now = new Date();
          return 'audio' + now.getFullYear() + now.getMonth() + now.getDate() + now.getHours() + now.getMinutes() + now.getSeconds();
      }
      
      // To automatically get the dimensions of the poster image
      var onImgLoadEvent = function () {
          // Image is ready.
          var preview = this.previewImage;
          preview.removeListener('load', onImgLoadEvent);
          preview.removeListener('error', onImgLoadErrorEvent);
          preview.removeListener('abort', onImgLoadErrorEvent);
          
          this.setValueOf('info', 'width', preview.$.width);
          this.setValueOf('info', 'height', preview.$.height);
      };
      
      var onImgLoadErrorEvent = function () {
          // Error. Image is not loaded.
          var preview = this.previewImage;
          preview.removeListener('load', onImgLoadEvent);
          preview.removeListener('error', onImgLoadErrorEvent);
          preview.removeListener('abort', onImgLoadErrorEvent);
      };
      
      return {
          title: lang.dialogTitle,
          minWidth: 400,
          minHeight: 200,
          
          onShow: function () {
              // Clear previously saved elements.
              this.fakeImage = this.audioNode = null;
              // To get dimensions of poster image
              this.previewImage = editor.document.createElement('img');
              
              var fakeImage = this.getSelectedElement();
              if (fakeImage && fakeImage.data('cke-real-element-type') && fakeImage.data('cke-real-element-type') == 'audio') {
                  this.fakeImage = fakeImage;
                  
                  var audioNode = editor.restoreRealElement(fakeImage),
                      audios = [],
                      sourceList = audioNode.getElementsByTag('source', '');
                  if (sourceList.count() == 0)
                      sourceList = audioNode.getElementsByTag('source', 'cke');
                  
                  for (var i = 0, length = sourceList.count(); i < length; i++) {
                      var item = sourceList.getItem(i);
                      audios.push({src: item.getAttribute('src'), type: item.getAttribute('type')});
                  }
                  
                  this.audioNode = audioNode;
                  
                  this.setupContent(audioNode, audios);
              } else
                  this.setupContent(null, []);
          },
          
          onOk: function () {
              // If there's no selected element create one. Otherwise, reuse it
              var audioNode = null;
              if (!this.fakeImage) {
                  audioNode = CKEDITOR.dom.element.createFromHtml('<cke:audio></cke:audio>', editor.document);
                  audioNode.setAttributes(
                      {
                          controls: 'controls'
                      });
              } else {
                  audioNode = this.audioNode;
              }
              
              var extraStyles = {}, audios = [];
              this.commitContent(audioNode, extraStyles, audios);
              
              var innerHtml = '', links = '',
                  link = lang.linkTemplate || '',
                  fallbackTemplate = lang.fallbackTemplate || '';
              for (var i = 0; i < audios.length; i++) {
                  var audio = audios[i];
                  if (!audio || !audio.src)
                      continue;
                  innerHtml += '<cke:source src="' + audio.src + '" type="' + audio.type + '" />';
                  links += link.replace('%src%', audio.src).replace('%type%', audio.type);
              }
              audioNode.setHtml(innerHtml + fallbackTemplate.replace('%links%', links));
              
              // Refresh the fake image.
              var newFakeImage = editor.createFakeElement(audioNode, 'cke_audio', 'audio', false);
              newFakeImage.setStyles(extraStyles);
              if (this.fakeImage) {
                  newFakeImage.replace(this.fakeImage);
                  editor.getSelection().selectElement(newFakeImage);
              } else {
                  // Insert it in a div
                  var div = new CKEDITOR.dom.element('DIV', editor.document);
                  editor.insertElement(div);
                  div.append(newFakeImage);
              }
          },
          onHide: function () {
              if (this.previewImage) {
                  this.previewImage.removeListener('load', onImgLoadEvent);
                  this.previewImage.removeListener('error', onImgLoadErrorEvent);
                  this.previewImage.removeListener('abort', onImgLoadErrorEvent);
                  this.previewImage.remove();
                  this.previewImage = null;		// Dialog is closed.
              }
          },
          
          contents:
              [
                  {
                      id: 'info',
                      elements:
                          [
                              {
                                  type: 'hbox',
                                  widths: ['', '100px'],
                                  children: [
                                      {
                                          type: 'text',
                                          id: 'poster',
                                          label: lang.poster,
                                          commit: commitValue,
                                          setup: loadValue,
                                          onChange: function () {
                                              var dialog = this.getDialog(),
                                                  newUrl = this.getValue();
                                              
                                              //Update preview image
                                              if (newUrl.length > 0)	//Prevent from load before onShow
                                              {
                                                  dialog = this.getDialog();
                                                  var preview = dialog.previewImage;
                                                  
                                                  preview.on('load', onImgLoadEvent, dialog);
                                                  preview.on('error', onImgLoadErrorEvent, dialog);
                                                  preview.on('abort', onImgLoadErrorEvent, dialog);
                                                  preview.setAttribute('src', newUrl);
                                              }
                                          }
                                      },
                                      {
                                          type: 'button',
                                          id: 'browse',
                                          hidden: 'true',
                                          style: 'display:inline-block;margin-top:21px;',
                                          filebrowser:
                                              {
                                                  action: 'Browse',
                                                  target: 'info:poster',
                                                  url: editor.config.filebrowserImageBrowseUrl || editor.config.filebrowserBrowseUrl
                                              },
                                          label: editor.lang.common.browseServer
                                      }]
                              },
                              {
                                  type: 'hbox',
                                  widths: ['33%', '33%', '33%'],
                                  children: [
                                      {
                                          type: 'text',
                                          id: 'width',
                                          label: editor.lang.common.width,
                                          'default': 400,
                                          validate: CKEDITOR.dialog.validate.notEmpty(lang.widthRequired),
                                          commit: commitValue,
                                          setup: loadValue
                                      },
                                      {
                                          type: 'text',
                                          id: 'height',
                                          label: editor.lang.common.height,
                                          'default': 300,
                                          validate: CKEDITOR.dialog.validate.notEmpty(lang.heightRequired),
                                          commit: commitValue,
                                          setup: loadValue
                                      },
                                      {
                                          type: 'text',
                                          id: 'id',
                                          label: 'Id',
                                          commit: commitValue,
                                          setup: loadValue
                                      }
                                  ]
                              },
                              {
                                  type: 'hbox',
                                  widths: ['', '100px', '75px'],
                                  children: [
                                      {
                                          type: 'text',
                                          id: 'src0',
                                          label: lang.sourceaudio,
                                          commit: commitSrc,
                                          setup: loadSrc
                                      },
                                      {
                                          type: 'button',
                                          id: 'browse',
                                          hidden: 'true',
                                          style: 'display:inline-block;margin-top:21px;',
                                          filebrowser:
                                              {
                                                  action: 'Browse',
                                                  target: 'info:src0',
                                                  url: editor.config.filebrowserAudioBrowseUrl || editor.config.filebrowserBrowseUrl
                                              },
                                          label: editor.lang.common.browseServer
                                      },
                                      {
                                          id: 'type0',
                                          label: lang.sourceType,
                                          type: 'select',
                                          'default': 'audio/mp3',
                                          items:
                                              [
                                                  ['MP3', 'audio/mp3'],
                                                  ['WAV', 'audio/wav']
                                              ],
                                          commit: commitSrc,
                                          setup: loadSrc
                                      }]
                              },
                              
                              {
                                  type: 'hbox',
                                  widths: ['', '100px', '75px'],
                                  children: [
                                      {
                                          type: 'text',
                                          id: 'src1',
                                          label: lang.sourceaudio,
                                          commit: commitSrc,
                                          setup: loadSrc
                                      },
                                      {
                                          type: 'button',
                                          id: 'browse',
                                          hidden: 'true',
                                          style: 'display:inline-block;margin-top:21px;',
                                          filebrowser:
                                              {
                                                  action: 'Browse',
                                                  target: 'info:src1',
                                                  url: editor.config.filebrowserAudioBrowseUrl || editor.config.filebrowserBrowseUrl
                                              },
                                          label: editor.lang.common.browseServer
                                      },
                                      {
                                          id: 'type1',
                                          label: lang.sourceType,
                                          type: 'select',
                                          'default': 'audio/wav',
                                          items:
                                              [
                                                  ['MP3', 'audio/mp3'],
                                                  ['WAV', 'audio/wav']
                                              ],
                                          commit: commitSrc,
                                          setup: loadSrc
                                      }]
                              }
                          ]
                  }
              
              ]
      };
  });