From 7c7d42b5f1c3c9cea62b4a73a97e07cea25f8d30 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 11 Mar 2010 10:18:11 -0500 Subject: enable tinymce editor --- plugins/TinyMCE/TinyMCEPlugin.php | 96 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 plugins/TinyMCE/TinyMCEPlugin.php (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php new file mode 100644 index 000000000..1d9d4a288 --- /dev/null +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -0,0 +1,96 @@ +. + * + * @category WYSIWYG + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Use TinyMCE library to allow rich text editing in the browser + * + * Converts the notice form in browser to a rich-text editor. + * + * @category WYSIWYG + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class TinyMCEPlugin extends Plugin +{ + function onEndShowScripts($action) + { + if (common_logged_in()) { + $action->script(common_path('plugins/TinyMCE/js/jquery.tinymce.js')); + $action->inlineScript($this->_inlineScript()); + } + + return true; + } + + function onEndShowStyles($action) + { + $action->style('span#notice_data-text_container { float: left }'); + return true; + } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'TinyMCE', + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou', + 'homepage' => 'http://status.net/wiki/Plugin:TinyMCE', + 'rawdescription' => + _m('Use TinyMCE library to allow rich text editing in the browser')); + return true; + } + + function _inlineScript() + { + $path = common_path('plugins/TinyMCE/js/tiny_mce.js'); + + $scr = << Date: Thu, 11 Mar 2010 11:31:54 -0500 Subject: save the data from TinyMCE --- plugins/TinyMCE/TinyMCEPlugin.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 1d9d4a288..c0fd8506e 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -49,6 +49,8 @@ if (!defined('STATUSNET')) { class TinyMCEPlugin extends Plugin { + var $html; + function onEndShowScripts($action) { if (common_logged_in()) { @@ -76,6 +78,39 @@ class TinyMCEPlugin extends Plugin return true; } + function onArgsInitialize(&$args) + { + if (!array_key_exists('action', $args) || + $args['action'] != 'newnotice') { + return true; + } + + $raw = $args['status_textarea']; + + require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php'; + + $config = array('safe' => 1, + 'deny_attribute' => 'id,style,on*'); + + $this->html = htmLawed($raw, $config); + + $text = html_entity_decode(strip_tags($this->html)); + + $args['status_textarea'] = $text; + + return true; + } + + function onStartNoticeSave($notice) + { + if (!empty($this->html)) { + // Stomp on any rendering + $notice->rendered = $this->html; + } + + return true; + } + function _inlineScript() { $path = common_path('plugins/TinyMCE/js/tiny_mce.js'); -- cgit v1.2.3-54-g00ecf From 8f071b2818e8321ea910df612016175f65093402 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 11 Mar 2010 11:54:04 -0500 Subject: scrub magic quotes from HTML in TinyMCE --- plugins/TinyMCE/TinyMCEPlugin.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index c0fd8506e..f8d85c1ba 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -85,7 +85,7 @@ class TinyMCEPlugin extends Plugin return true; } - $raw = $args['status_textarea']; + $raw = $this->_scrub($args['status_textarea']); require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php'; @@ -127,5 +127,15 @@ END_OF_SCRIPT; return $scr; } + + function _scrub($txt) + { + $strip = get_magic_quotes_gpc(); + if ($strip) { + return stripslashes($txt); + } else { + return $txt; + } + } } -- cgit v1.2.3-54-g00ecf From e54d441af044689cc37b1b58104e1b404f55b9db Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 10 Aug 2010 15:48:02 -0700 Subject: TinyMCE: workaround for save trigger aborting our AJAX form submission. --- plugins/TinyMCE/TinyMCEPlugin.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index f8d85c1ba..3a7656d32 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -115,12 +115,20 @@ class TinyMCEPlugin extends Plugin { $path = common_path('plugins/TinyMCE/js/tiny_mce.js'); + // Note: the normal on-submit triggering to save data from + // the HTML editor into the textarea doesn't play well with + // our AJAX form submission. Manually moving it to trigger + // on our send button click. $scr = << Date: Tue, 10 Aug 2010 16:55:03 -0700 Subject: First stab redoing argument loading for TinyMCE (to avoid hacking checks for all notice saves everywhere) --- actions/newnotice.php | 1 + plugins/TinyMCE/TinyMCEPlugin.php | 62 ++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 30 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/actions/newnotice.php b/actions/newnotice.php index 748d104ff..5e682ffd0 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -203,6 +203,7 @@ class NewnoticeAction extends Action $options = array_merge($options, $locOptions); } + Event::handle('SaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options)); $notice = Notice::saveNew($user->id, $content_shortened, 'web', $options); if (isset($upload)) { diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 3a7656d32..8dc1d8a58 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -78,36 +78,48 @@ class TinyMCEPlugin extends Plugin return true; } - function onArgsInitialize(&$args) + /** + * Sanitize HTML input and strip out potentially dangerous bits. + * + * @param string $raw HTML + * @return string HTML + */ + private function sanitizeHtml($raw) { - if (!array_key_exists('action', $args) || - $args['action'] != 'newnotice') { - return true; - } - - $raw = $this->_scrub($args['status_textarea']); - require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php'; $config = array('safe' => 1, 'deny_attribute' => 'id,style,on*'); - $this->html = htmLawed($raw, $config); - - $text = html_entity_decode(strip_tags($this->html)); - - $args['status_textarea'] = $text; - - return true; + return htmLawed($raw, $config); } - function onStartNoticeSave($notice) + /** + * Strip HTML to plaintext string + * + * @param string $html HTML + * @return string plaintext, single line + */ + private function stripHtml($html) { - if (!empty($this->html)) { - // Stomp on any rendering - $notice->rendered = $this->html; - } + return str_replace("\n", " ", html_entity_decode(strip_tags($html))); + } + /** + * Hook for new-notice form processing to take our HTML goodies; + * won't affect API posting etc. + * + * @param NewNoticeAction $action + * @param User $user + * @param string $content + * @param array $options + * @return boolean hook return + */ + function onSaveNewNoticeWeb($action, $user, &$content, &$options) + { + $html = $this->sanitizeHtml($action->arg('status_textarea')); + $options['rendered'] = $html; + $content = $this->stripHtml($html); return true; } @@ -135,15 +147,5 @@ END_OF_SCRIPT; return $scr; } - - function _scrub($txt) - { - $strip = get_magic_quotes_gpc(); - if ($strip) { - return stripslashes($txt); - } else { - return $txt; - } - } } -- cgit v1.2.3-54-g00ecf From e3bc7ed4bfa8daac84177da0efda796c15294e95 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 12:10:08 -0700 Subject: TinyMCE: Switch default 'simple' layout for customized advanced layout: bold/italic/strikethrough undo/redo link/unlink/image --- plugins/TinyMCE/TinyMCEPlugin.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 8dc1d8a58..64d071435 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -63,7 +63,7 @@ class TinyMCEPlugin extends Plugin function onEndShowStyles($action) { - $action->style('span#notice_data-text_container { float: left }'); + $action->style('span#notice_data-text_container, span#notice_data-text_parent { float: left }'); return true; } @@ -136,7 +136,10 @@ class TinyMCEPlugin extends Plugin $('textarea#notice_data-text').tinymce({ script_url : '{$path}', // General options - theme : "simple", + theme : "advanced", + theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image", + theme_advanced_buttons2 : "", + theme_advanced_buttons3 : "", add_form_submit_trigger : false }); $('#notice_action-submit').click(function() { -- cgit v1.2.3-54-g00ecf From ffc27a337fbdf75e6b23e44aabd1ecd8d8dc9866 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 12:14:05 -0700 Subject: TinyMCE: add fullscreen zoom plugin for editor (a bit awkward but better than trying to work in tiny area... need a nicer intermediate size maybe) --- plugins/TinyMCE/TinyMCEPlugin.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 64d071435..90bb2b2de 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -137,10 +137,12 @@ class TinyMCEPlugin extends Plugin script_url : '{$path}', // General options theme : "advanced", - theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image", + plugins : "fullscreen", + theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image,|,fullscreen", theme_advanced_buttons2 : "", theme_advanced_buttons3 : "", - add_form_submit_trigger : false + add_form_submit_trigger : false, + theme_advanced_resizing : true }); $('#notice_action-submit').click(function() { tinymce.triggerSave(); -- cgit v1.2.3-54-g00ecf From 771928c6e99a2eec29504b678ab3969048ae3807 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 12:44:01 -0700 Subject: TinyMCE: enable autoresize plugin, makes the text area bigger as you're typing a giant message --- plugins/TinyMCE/TinyMCEPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 90bb2b2de..92d31e51e 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -137,7 +137,7 @@ class TinyMCEPlugin extends Plugin script_url : '{$path}', // General options theme : "advanced", - plugins : "fullscreen", + plugins : "paste,fullscreen,autoresize", theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image,|,fullscreen", theme_advanced_buttons2 : "", theme_advanced_buttons3 : "", -- cgit v1.2.3-54-g00ecf From d832b46573df869255da166b31e213d1742de862 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 12:49:02 -0700 Subject: TinyMCE: use inlinepopups mode, so linking dialog appears as a lightbox instead of a separate browser window (which may trigger popup blockers, plays very poorly with fullscreen netbook UIs, and is generally annoying) --- plugins/TinyMCE/TinyMCEPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 92d31e51e..cd6777ca3 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -137,7 +137,7 @@ class TinyMCEPlugin extends Plugin script_url : '{$path}', // General options theme : "advanced", - plugins : "paste,fullscreen,autoresize", + plugins : "paste,fullscreen,autoresize,inlinepopups", theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image,|,fullscreen", theme_advanced_buttons2 : "", theme_advanced_buttons3 : "", -- cgit v1.2.3-54-g00ecf From 8bc1ab436ad4ebe370ca97a7fa27a3acb290dc68 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 13:17:11 -0700 Subject: TinyMCE: enable tab focus behavior matching the default textarea --- plugins/TinyMCE/TinyMCEPlugin.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index cd6777ca3..d1756279b 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -137,12 +137,13 @@ class TinyMCEPlugin extends Plugin script_url : '{$path}', // General options theme : "advanced", - plugins : "paste,fullscreen,autoresize,inlinepopups", + plugins : "paste,fullscreen,autoresize,inlinepopups,tabfocus", theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image,|,fullscreen", theme_advanced_buttons2 : "", theme_advanced_buttons3 : "", add_form_submit_trigger : false, - theme_advanced_resizing : true + theme_advanced_resizing : true, + tabfocus_elements: ":prev,:next" }); $('#notice_action-submit').click(function() { tinymce.triggerSave(); -- cgit v1.2.3-54-g00ecf From c19696afecd98f225181c8a8a368712954d6dbd4 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 13:38:09 -0700 Subject: TinyMCE: add Shane Tomlinson's linkautodetect plugin so typed URLs get linked for you, fitting expected user behavior better. (IE apparently already does this; plugin adds similar behavior for other browsers.) Plugin source: http://sourceforge.net/tracker/?func=detail&aid=2770218&group_id=103281&atid=738747 Source JS compressed manually with jsmin. Note: the link detection doesn't match StatusNet's internal link detection right now. URLs with funky chars, especially like Wikipedia style ones, will often not automatically catch. (But you should still be able to manually link them.) --- plugins/TinyMCE/TinyMCEPlugin.php | 2 +- .../js/plugins/linkautodetect/changelog.txt | 9 ++ .../js/plugins/linkautodetect/editor_plugin.js | 7 + .../js/plugins/linkautodetect/editor_plugin_src.js | 141 +++++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 plugins/TinyMCE/js/plugins/linkautodetect/changelog.txt create mode 100644 plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin.js create mode 100644 plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin_src.js (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index d1756279b..9408e20c9 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -137,7 +137,7 @@ class TinyMCEPlugin extends Plugin script_url : '{$path}', // General options theme : "advanced", - plugins : "paste,fullscreen,autoresize,inlinepopups,tabfocus", + plugins : "paste,fullscreen,autoresize,inlinepopups,tabfocus,linkautodetect", theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image,|,fullscreen", theme_advanced_buttons2 : "", theme_advanced_buttons3 : "", diff --git a/plugins/TinyMCE/js/plugins/linkautodetect/changelog.txt b/plugins/TinyMCE/js/plugins/linkautodetect/changelog.txt new file mode 100644 index 000000000..ecab340ab --- /dev/null +++ b/plugins/TinyMCE/js/plugins/linkautodetect/changelog.txt @@ -0,0 +1,9 @@ +0.1 2009-04-15 - initial version +0.11 2009-05-10 - Fix for email addresses with two periods in the domain + were incorrectly converted to http links. Fix submitted + by Ralph Slooten. + Fix for tinyMCE.isIE that needed to be tinymce.isIE. +0.12 2009-06-23 - Fix for URLs that have an HTML anchor identifier in them, such as + http://www.palmpre.org/forums/palm-pre/85-copy-and-paste.html#post457 + Previously, it would create a link to only + http://www.palmpre.org/forums/palm-pre/85-copy-and-paste.html \ No newline at end of file diff --git a/plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin.js b/plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin.js new file mode 100644 index 000000000..7e97a78e4 --- /dev/null +++ b/plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin.js @@ -0,0 +1,7 @@ + +(function(){tinymce.create('tinymce.plugins.LinkAutoDetect',{init:function(ed,url){var t=this;t.RE_email=/^[a-z0-9_\-]+(\.[_a-z0-9\-]+)*@([_a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)$/i;t.RE_url=/^((https?|ftp|news):\/\/)?([a-z]([a-z0-9\-]*\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-z][a-z0-9_]*)?$/i;ed.onKeyPress.add(t.onKeyPress,t);ed.onKeyUp.add(t.onKeyUp,t);},getInfo:function(){return{longname:'Link Auto Detect',author:'Ubernote/Shane Tomlinson',authorurl:'http://www.ubernote.com',infourl:'http://www.ubernote.com',version:'0.2'};},onKeyPress:function(ed,ev,o){if(tinymce.isIE){return;} +var s=ed.selection.getSel();var textNode=s.anchorNode;var createLink=function(searchfor,hlink,midStart){var leftText=textNode;var rightText=leftText.splitText(s.anchorOffset);var midText=leftText.splitText(midStart);var midEnd=midText.data.search(searchfor);if(midEnd!=-1){rightText=midText.splitText(midEnd);} +var tag=ed.dom.create('a',{href:hlink},midText.data);var a=midText.parentNode.insertBefore(tag,rightText);s.collapse(rightText,0);ed.dom.remove(midText);};if((ev.which==13||ev.which==32)&&textNode.nodeType==3&&textNode.data.length>3&&textNode.data.indexOf('.')>=0&&!ed.dom.getParent(textNode,'a')){var midStart=textNode.data.substring(0,s.anchorOffset).search(/\S{4,}$/);if(midStart!=-1){var matchData=textNode.data.substring(0,s.anchorOffset).replace(/^.*?(\S*)$/,'$1');var matchURL=matchData.match(this.RE_url);var matchEmail=matchData.match(this.RE_email);if(matchEmail){createLink(/[^a-zA-Z0-9\.@_\-]/,'mailto:'+matchEmail[0],midStart);} +else if(matchURL){createLink(/[^a-zA-Z0-9\._\-\/\&\?#=:@]/,(matchURL[1]?'':'http://')+matchURL[0],midStart);}}}},onKeyUp:function(ed,ev,o){if(tinymce.isIE){return;} +var s=ed.selection.getSel();var textNode=s.anchorNode;var a=ed.dom.getParent(textNode,'a');if(!(ev.which&&(ev.which==13||ev.which==32))&&(ev.which||ev.keyCode==8||ev.keyCode==46)&&(textNode.nodeType==3)&&(a)){var matchEmail=s.anchorNode.data.match(this.RE_email);var matchURL=textNode.data.match(this.RE_url);if(matchEmail){ed.dom.setAttrib(a,'href','mailto:'+textNode.data);} +if(matchURL){ed.dom.setAttrib(a,'href',(matchURL[1]?'':'http://')+matchURL[0]);}}}});tinymce.PluginManager.add('linkautodetect',tinymce.plugins.LinkAutoDetect);})(); \ No newline at end of file diff --git a/plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin_src.js b/plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin_src.js new file mode 100644 index 000000000..d2693927c --- /dev/null +++ b/plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin_src.js @@ -0,0 +1,141 @@ +/** + * $Id: editor_plugin_src.js 2009-05-10 + * + * @author Ubernote/Shane Tomlinson + * http://www.ubernote.com + * set117@gmail.com + * + * Detect emails and urls as they are typed in Mozilla/Safari/Chrome and Opera + * Borrowed from both Typo3 http://typo3.org/ and Xinha http://xinha.gogo.co.nz/ + * Heavily modified and cleaned up. + * + * Original license info from Xinha at the bottom. + */ + +(function() { + tinymce.create('tinymce.plugins.LinkAutoDetect', { + init : function(ed, url) { + var t = this; + t.RE_email = /^[a-z0-9_\-]+(\.[_a-z0-9\-]+)*@([_a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)$/i; + t.RE_url = /^((https?|ftp|news):\/\/)?([a-z]([a-z0-9\-]*\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-z][a-z0-9_]*)?$/i; + ed.onKeyPress.add( t.onKeyPress, t ); + ed.onKeyUp.add( t.onKeyUp, t ); + }, + + getInfo : function() { + return { + longname : 'Link Auto Detect', + author : 'Ubernote/Shane Tomlinson', + authorurl : 'http://www.ubernote.com', + infourl : 'http://www.ubernote.com', + version : '0.2' + }; + }, + + onKeyPress : function(ed, ev, o) { + if(tinymce.isIE) { + // IE already does auto-detect, so no worries. + return; + } // end if + + var s = ed.selection.getSel(); + var textNode = s.anchorNode; + + var createLink = function (searchfor, hlink, midStart) { + var leftText = textNode; + var rightText = leftText.splitText(s.anchorOffset); + var midText = leftText.splitText(midStart); + var midEnd = midText.data.search(searchfor); + if (midEnd != -1) { + rightText = midText.splitText(midEnd); + } // end if + var tag = ed.dom.create('a', { href: hlink }, midText.data); + var a = midText.parentNode.insertBefore(tag, rightText); + + // We are going to put the cursor into the first position after + // the anchor and let the browser take care of inserting the space/enter. + s.collapse(rightText, 0); + ed.dom.remove(midText); + }; + + // Space or Enter, see if the text just typed looks like a URL, or email address and link it accordingly + if((ev.which == 13 || ev.which == 32) + && textNode.nodeType == 3 && textNode.data.length > 3 + && textNode.data.indexOf('.') >= 0 && !ed.dom.getParent(textNode, 'a')) { + var midStart = textNode.data.substring(0,s.anchorOffset).search(/\S{4,}$/); + if(midStart != -1) { + var matchData = textNode.data.substring(0,s.anchorOffset).replace(/^.*?(\S*)$/, '$1'); + var matchURL = matchData.match(this.RE_url); + var matchEmail = matchData.match(this.RE_email); + if(matchEmail) { + createLink(/[^a-zA-Z0-9\.@_\-]/, 'mailto:' + matchEmail[0], midStart); + } + else if(matchURL) { + createLink( /[^a-zA-Z0-9\._\-\/\&\?#=:@]/, (matchURL[1] ? '' : 'http://') + matchURL[0], midStart); + } + } // end if + } + }, + + onKeyUp : function(ed, ev, o) { + if(tinymce.isIE) { + // IE already does auto-detect, so no worries. + return; + } // end if + + var s = ed.selection.getSel(); + var textNode = s.anchorNode; + var a = ed.dom.getParent(textNode, 'a'); + + if( ! (ev.which && ( ev.which == 13 || ev.which == 32)) + && (ev.which || ev.keyCode == 8 || ev.keyCode == 46) + && (textNode.nodeType == 3) && (a)) { + // See if we might be changing a link + var matchEmail = s.anchorNode.data.match(this.RE_email); + var matchURL = textNode.data.match(this.RE_url); + if(matchEmail) { + ed.dom.setAttrib(a, 'href', 'mailto:' + textNode.data); + } // end if + if(matchURL) { + ed.dom.setAttrib(a, 'href', (matchURL[1] ? '' : 'http://') + matchURL[0]); + } // end if + } // end if + } + }); + + // Register plugin + tinymce.PluginManager.add('linkautodetect', tinymce.plugins.LinkAutoDetect); +})(); + +/* +htmlArea License (based on BSD license) +Copyright (c) 2002-2004, interactivetools.com, inc. +Copyright (c) 2003-2004 dynarch.com +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1) Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2) Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3) Neither the name of interactivetools.com, inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 527561cd93b69ddaba660f272462aadfaef0c511 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 14:39:39 -0700 Subject: TinyMCE: core tweak; switching order of input processing so length limit is applied to stripped version of the text --- actions/newnotice.php | 14 ++++++-------- plugins/TinyMCE/TinyMCEPlugin.php | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/actions/newnotice.php b/actions/newnotice.php index 5e682ffd0..8263198f7 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -131,6 +131,8 @@ class NewnoticeAction extends Action $user = common_current_user(); assert($user); // XXX: maybe an error instead... $content = $this->trimmed('status_textarea'); + $options = array(); + Event::handle('StartSaveNewNoticeWeb', array($this, $user, &$content, &$options)); if (!$content) { $this->clientError(_('No content!')); @@ -157,11 +159,9 @@ class NewnoticeAction extends Action Notice::maxContent())); } - $replyto = $this->trimmed('inreplyto'); - #If an ID of 0 is wrongly passed here, it will cause a database error, - #so override it... - if ($replyto == 0) { - $replyto = 'false'; + $replyto = intval($this->trimmed('inreplyto')); + if ($replyto) { + $options['replyto'] = $replyto; } $upload = null; @@ -182,8 +182,6 @@ class NewnoticeAction extends Action } } - $options = array('reply_to' => ($replyto == 'false') ? null : $replyto); - if ($user->shareLocation()) { // use browser data if checked; otherwise profile data if ($this->arg('notice_data-geo')) { @@ -203,12 +201,12 @@ class NewnoticeAction extends Action $options = array_merge($options, $locOptions); } - Event::handle('SaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options)); $notice = Notice::saveNew($user->id, $content_shortened, 'web', $options); if (isset($upload)) { $upload->attachToNotice($notice); } + Event::handle('EndSaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options)); if ($this->boolean('ajax')) { header('Content-Type: text/xml;charset=utf-8'); diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 9408e20c9..d9e189375 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -115,7 +115,7 @@ class TinyMCEPlugin extends Plugin * @param array $options * @return boolean hook return */ - function onSaveNewNoticeWeb($action, $user, &$content, &$options) + function onStartSaveNewNoticeWeb($action, $user, &$content, &$options) { $html = $this->sanitizeHtml($action->arg('status_textarea')); $options['rendered'] = $html; -- cgit v1.2.3-54-g00ecf From 3c28464daba8cbb2d8362c38ebb8e2c41ff5049f Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 14:50:59 -0700 Subject: TinyMCE: only apply HTML parsing if we actually got into JS and poked the editor widget. With JS off, we'll take plaintext as usual. --- plugins/TinyMCE/TinyMCEPlugin.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index d9e189375..8112b7dbb 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -117,9 +117,11 @@ class TinyMCEPlugin extends Plugin */ function onStartSaveNewNoticeWeb($action, $user, &$content, &$options) { - $html = $this->sanitizeHtml($action->arg('status_textarea')); - $options['rendered'] = $html; - $content = $this->stripHtml($html); + if ($action->arg('richedit')) { + $html = $this->sanitizeHtml($content); + $options['rendered'] = $html; + $content = $this->stripHtml($html); + } return true; } @@ -145,8 +147,11 @@ class TinyMCEPlugin extends Plugin theme_advanced_resizing : true, tabfocus_elements: ":prev,:next" }); + $('#form_notice').append(''); $('#notice_action-submit').click(function() { - tinymce.triggerSave(); + if (typeof tinymce != "undefined") { + tinymce.triggerSave(); + } }); }); END_OF_SCRIPT; -- cgit v1.2.3-54-g00ecf From 6ee3f35302d739a5be1287839bfbb13ec86c1800 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 15:56:40 -0700 Subject: work in progress: prettier attachment mode for tinymce? --- actions/newnotice.php | 5 +- plugins/TinyMCE/TinyMCEPlugin.php | 103 ++++++++++++++++++++++++++++++++++---- 2 files changed, 97 insertions(+), 11 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/actions/newnotice.php b/actions/newnotice.php index 8263198f7..8f1fb1c40 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -169,7 +169,10 @@ class NewnoticeAction extends Action if (isset($upload)) { - $content_shortened .= ' ' . $upload->shortUrl(); + if (Event::handle('StartSaveNewNoticeAppendAttachment', array($this, $upload, &$content_shortened, &$options))) { + $content_shortened .= ' ' . $upload->shortUrl(); + } + Event::handle('EndSaveNewNoticeAppendAttachment', array($this, $upload, &$content_shortened, &$options)); if (Notice::contentTooLong($content_shortened)) { $upload->delete(); diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 8112b7dbb..e482ab320 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -1,4 +1,5 @@ script(common_path('plugins/TinyMCE/js/jquery.tinymce.js')); $action->inlineScript($this->_inlineScript()); } @@ -70,11 +70,11 @@ class TinyMCEPlugin extends Plugin function onPluginVersion(&$versions) { $versions[] = array('name' => 'TinyMCE', - 'version' => STATUSNET_VERSION, - 'author' => 'Evan Prodromou', - 'homepage' => 'http://status.net/wiki/Plugin:TinyMCE', - 'rawdescription' => - _m('Use TinyMCE library to allow rich text editing in the browser')); + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou', + 'homepage' => 'http://status.net/wiki/Plugin:TinyMCE', + 'rawdescription' => + _m('Use TinyMCE library to allow rich text editing in the browser')); return true; } @@ -86,10 +86,10 @@ class TinyMCEPlugin extends Plugin */ private function sanitizeHtml($raw) { - require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php'; + require_once INSTALLDIR . '/extlib/htmLawed/htmLawed.php'; $config = array('safe' => 1, - 'deny_attribute' => 'id,style,on*'); + 'deny_attribute' => 'id,style,on*'); return htmLawed($raw, $config); } @@ -125,6 +125,75 @@ class TinyMCEPlugin extends Plugin return true; } + /** + * Hook for new-notice form processing to process file upload appending... + * + * @param NewNoticeAction $action + * @param MediaFile $media + * @param string $content + * @param array $options + * @return boolean hook return + */ + function onStartSaveNewNoticeAppendAttachment($action, $media, &$content, &$options) + { + if ($action->arg('richedit')) { + // See if we've got a placeholder inline image; if so, fill it! + $dom = new DOMDocument(); + common_log(LOG_INFO, 'QQQQQQQQQQQQQQQQQQQQQQQQ'); + if ($dom->loadHTML($options['rendered'])) { + $imgs = $dom->getElementsByTagName('img'); + foreach ($imgs as $img) { + common_log(LOG_INFO, 'img: ' . var_export($img, true)); + if (preg_match('/(^| )placeholder( |$)/', $img->getAttribute('class'))) { + common_log(LOG_INFO, 'QQQQQQ: img src: ' . $media->fileRecord->url); + $img->setAttribute('src', $media->fileRecord->url); + $holderWidth = intval($img->getAttribute('width')); + $holderHeight = intval($img->getAttribute('height')); + $holderAspect = $holderWidth / $holderHeight; + + $path = File::path($media->filename); + $imgInfo = getimagesize($path); + common_log(LOG_INFO, 'QQQQQQ: ' . $path . ' : ' . var_export($imgInfo, true)); + + $origWidth = $imgInfo[0]; + $origHeight = $imgInfo[1]; + $origAspect = $origWidth / $origHeight; + if ($origAspect >= 1.0) { + // wide image + if ($origWidth > $holderWidth) { + $width = $holderWidth; + $height = intval($holderWidth / $origAspect); + } else { + $width = $origWidth; + $height = $origHeight; + } + } else { + if ($origHeight > $holderHeight) { + $height = $holderHeight; + $width = ($holderWidth * $origAspect); + } else { + $width = $origWidth; + $height = $origHeight; + } + } + + $img->setAttribute('width', $width); + $img->setAttribute('height', $height); + + common_log(LOG_INFO, 'QQQQQ: ' . $width . ' ' . $height); + } + } + $html = $dom->saveHTML(); + common_log(LOG_INFO, 'QQQQQQ: out: ' . $html); + $options['rendered'] = $html; + } + + // The regular code will append the short URL to the plaintext content. + // Carry on and let it through... + } + return true; + } + function _inlineScript() { $path = common_path('plugins/TinyMCE/js/tiny_mce.js'); @@ -153,10 +222,24 @@ class TinyMCEPlugin extends Plugin tinymce.triggerSave(); } }); + $('#'+SN.C.S.NoticeDataAttach).change(function() { + /* + S = '
'+$(this).val()+'
'; + NDAS = $('#'+SN.C.S.NoticeDataAttachSelected); + if (NDAS.length > 0) { + NDAS.replaceWith(S); + } + */ + //alert('yay'); + var img = ''; + var html = tinyMCE.activeEditor.getContent(); + tinyMCE.activeEditor.setContent(html + img); + }); }); END_OF_SCRIPT; return $scr; } + } -- cgit v1.2.3-54-g00ecf From 3370a326d84f3eb8a39a073eae3705069b517263 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 11 Aug 2010 17:01:38 -0700 Subject: work in progress: tinymce image attachments --- plugins/TinyMCE/TinyMCEPlugin.php | 152 +++++++++++++++++++++++++--------- plugins/TinyMCE/icons/placeholder.png | Bin 0 -> 78779 bytes plugins/TinyMCE/icons/placeholder.xcf | Bin 0 -> 691137 bytes 3 files changed, 112 insertions(+), 40 deletions(-) create mode 100644 plugins/TinyMCE/icons/placeholder.png create mode 100644 plugins/TinyMCE/icons/placeholder.xcf (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index e482ab320..f67d6ea13 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -139,52 +139,16 @@ class TinyMCEPlugin extends Plugin if ($action->arg('richedit')) { // See if we've got a placeholder inline image; if so, fill it! $dom = new DOMDocument(); - common_log(LOG_INFO, 'QQQQQQQQQQQQQQQQQQQQQQQQ'); + if ($dom->loadHTML($options['rendered'])) { $imgs = $dom->getElementsByTagName('img'); foreach ($imgs as $img) { - common_log(LOG_INFO, 'img: ' . var_export($img, true)); if (preg_match('/(^| )placeholder( |$)/', $img->getAttribute('class'))) { - common_log(LOG_INFO, 'QQQQQQ: img src: ' . $media->fileRecord->url); - $img->setAttribute('src', $media->fileRecord->url); - $holderWidth = intval($img->getAttribute('width')); - $holderHeight = intval($img->getAttribute('height')); - $holderAspect = $holderWidth / $holderHeight; - - $path = File::path($media->filename); - $imgInfo = getimagesize($path); - common_log(LOG_INFO, 'QQQQQQ: ' . $path . ' : ' . var_export($imgInfo, true)); - - $origWidth = $imgInfo[0]; - $origHeight = $imgInfo[1]; - $origAspect = $origWidth / $origHeight; - if ($origAspect >= 1.0) { - // wide image - if ($origWidth > $holderWidth) { - $width = $holderWidth; - $height = intval($holderWidth / $origAspect); - } else { - $width = $origWidth; - $height = $origHeight; - } - } else { - if ($origHeight > $holderHeight) { - $height = $holderHeight; - $width = ($holderWidth * $origAspect); - } else { - $width = $origWidth; - $height = $origHeight; - } - } - - $img->setAttribute('width', $width); - $img->setAttribute('height', $height); - - common_log(LOG_INFO, 'QQQQQ: ' . $width . ' ' . $height); + // Create a link to the attachment page... + $this->formatAttachment($img, $media); } } $html = $dom->saveHTML(); - common_log(LOG_INFO, 'QQQQQQ: out: ' . $html); $options['rendered'] = $html; } @@ -194,9 +158,117 @@ class TinyMCEPlugin extends Plugin return true; } + /** + * Format the attachment placeholder img with the final version. + * + * @param DOMElement $img + * @param MediaFile $media + */ + private function formatAttachment($img, $media) + { + $dom = $img->ownerDocument; + $link = $dom->createElement('a'); + $link->setAttribute('href', $media->fileurl); + + if ($this->isEmbeddable($media)) { + common_log(LOG_INFO, 'QQQQQ'); + // Fix the the attributes and wrap the link around it... + $this->insertImage($img, $media); + common_log(LOG_INFO, 'QQQQQ A!'); + try { + $dom->replaceChild($link, $img); //it dies in here?! + } catch (Exception $wtf) { + common_log(LOG_ERR, 'QQQ WTF? ' . $wtf->getMessage()); + } + common_log(LOG_INFO, 'QQQQQ B!'); + $link->appendChild($img); + common_log(LOG_INFO, 'QQQQQ C!'); + } else { + common_log(LOG_INFO, 'QQQQQ X'); + // Not an image? Replace it with a text link. + $text = $dom->createTextNode($media->shortUrl()); + $link->appendChild($text); + $dom->replaceChild($link, $img); + } + } + + /** + * Is this media file a type we can display inline? + * + * @param MediaFile $media + * @return boolean + */ + private function isEmbeddable($media) + { + $showable = array('image/png', + 'image/gif', + 'image/jpeg'); + return in_array($media->mimetype, $showable); + } + + /** + * Rewrite and resize a placeholder image element to match the uploaded + * file. If the holder is smaller than the file, the file is scaled to fit + * with correct aspect ratio (but will be loaded at full resolution). + * + * @param DOMElement $img + * @param MediaFile $media + */ + private function insertImage($img, $media) + { + $img->setAttribute('src', $media->fileRecord->url); + + $holderWidth = intval($img->getAttribute('width')); + $holderHeight = intval($img->getAttribute('height')); + + $path = File::path($media->filename); + $imgInfo = getimagesize($path); + + if ($imgInfo) { + $origWidth = $imgInfo[0]; + $origHeight = $imgInfo[1]; + + list($width, $height) = $this->sizeBox( + $origWidth, $origHeight, + $holderWidth, $holderHeight); + + $img->setAttribute('width', $width); + $img->setAttribute('height', $height); + } + } + + /** + * + * @param int $origWidth + * @param int $origHeight + * @param int $holderWidth + * @param int $holderHeight + * @return array($width, $height) + */ + private function sizeBox($origWidth, $origHeight, $holderWidth, $holderHeight) + { + $holderAspect = $holderWidth / $holderHeight; + $origAspect = $origWidth / $origHeight; + if ($origAspect >= 1.0) { + // wide image + if ($origWidth > $holderWidth) { + return array($holderWidth, intval($holderWidth / $origAspect)); + } else { + return array($origWidth, $origHeight); + } + } else { + if ($origHeight > $holderHeight) { + return array(intval($holderWidth * $origAspect), $holderHeight); + } else { + return array($origWidth, $origHeight); + } + } + } + function _inlineScript() { $path = common_path('plugins/TinyMCE/js/tiny_mce.js'); + $placeholder = common_path('plugins/TinyMCE/icons/placeholder.png'); // Note: the normal on-submit triggering to save data from // the HTML editor into the textarea doesn't play well with @@ -231,7 +303,7 @@ class TinyMCEPlugin extends Plugin } */ //alert('yay'); - var img = ''; + var img = ''; var html = tinyMCE.activeEditor.getContent(); tinyMCE.activeEditor.setContent(html + img); }); diff --git a/plugins/TinyMCE/icons/placeholder.png b/plugins/TinyMCE/icons/placeholder.png new file mode 100644 index 000000000..911f257d5 Binary files /dev/null and b/plugins/TinyMCE/icons/placeholder.png differ diff --git a/plugins/TinyMCE/icons/placeholder.xcf b/plugins/TinyMCE/icons/placeholder.xcf new file mode 100644 index 000000000..e05f8a9c9 Binary files /dev/null and b/plugins/TinyMCE/icons/placeholder.xcf differ -- cgit v1.2.3-54-g00ecf From f14f252a1633c9297f33a98ef7f4ccf6db0efaef Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 12 Aug 2010 11:39:42 -0700 Subject: TinyMCE: fixes to attachment handling --- plugins/TinyMCE/TinyMCEPlugin.php | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index f67d6ea13..47d3d059f 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -148,8 +148,7 @@ class TinyMCEPlugin extends Plugin $this->formatAttachment($img, $media); } } - $html = $dom->saveHTML(); - $options['rendered'] = $html; + $options['rendered'] = $this->saveHtml($dom); } // The regular code will append the short URL to the plaintext content. @@ -166,29 +165,26 @@ class TinyMCEPlugin extends Plugin */ private function formatAttachment($img, $media) { + $parent = $img->parentNode; $dom = $img->ownerDocument; + $link = $dom->createElement('a'); $link->setAttribute('href', $media->fileurl); + $link->setAttribute('title', File::url($media->filename)); if ($this->isEmbeddable($media)) { - common_log(LOG_INFO, 'QQQQQ'); // Fix the the attributes and wrap the link around it... $this->insertImage($img, $media); - common_log(LOG_INFO, 'QQQQQ A!'); - try { - $dom->replaceChild($link, $img); //it dies in here?! - } catch (Exception $wtf) { - common_log(LOG_ERR, 'QQQ WTF? ' . $wtf->getMessage()); - } - common_log(LOG_INFO, 'QQQQQ B!'); + $parent->replaceChild($link, $img); //it dies in here?! $link->appendChild($img); - common_log(LOG_INFO, 'QQQQQ C!'); } else { - common_log(LOG_INFO, 'QQQQQ X'); // Not an image? Replace it with a text link. + $link->setAttribute('rel', 'external'); + $link->setAttribute('class', 'attachment'); + $link->setAttribute('id', 'attachment-' . $media->fileRecord->id); $text = $dom->createTextNode($media->shortUrl()); $link->appendChild($text); - $dom->replaceChild($link, $img); + $parent->replaceChild($link, $img); } } @@ -265,6 +261,15 @@ class TinyMCEPlugin extends Plugin } } + private function saveHtml($dom) + { + $html = $dom->saveHTML(); + // hack to remove surrounding crap added to the dom + // all we wanted was a fragment + $stripped = preg_replace('/^.*]*>(.*)<\/body.*$/is', '$1', $html); + return $stripped; + } + function _inlineScript() { $path = common_path('plugins/TinyMCE/js/tiny_mce.js'); -- cgit v1.2.3-54-g00ecf From 34995df879457f03ad6f78e617294dc2dd040b7d Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 12 Aug 2010 12:47:07 -0700 Subject: TinyMCE: counter support (may not be 100% exact match to server-side count, but there's already discrepencies due to URL shortening) Fix for bad char conversions also, caused short text to not be saved in some cases. --- js/util.js | 6 +++++- plugins/TinyMCE/TinyMCEPlugin.php | 45 +++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 22 deletions(-) (limited to 'plugins/TinyMCE/TinyMCEPlugin.php') diff --git a/js/util.js b/js/util.js index 6a67da4bc..ad8a44c82 100644 --- a/js/util.js +++ b/js/util.js @@ -110,7 +110,7 @@ var SN = { // StatusNet return; } - var remaining = MaxLength - form.find('#'+SN.C.S.NoticeDataText).val().length; + var remaining = MaxLength - SN.U.CharacterCount(form); var counter = form.find('#'+SN.C.S.NoticeTextCount); if (remaining.toString() != counter.text()) { @@ -134,6 +134,10 @@ var SN = { // StatusNet } }, + CharacterCount: function(form) { + return form.find('#'+SN.C.S.NoticeDataText).val().length; + }, + ClearCounterBlackout: function(form) { // Allow keyup events to poke the counter again SN.C.I.CounterBlackout = false; diff --git a/plugins/TinyMCE/TinyMCEPlugin.php b/plugins/TinyMCE/TinyMCEPlugin.php index 47d3d059f..ca16f6059 100644 --- a/plugins/TinyMCE/TinyMCEPlugin.php +++ b/plugins/TinyMCE/TinyMCEPlugin.php @@ -102,7 +102,7 @@ class TinyMCEPlugin extends Plugin */ private function stripHtml($html) { - return str_replace("\n", " ", html_entity_decode(strip_tags($html))); + return str_replace("\n", " ", html_entity_decode(strip_tags($html), ENT_QUOTES, 'UTF-8')); } /** @@ -281,6 +281,7 @@ class TinyMCEPlugin extends Plugin // on our send button click. $scr = <<'); - $('#notice_action-submit').click(function() { - if (typeof tinymce != "undefined") { - tinymce.triggerSave(); - } - }); - $('#'+SN.C.S.NoticeDataAttach).change(function() { - /* - S = '
'+$(this).val()+'
'; - NDAS = $('#'+SN.C.S.NoticeDataAttachSelected); - if (NDAS.length > 0) { - NDAS.replaceWith(S); + tabfocus_elements: ":prev,:next", + setup: function(ed) { + noticeForm.append(''); + + $('#notice_action-submit').click(function() { + tinymce.triggerSave(); + }); + + var origCounter = SN.U.CharacterCount; + SN.U.CharacterCount = function(form) { + var text = $(ed.getDoc()).text(); + return text.length; + }; + ed.onKeyUp.add(function (ed, e) { + SN.U.Counter(noticeForm); + }); + + $('#'+SN.C.S.NoticeDataAttach).change(function() { + var img = ''; + var html = tinyMCE.activeEditor.getContent(); + ed.setContent(html + img); + }); } - */ - //alert('yay'); - var img = ''; - var html = tinyMCE.activeEditor.getContent(); - tinyMCE.activeEditor.setContent(html + img); }); }); END_OF_SCRIPT; @@ -319,4 +323,3 @@ END_OF_SCRIPT; } } - -- cgit v1.2.3-54-g00ecf