| 1 |
;# Realtime Preview plugin for MovableType w/ BigPAPI |
|---|
| 2 |
;# Original Copyright (c) 2006 Piroli YUKARINOMIYA |
|---|
| 3 |
;# Open MagicVox.net - http://www.magicvox.net/ |
|---|
| 4 |
;# @see http://www.magicvox.net/archive/2006/02071650.php |
|---|
| 5 |
|
|---|
| 6 |
;# This code is released under the Artistic License. |
|---|
| 7 |
;# The terms of the Artistic License are described at |
|---|
| 8 |
;# http://www.perl.com/language/misc/Artistic.html |
|---|
| 9 |
|
|---|
| 10 |
package MT::Plugin::RealtimePreview; |
|---|
| 11 |
use strict; |
|---|
| 12 |
|
|---|
| 13 |
use vars qw( $VERSION ); |
|---|
| 14 |
$VERSION = '1.20'; |
|---|
| 15 |
|
|---|
| 16 |
use base qw( MT::Plugin ); |
|---|
| 17 |
my $plugin = new MT::Plugin ({ |
|---|
| 18 |
name => 'Realtime Preview', |
|---|
| 19 |
version => $VERSION, |
|---|
| 20 |
author_name => 'Piroli YUKARINOMIYA', |
|---|
| 21 |
author_link => 'http://www.magicvox.net/', |
|---|
| 22 |
doc_link => 'http://www.magicvox.net/archive/2006/02071650.php', |
|---|
| 23 |
description => |
|---|
| 24 |
'Enable realtime previewing in editing the entry.<br />'. |
|---|
| 25 |
'You can get a good preview of the entry in realtime.', |
|---|
| 26 |
}); |
|---|
| 27 |
MT->add_plugin ($plugin); |
|---|
| 28 |
|
|---|
| 29 |
;### Callback register for BigPAPI |
|---|
| 30 |
MT->add_callback ('bigpapi::template::edit_entry', 9, $plugin, \&realtime_preview); |
|---|
| 31 |
|
|---|
| 32 |
;### Template register for MTRealtimePreview* |
|---|
| 33 |
use MT::Template::Context; |
|---|
| 34 |
MT::Template::Context->add_container_tag ('RealtimePreview' => \&tag_realtime_preview); |
|---|
| 35 |
MT::Template::Context->add_tag ('RealtimePreviewID' => \&tag_realtime_preview_id); |
|---|
| 36 |
|
|---|
| 37 |
sub instance { $plugin } |
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
;# Preview the contents of the textarea that has IDs below in MovableType editing screen |
|---|
| 41 |
my @preview_default = qw( title text text_more keywords excerpt ); |
|---|
| 42 |
|
|---|
| 43 |
;# Add prefix in creating ids for preview |
|---|
| 44 |
my $id_prefix = 'rtpv_'; |
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
;### Customize the entry editing page of MovableType |
|---|
| 48 |
use MT::Entry; |
|---|
| 49 |
sub realtime_preview { |
|---|
| 50 |
my ($cb, $app, $template) = @_; |
|---|
| 51 |
my $q = $app->{'query'}; |
|---|
| 52 |
;# |
|---|
| 53 |
;# retrieve a url for previewing |
|---|
| 54 |
my $preview_url; |
|---|
| 55 |
$q && $q->param('blog_id') |
|---|
| 56 |
or return undef;# invalid blog_id |
|---|
| 57 |
if ($q->param('id') && (my $entry = MT::Entry->load ({ |
|---|
| 58 |
'blog_id' => $q->param ('blog_id'), 'id' => $q->param ('id'), status => 2 |
|---|
| 59 |
}))) { |
|---|
| 60 |
$preview_url = $entry->permalink (undef);# preview with current editing entry |
|---|
| 61 |
} elsif (($entry = MT::Entry->load ( |
|---|
| 62 |
{'blog_id' => $q->param ('blog_id'), status => 2}, |
|---|
| 63 |
{'sort' => 'created_on', direction => 'descend', limit => 1} |
|---|
| 64 |
))) { |
|---|
| 65 |
$preview_url = $entry->permalink (undef);# preview with the most recent published page |
|---|
| 66 |
} else { |
|---|
| 67 |
return undef;# there is no page previewed |
|---|
| 68 |
} |
|---|
| 69 |
|
|---|
| 70 |
;# previewed fields |
|---|
| 71 |
my $event_handlers; |
|---|
| 72 |
map { $event_handlers .= sprintf "\taddEventHandler ('%s', '%s%s');\n", $_, $id_prefix, $_ } @preview_default; |
|---|
| 73 |
$event_handlers ne '' |
|---|
| 74 |
or return undef;# there is no field previewed |
|---|
| 75 |
|
|---|
| 76 |
;# Add JavaScript codes |
|---|
| 77 |
my $old = <<HTML; |
|---|
| 78 |
</head> |
|---|
| 79 |
HTML |
|---|
| 80 |
my $add = <<HTML; |
|---|
| 81 |
<script type="text/javascript"> |
|---|
| 82 |
var wndPreview = null; |
|---|
| 83 |
|
|---|
| 84 |
// 06/06/14, transporting from MT::Util::html_text_transform, thx to Yamakawa |
|---|
| 85 |
function convert_paras (text) { |
|---|
| 86 |
var paras = text.split (/\\r?\\n\\r?\\n/); |
|---|
| 87 |
for (var i in paras) |
|---|
| 88 |
if (! paras[i].match (/^<\\/?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)/)) |
|---|
| 89 |
paras[i] = '<p>' + paras[i].replace (/\\r?\\n/g, '<br />\\n') + '</p>\\n'; |
|---|
| 90 |
return paras.join ('\\n\\n'); |
|---|
| 91 |
} |
|---|
| 92 |
|
|---|
| 93 |
function addEventHandler (src, target) { |
|---|
| 94 |
var txtarea = document.getElementById (src); |
|---|
| 95 |
if (txtarea) |
|---|
| 96 |
(txtarea.onchange = txtarea.onkeyup = txtarea.onfocus = function () { |
|---|
| 97 |
var u = wndPreview; |
|---|
| 98 |
if (! u || u.closed || ! (u = u.document)) |
|---|
| 99 |
return; |
|---|
| 100 |
var text = txtarea.value; |
|---|
| 101 |
if (document.getElementById ('convert_breaks').options.selectedIndex) |
|---|
| 102 |
text = convert_paras (text); |
|---|
| 103 |
for (var v = 1, i = 1; u && v; i++) |
|---|
| 104 |
(v = u.getElementById (target + i)) && (v.innerHTML = text); |
|---|
| 105 |
}) (); |
|---|
| 106 |
} |
|---|
| 107 |
|
|---|
| 108 |
function checkPageLoaded () { |
|---|
| 109 |
var u; |
|---|
| 110 |
if ((u = wndPreview) && (! u.closed) && (u = u.document) |
|---|
| 111 |
&& (u = u.getElementsByTagName ('body')) |
|---|
| 112 |
&& u.length && (u = u[0]) && (u = u.lastChild)) |
|---|
| 113 |
{ |
|---|
| 114 |
%%RTPREVIEW_EVENT_HANDLERS%% |
|---|
| 115 |
return; |
|---|
| 116 |
} |
|---|
| 117 |
setTimeout ("checkPageLoaded ()", 100); |
|---|
| 118 |
} |
|---|
| 119 |
|
|---|
| 120 |
function invokeRealtimePreview () { |
|---|
| 121 |
if (wndPreview && ! wndPreview.closed && wndPreview.document) |
|---|
| 122 |
wndPreview.focus (); |
|---|
| 123 |
else |
|---|
| 124 |
wndPreview = window.open ('%%RTPREVIEW_PREVIEW_URL%%'); |
|---|
| 125 |
checkPageLoaded (); |
|---|
| 126 |
} |
|---|
| 127 |
</script> |
|---|
| 128 |
HTML |
|---|
| 129 |
$add =~ s/%%RTPREVIEW_PREVIEW_URL%%/$preview_url/; |
|---|
| 130 |
$add =~ s/%%RTPREVIEW_EVENT_HANDLERS%%/$event_handlers/; |
|---|
| 131 |
|
|---|
| 132 |
$old = quotemeta ($old); |
|---|
| 133 |
$$template =~ s/($old)/$add$1/; |
|---|
| 134 |
|
|---|
| 135 |
;# Add previewing button |
|---|
| 136 |
$old = <<HTML; |
|---|
| 137 |
<input type="button" name="preview_entry" value="<MT_TRANS phrase="Preview">" accesskey="v" title="<MT_TRANS phrase="Preview this entry (p)">" onclick="submitForm(this.form, 'preview_entry')" /> |
|---|
| 138 |
HTML |
|---|
| 139 |
$add = <<HTML; |
|---|
| 140 |
<input type="button" value="Realtime Preview" title="Do realtime previewing" onclick="invokeRealtimePreview ();" /> |
|---|
| 141 |
HTML |
|---|
| 142 |
$old = quotemeta ($old); |
|---|
| 143 |
$$template =~ s/($old)/$1$add/; |
|---|
| 144 |
} |
|---|
| 145 |
|
|---|
| 146 |
|
|---|
| 147 |
;### Container tag to creat span element having the unique id. |
|---|
| 148 |
sub tag_realtime_preview { |
|---|
| 149 |
my ($ctx, $args, $cond) = @_; |
|---|
| 150 |
;# |
|---|
| 151 |
;# build contents within container tag |
|---|
| 152 |
defined (my $content = $ctx->stash('builder')->build ($ctx, $ctx->stash ('tokens'))) |
|---|
| 153 |
or return $ctx->error ($ctx->errstr); |
|---|
| 154 |
if (my $field = $args->{field}) { |
|---|
| 155 |
$content = sprintf '<span id="%s">%s</span>', tag_realtime_preview_id ($ctx, $args), $content; |
|---|
| 156 |
} |
|---|
| 157 |
return $content; |
|---|
| 158 |
} |
|---|
| 159 |
|
|---|
| 160 |
|
|---|
| 161 |
;### Tag to get the unique id. |
|---|
| 162 |
sub tag_realtime_preview_id { |
|---|
| 163 |
my ($ctx, $args) = @_; |
|---|
| 164 |
;# |
|---|
| 165 |
if (my $field = $args->{field}) { |
|---|
| 166 |
return sprintf '%s%s%d', $id_prefix, $field, ++$ctx->{__stash}{__PACKAGE__. $field}; |
|---|
| 167 |
} |
|---|
| 168 |
return ''; |
|---|
| 169 |
} |
|---|
| 170 |
|
|---|
| 171 |
1; |
|---|