diff --git a/_config.php b/_config.php index 748106b2b..fea04185e 100644 --- a/_config.php +++ b/_config.php @@ -32,6 +32,7 @@ Object::useCustomClass('Datetime', 'SS_Datetime', true); define('MCE_ROOT', FRAMEWORK_DIR . '/thirdparty/tinymce/'); ShortcodeParser::get('default')->register('file_link', array('File', 'link_shortcode_handler')); +ShortcodeParser::get('default')->register('embed', array('Oembed', 'handle_shortcode')); /** * The secret key that needs to be sent along with pings to /Email_BounceHandler diff --git a/_config/Oembed.yml b/_config/Oembed.yml new file mode 100644 index 000000000..41226d09b --- /dev/null +++ b/_config/Oembed.yml @@ -0,0 +1,22 @@ +name: Oembed +--- +Oembed: + providers: + 'http://*.youtube.com/watch*': + 'http://www.youtube.com/oembed/' + 'http://*.flickr.com/*': + 'http://www.flickr.com/services/oembed/' + 'http://*.viddler.com/*': + 'http://lab.viddler.com/services/oembed/' + 'http://*.revision3.com/*': + 'http://revision3.com/api/oembed/' + 'http://*.hulu.com/watch/*': + 'http://www.hulu.com/api/oembed.json' + 'http://*.vimeo.com/*': + 'http://www.vimeo.com/api/oembed.json' + 'https://twitter.com/*': + 'https://api.twitter.com/1/statuses/oembed.json' + 'http://twitter.com/*': + 'https://api.twitter.com/1/statuses/oembed.json' + autodiscover: + true diff --git a/admin/_config.php b/admin/_config.php index cf8c14086..6a6f1a573 100644 --- a/admin/_config.php +++ b/admin/_config.php @@ -20,7 +20,7 @@ HtmlEditorConfig::get('cms')->enablePlugins('media', 'fullscreen'); HtmlEditorConfig::get('cms')->enablePlugins(array('ssbuttons' => sprintf('../../../%s/tinymce_ssbuttons/editor_plugin_src.js', THIRDPARTY_DIR))); HtmlEditorConfig::get('cms')->insertButtonsBefore('formatselect', 'styleselect'); -HtmlEditorConfig::get('cms')->addButtonsToLine(2, 'ssimage', 'ssflash', 'sslink', 'unlink', 'anchor', 'separator','code', 'fullscreen', 'separator'); +HtmlEditorConfig::get('cms')->addButtonsToLine(2, 'ssmedia', 'ssflash', 'sslink', 'unlink', 'anchor', 'separator','code', 'fullscreen', 'separator'); HtmlEditorConfig::get('cms')->removeButtons('tablecontrols'); HtmlEditorConfig::get('cms')->addButtonsToLine(3, 'tablecontrols'); diff --git a/docs/en/topics/rich-text-editing.md b/docs/en/topics/rich-text-editing.md index f9a900100..c33027afc 100644 --- a/docs/en/topics/rich-text-editing.md +++ b/docs/en/topics/rich-text-editing.md @@ -111,8 +111,8 @@ so this is considered advanced usage of the field. :::php // File: mysite/_config.php HtmlEditorConfig::get('cms')->disablePlugins('ssbuttons'); - HtmlEditorConfig::get('cms')->removeButtons('sslink', 'ssimage'); - HtmlEditorConfig::get('cms')->addButtonsToLine(2, 'link', 'image'); + HtmlEditorConfig::get('cms')->removeButtons('sslink', 'ssmedia'); + HtmlEditorConfig::get('cms')->addButtonsToLine(2, 'link', 'media'); ### Developing a wrapper to use a different WYSIWYG editors with HTMLEditorField @@ -126,4 +126,4 @@ or start your own configuration. ## Related - * [Howto: Extend the CMS Interface](../howto/extend-cms-interface) \ No newline at end of file + * [Howto: Extend the CMS Interface](../howto/extend-cms-interface) diff --git a/forms/HtmlEditorField.php b/forms/HtmlEditorField.php index 271da6152..8df190866 100644 --- a/forms/HtmlEditorField.php +++ b/forms/HtmlEditorField.php @@ -391,6 +391,13 @@ class HtmlEditorField_Toolbar extends RequestHandler { $fromCMS->addExtraClass('content'); $selectComposite->addExtraClass('content-select'); + $fromWeb = new CompositeField( + new LiteralField('headerURL', '

' . sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.ADDURL', 'Add URL')) . '

'), + $remoteURL = new TextField('RemoteURL', ''), + new LiteralField('addURLImage', '') + ); + $remoteURL->addExtraClass('remoteurl'); + Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css'); $computerUploadField = Object::create('UploadField', 'AssetUploadField', ''); $computerUploadField->setConfig('previewMaxWidth', 40); @@ -401,11 +408,15 @@ class HtmlEditorField_Toolbar extends RequestHandler { $computerUploadField->setFolderName(Upload::$uploads_folder); $tabSet = new TabSet( - "MediaFormInsertImageTabs", + "MediaFormInsertMediaTabs", new Tab( _t('HtmlEditorField.FROMCOMPUTER','From your computer'), $computerUploadField ), + new Tab( + _t('HtmlEditorField.FROMWEB', 'From the web'), + $fromWeb + ), new Tab( _t('HtmlEditorField.FROMCMS','From the CMS'), $fromCMS @@ -423,19 +434,19 @@ class HtmlEditorField_Toolbar extends RequestHandler { $fields = new FieldList( new LiteralField( 'Heading', - sprintf('

%s

', _t('HtmlEditorField.INSERTIMAGE', 'Insert Image')). - sprintf('

%s

', _t('HtmlEditorField.UpdateIMAGE', 'Update Image')) + sprintf('

%s

', _t('HtmlEditorField.INSERTMEDIA', 'Insert Media')). + sprintf('

%s

', _t('HtmlEditorField.UpdateMEDIA', 'Update Media')) ), $allFields ); $actions = new FieldList( - FormAction::create('insertimage', _t('HtmlEditorField.BUTTONINSERT', 'Insert')) - ->addExtraClass('ss-ui-action-constructive image-insert') + FormAction::create('insertmedia', _t('HtmlEditorField.BUTTONINSERT', 'Insert')) + ->addExtraClass('ss-ui-action-constructive media-insert') ->setAttribute('data-icon', 'accept') ->setUseButtonTag(true), - FormAction::create('insertimage', _t('HtmlEditorField.BUTTONUpdate', 'Update')) - ->addExtraClass('ss-ui-action-constructive image-update') + FormAction::create('insertmedia', _t('HtmlEditorField.BUTTONUpdate', 'Update')) + ->addExtraClass('ss-ui-action-constructive media-update') ->setAttribute('data-icon', 'accept') ->setUseButtonTag(true) ); @@ -493,6 +504,8 @@ class HtmlEditorField_Toolbar extends RequestHandler { // Instanciate file wrapper and get fields based on its type if($file && $file->appCategory() == 'image') { $fileWrapper = new HtmlEditorField_Image($url, $file); + } elseif(!Director::is_site_url($url)) { + $fileWrapper = new HtmlEditorField_Embed($url, $file); } else { $fileWrapper = new HtmlEditorField_File($url, $file); } @@ -516,7 +529,9 @@ class HtmlEditorField_Toolbar extends RequestHandler { protected function getFieldsForFile($url, $file) { $fields = $this->extend('getFieldsForFile', $url, $file); if(!$fields) { - if($file->Extension == 'swf') { + if($file instanceof HtmlEditorField_Embed) { + $fields = $this->getFieldsForOembed($url, $file); + } elseif($file->Extension == 'swf') { $fields = $this->getFieldsForFlash($url, $file); } else { $fields = $this->getFieldsForImage($url, $file); @@ -529,6 +544,75 @@ class HtmlEditorField_Toolbar extends RequestHandler { return $fields; } + /** + * @return FieldList + */ + protected function getFieldsForOembed($url, $file) { + if(isset($file->Oembed->thumbnail_url)) { + $thumbnailURL = $file->Oembed->thumbnail_url; + } elseif($file->Type == 'photo') { + $thumbnailURL = $file->Oembed->url; + } else { + $thumbnailURL = $url; + } + + $previewField = new LiteralField("ImageFull", + "{$file->Name}\n" + ); + + $fields = new FieldList( + $filePreview = CompositeField::create( + CompositeField::create( + $previewField + )->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'), + CompositeField::create( + CompositeField::create( + new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type') . ':', $file->Type), + $urlField = new ReadonlyField('ClickableURL', _t('AssetTableField.URL','URL'), + sprintf('%s', $url, $url) + ) + ) + )->setName("FilePreviewData")->addExtraClass('cms-file-info-data') + )->setName("FilePreview")->addExtraClass('cms-file-info'), + new TextField('CaptionText', _t('HtmlEditorField.CAPTIONTEXT', 'Caption text')), + new DropdownField( + 'CSSClass', + _t('HtmlEditorField.CSSCLASS', 'Alignment / style'), + array( + 'left' => _t('HtmlEditorField.CSSCLASSLEFT', 'On the left, with text wrapping around.'), + 'leftAlone' => _t('HtmlEditorField.CSSCLASSLEFTALONE', 'On the left, on its own.'), + 'right' => _t('HtmlEditorField.CSSCLASSRIGHT', 'On the right, with text wrapping around.'), + 'center' => _t('HtmlEditorField.CSSCLASSCENTER', 'Centered, on its own.'), + ) + ), + $dimensionsField = new FieldGroup(_t('HtmlEditorField.IMAGEDIMENSIONS', 'Dimensions'), + $widthField = new TextField('Width', _t('HtmlEditorField.IMAGEWIDTHPX', 'Width'), $file->Width), + $heightField = new TextField('Height', " x " . _t('HtmlEditorField.IMAGEHEIGHTPX', 'Height'), $file->Height) + ) + ); + $urlField->dontEscape = true; + $dimensionsField->addExtraClass('dimensions'); + $widthField->setMaxLength(5); + $heightField->setMaxLength(5); + + if($file->Type == 'photo') { + $filePreview->FieldList()->insertBefore(new TextField( + 'AltText', + _t('HtmlEditorField.IMAGEALTTEXT', 'Alternative text (alt) - shown if image cannot be displayed'), + $file->Title, + 80 + ), 'CaptionText'); + $filePreview->FieldList()->insertBefore(new TextField( + 'Title', + _t('HtmlEditorField.IMAGETITLE', 'Title text (tooltip) - for additional information about the image') + ), 'CaptionText'); + } + + $this->extend('updateFieldsForImage', $fields, $url, $file); + + return $fields; + } + /** * @return FieldList */ @@ -552,8 +636,8 @@ class HtmlEditorField_Toolbar extends RequestHandler { * @return FieldList */ protected function getFieldsForImage($url, $file) { - if($file instanceof Image) { - $formattedImage = $file->FormattedImage('SetWidth', Image::$asset_preview_width); + if($file->File instanceof Image) { + $formattedImage = $file->File->generateFormattedImage('SetWidth', Image::$asset_preview_width); $thumbnailURL = $formattedImage ? $formattedImage->URL : $url; } else { $thumbnailURL = $url; @@ -719,6 +803,52 @@ class HtmlEditorField_File extends ViewableData { } +class HtmlEditorField_Embed extends HtmlEditorField_File { + protected $oembed; + + public function __construct($url, $file = null) { + parent::__construct($url, $file); + $this->oembed = Oembed::get_oembed_from_url($url); + if(!$this->oembed) { + return Controller::curr()->httpError(404, 'The URL ' . $url . ' could not be turned into a media resource.'); + } + } + + public function getWidth() { + return $this->oembed->Width; + } + + public function getHeight() { + return $this->oembed->Height; + } + + public function getPreview() { + if(isset($this->oembed->thumbnail_url)) { + return sprintf('', $this->oembed->thumbnail_url); + } + } + + public function getName() { + if(isset($this->oembed->title)) { + return $this->oembed->title; + } else { + return parent::getName(); + } + } + + public function getType() { + return $this->oembed->type; + } + + public function getOembed() { + return $this->oembed; + } + + public function appCategory() { + return 'embed'; + } +} + class HtmlEditorField_Image extends HtmlEditorField_File { protected $width; diff --git a/javascript/HtmlEditorField.js b/javascript/HtmlEditorField.js index 84da7e25b..e9ff08725 100644 --- a/javascript/HtmlEditorField.js +++ b/javascript/HtmlEditorField.js @@ -683,7 +683,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE; var self = this, ed = this.getEditor(), node = $(ed.getSelectedNode()); // TODO Depends on managed mime type if(node.is('img')) { - this.showFileView(node.attr('src'), function() { + this.showFileView(node.data('url') || node.attr('src'), function() { $(this).updateFromNode(node); self.toggleCloseButton(); self.redraw(); @@ -711,9 +711,9 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE; var updateExisting = Boolean(this.find('.ss-htmleditorfield-file').length); this.find('.htmleditorfield-mediaform-heading.insert')[updateExisting ? 'hide' : 'show'](); - this.find('.Actions .image-insert')[updateExisting ? 'hide' : 'show'](); + this.find('.Actions .media-insert')[updateExisting ? 'hide' : 'show'](); this.find('.htmleditorfield-mediaform-heading.update')[updateExisting ? 'show' : 'hide'](); - this.find('.Actions .image-update')[updateExisting ? 'show' : 'hide'](); + this.find('.Actions .media-update')[updateExisting ? 'show' : 'hide'](); }, resetFields: function() { var ed = this.getEditor(), node = $(ed.getSelectedNode()); @@ -796,6 +796,21 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE; }); + /** + * Show the second step after adding a URL + */ + $('form.htmleditorfield-form.htmleditorfield-mediaform img.add-url').entwine({ + onclick: function(e) { + var form = this.closest('form'); + + var urlField = this.closest('.CompositeField').find('input.remoteurl'); + + form.showFileView(urlField.val()); + form.redraw(); + } + + }); + /** * Represents a single selected file, together with a set of form fields to edit its properties. * Overload this based on the media type to determine how the HTML should be created. @@ -985,6 +1000,60 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE; } }); + + /** + * Insert an oembed object tag into the content. + * Requires the 'media' plugin for serialization of tags into placeholders. + */ + $('form.htmleditorfield-mediaform .ss-htmleditorfield-file.embed').entwine({ + getAttributes: function() { + var width = this.find(':input[name=Width]').val(), + height = this.find(':input[name=Height]').val(); + return { + 'src' : this.find('.thumbnail-preview').attr('src'), + 'width' : width ? parseInt(width, 10) : null, + 'height' : height ? parseInt(height, 10) : null, + 'class' : this.find(':input[name=CSSClass]').val() + }; + }, + getExtraData: function() { + var width = this.find(':input[name=Width]').val(), + height = this.find(':input[name=Height]').val(); + return { + 'CaptionText': this.find(':input[name=CaptionText]').val(), + 'Url': this.find(':input[name=URL]').val(), + 'thumbnail': this.find('.thumbnail-preview').attr('src'), + 'width' : width ? parseInt(width, 10) : null, + 'height' : height ? parseInt(height, 10) : null, + 'cssclass': this.find(':input[name=CSSClass]').val() + }; + }, + getHTML: function() { + var el, + attrs = this.getAttributes(), + extraData = this.getExtraData(), + // imgEl = $(''); + imgEl = $('').attr(attrs).addClass('ss-htmleditorfield-file embed'); + + $.each(extraData, function (key, value) { + imgEl.attr('data-' + key, value) + }); + + if(extraData.CaptionText) { + el = $('

' + extraData.CaptionText + '

').prepend(imgEl); + } else { + el = imgEl; + } + return $('
').append(el).html(); // Little hack to get outerHTML string + }, + updateFromNode: function(node) { + this.find(':input[name=Width]').val(node.width()); + this.find(':input[name=Height]').val(node.height()); + this.find(':input[name=Title]').val(node.attr('title')); + this.find(':input[name=CSSClass]').val(node.data('cssclass')); + } + }); + $('form.htmleditorfield-mediaform .ss-htmleditorfield-file .dimensions :input').entwine({ OrigVal: null, onmatch: function () { diff --git a/lang/en.yml b/lang/en.yml index 0bc966800..2bcd97fc9 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -255,7 +255,7 @@ en: IMAGEHEIGHTPX: Height IMAGETITLE: 'Title text (tooltip) - for additional information about the image' IMAGEWIDTHPX: Width - INSERTIMAGE: 'Insert Image' + INSERTMEDIA: 'Insert Media' LINK: 'Insert Link' LINKANCHOR: 'Anchor on this page' LINKDESCR: 'Link description' diff --git a/oembed/Oembed.php b/oembed/Oembed.php new file mode 100644 index 000000000..8609dfeb3 --- /dev/null +++ b/oembed/Oembed.php @@ -0,0 +1,192 @@ +get('Oembed', 'autodiscover'); + } + + public static function get_providers() { + return Config::inst()->get('Oembed', 'providers'); + } + + protected static function match_url($url) { + foreach(self::get_providers() as $scheme=>$endpoint) { + if(self::match_scheme($url, $scheme)) { + return $endpoint; + } + } + return false; + } + + protected static function match_scheme($url, $scheme) { + $urlInfo = parse_url($url); + $schemeInfo = parse_url($scheme); + foreach($schemeInfo as $k=>$v) { + if(!array_key_exists($k, $urlInfo)) { + return false; + } + if(strpos($v, '*') !== false) { + $v = preg_quote($v, '/'); + $v = str_replace('\*', '.*', $v); + if($k == 'host') { + $v = str_replace('*\.', '*', $v); + } + if(!preg_match('/' . $v . '/', $urlInfo[$k])) { + return false; + } + } elseif(strcasecmp($urlInfo[$k], $v)) { + return false; + } + } + return true; + } + + protected static function autodiscover_from_url($url) { + $service = new RestfulService($url); + $body = $service->request(); + if(!$body || $body->isError()) { + return false; + } + $body = $body->getBody(); + + if(preg_match_all('#]+?(?:href=[\'"](.+?)[\'"][^>]+?)?type=["\']application/json\+oembed["\'](?:[^>]+?href=[\'"](.+?)[\'"])?#', $body, $matches, PREG_SET_ORDER)) { + $match = $matches[0]; + if(!empty($match[1])) { + return html_entity_decode($match[1]); + } + if(!empty($match[2])) { + return html_entity_decode($match[2]); + } + } + return false; + } + + public static function get_oembed_from_url($url, $type = false, Array $options = array()) { + $endpoint = self::match_url($url); + $ourl = false; + if(!$endpoint) { + if(self::get_autodiscover()) { + $ourl = self::autodiscover_from_url($url); + } + } elseif($endpoint === true) { + $ourl = self::autodiscover_from_url($url); + } else { + $ourl = Controller::join_links($endpoint, '?format=json&url=' . rawurlencode($url)); + } + if($ourl) { + if($options) { + if(isset($options['width']) && !isset($options['maxwidth'])) { + $options['maxwidth'] = $options['width']; + } + if(isset($options['height']) && !isset($options['maxheight'])) { + $options['maxheight'] = $options['height']; + } + $ourl = Controller::join_links($ourl, '?' . http_build_query($options, '', '&')); + } + return new Oembed_Result($ourl, $url, $type, $options); + } + return false; + } + + public static function handle_shortcode($arguments, $url, $parser, $shortcode) { + if(isset($arguments['type'])) { + $type = $arguments['type']; + unset($arguments['type']); + } else { + $type = false; + } + $oembed = self::get_oembed_from_url($url, $type, $arguments); + if($oembed && $oembed->exists()) { + return $oembed->forTemplate(); + } else { + return '' . $url . ''; + } + } +} + +class Oembed_Result extends ViewableData { + protected $data = false; + protected $origin = false; + protected $type = false; + protected $url; + protected $extraClass; + + public static $casting = array( + 'html' => 'HTMLText', + ); + + public function __construct($url, $origin = false, $type = false, Array $options = array()) { + $this->url = $url; + $this->origin = $origin; + $this->type = $type; + + if(isset($options['class'])) { + $this->extraClass = $options['class']; + } + + parent::__construct(); + } + + protected function loadData() { + if($this->data !== false) { + return; + } + $service = new RestfulService($this->url); + $body = $service->request(); + if(!$body || $body->isError()) { + $this->data = array(); + return; + } + $body = $body->getBody(); + $data = json_decode($body, true); + if(!$data) { + $data = array(); + } + foreach($data as $k=>$v) { + unset($data[$k]); + $data[strtolower($k)] = $v; + } + if($this->type && $this->type != $data['type']) { + $data = array(); + } + $this->data = $data; + } + + public function hasField($field) { + $this->loadData(); + return array_key_exists(strtolower($field), $this->data); + } + + public function getField($field) { + $field = strtolower($field); + if($this->hasField($field)) { + return $this->data[$field]; + } + } + + public function forTemplate() { + $this->loadData(); + switch($this->Type) { + case 'video': + case 'rich': + if($this->extraClass) { + return "
$this->HTML
"; + } else { + return $this->HTML; + } + break; + case 'link': + return '' . $this->Title . ''; + break; + case 'photo': + return ""; + break; + } + } + + public function exists() { + $this->loadData(); + return count($this->data) > 0; + } +} + diff --git a/thirdparty/tinymce/plugins/fullscreen/fullscreen.htm b/thirdparty/tinymce/plugins/fullscreen/fullscreen.htm index ffe528e41..f9d87a6d8 100644 --- a/thirdparty/tinymce/plugins/fullscreen/fullscreen.htm +++ b/thirdparty/tinymce/plugins/fullscreen/fullscreen.htm @@ -23,7 +23,7 @@ // Patch callbacks, make them point to window.opener patchCallback(settings, 'urlconverter_callback'); patchCallback(settings, 'insertlink_callback'); - patchCallback(settings, 'insertimage_callback'); + patchCallback(settings, 'insertmedia_callback'); patchCallback(settings, 'setupcontent_callback'); patchCallback(settings, 'save_callback'); patchCallback(settings, 'onchange_callback'); diff --git a/thirdparty/tinymce_ssbuttons/editor_plugin_src.js b/thirdparty/tinymce_ssbuttons/editor_plugin_src.js index 195972305..c73fa2ff1 100644 --- a/thirdparty/tinymce_ssbuttons/editor_plugin_src.js +++ b/thirdparty/tinymce_ssbuttons/editor_plugin_src.js @@ -29,13 +29,13 @@ init : function(ed, url) { ed.addButton('sslink', {title : ed.getLang('tinymce_ssbuttons.insertlink'), cmd : 'sslink', 'class' : 'mce_link'}); - ed.addButton('ssimage', {title : ed.getLang('tinymce_ssbuttons.insertimage'), cmd : 'ssimage', 'class' : 'mce_image'}); + ed.addButton('ssmedia', {title : ed.getLang('tinymce_ssbuttons.insertmedia'), cmd : 'ssmedia', 'class' : 'mce_image'}); ed.addCommand('sslink', function(ed) { jQuery('#' + this.id).entwine('ss').openLinkDialog(); }); - ed.addCommand('ssimage', function(ed) { + ed.addCommand('ssmedia', function(ed) { jQuery('#' + this.id).entwine('ss').openMediaDialog(); }); @@ -44,6 +44,63 @@ cm.setDisabled('sslink', co && n.nodeName != 'A'); cm.setActive('sslink', n.nodeName == 'A' && !n.name); }); + + ed.onSaveContent.add(function(ed, o) { + var content = jQuery(o.content); + content.find('.ss-htmleditorfield-file.embed').each(function() { + var el = jQuery(this); + var shortCode = '[embed width=' + el.data('width') + + ' height=' + el.data('height') + + ' class=' + el.data('cssclass') + + ' thumbnail=' + el.data('thumbnail') + + ']' + el.data('url') + + '[/embed]'; + el.replaceWith(shortCode); + }); + o.content = jQuery('
').append(content).html(); // Little hack to get outerHTML string + }); + + var shortTagRegex = /(.?)\[embed(.*?)\](.+?)\[\/\s*embed\s*\](.?)/gi; + ed.onBeforeSetContent.add(function(ed, o) { + var matches = null, content = o.content; + var prefix, suffix, attributes, attributeString, url; + var attrs, attr; + var imgEl; + while((matches = shortTagRegex.exec(content))) { + prefix = matches[1]; + suffix = matches[4]; + if(prefix === '[' && suffix === ']') { + continue; + } + attributes = {}; + attributeString = matches[2].replace(/['"]/g, '').replace(/(^\s+|\s+$)/g, ''); + attrs = attributeString.split(/\s+/); + for(attribute in attrs) { + attr = attrs[attribute].split('='); + if(attr.length == 1) { + attributes[attr[0]] = attr[0]; + } else { + attributes[attr[0]] = attr[1]; + } + } + attributes.cssclass = attributes.class; + url = matches[3]; + imgEl = jQuery('').attr({ + 'src': attributes.thumbnail, + 'width': attributes.width, + 'height': attributes.height, + 'class': attributes.cssclass, + 'data-url': url, + }).addClass('ss-htmleditorfield-file embed'); + + jQuery.each(attributes, function (key, value) { + imgEl.attr('data-' + key, value); + }); + + content = content.replace(matches[0], prefix + (jQuery('
').append(imgEl).html()) + suffix); + } + o.content = content; + }); } }); diff --git a/thirdparty/tinymce_ssbuttons/langs/de.js b/thirdparty/tinymce_ssbuttons/langs/de.js index 0948d6ff2..f0579dba6 100644 --- a/thirdparty/tinymce_ssbuttons/langs/de.js +++ b/thirdparty/tinymce_ssbuttons/langs/de.js @@ -1,5 +1,5 @@ tinyMCE.addI18n('de.tinymce_ssbuttons',{ insertlink: 'Link einfügen', -insertimage: 'Bild einfügen', +insertmedia: 'Bild einfügen', insertflash: 'Flash Objekt einfügen' -}); \ No newline at end of file +}); diff --git a/thirdparty/tinymce_ssbuttons/langs/en.js b/thirdparty/tinymce_ssbuttons/langs/en.js index 91ed8fb0d..c3deae81b 100644 --- a/thirdparty/tinymce_ssbuttons/langs/en.js +++ b/thirdparty/tinymce_ssbuttons/langs/en.js @@ -1,5 +1,5 @@ tinyMCE.addI18n('en.tinymce_ssbuttons', { insertlink: 'Insert Link', -insertimage: 'Insert Image', +insertmedia: 'Insert Media', insertflash: 'Insert Flash Object' -}); \ No newline at end of file +});