diff --git a/MenuItem.php b/MenuItem.php new file mode 100644 index 0000000..ae8bc70 --- /dev/null +++ b/MenuItem.php @@ -0,0 +1,32 @@ +getLang('menu_recommend'); + } +} diff --git a/TPL_EXAMPLE.txt b/TPL_EXAMPLE.txt deleted file mode 100644 index b0f8776..0000000 --- a/TPL_EXAMPLE.txt +++ /dev/null @@ -1,8 +0,0 @@ - 'recommend', 'id' => $ID)); -} -?> diff --git a/action.php b/action.php index dd87823..6df69be 100644 --- a/action.php +++ b/action.php @@ -1,22 +1,24 @@ register_hook($event, 'BEFORE', $this, '_handle'); + $controller->register_hook($event, 'BEFORE', $this, 'handle'); } + $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handleMenu'); + $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'autocomplete'); } - function _handle(&$event, $param) { - if (!in_array($event->data, array('recommend', 'plugin_recommend'))) { + /** + * Main processing + * + * @param Doku_Event $event + * @return void + */ + public function handle(Doku_Event $event) { + if ($event->data !=='recommend') { return; } @@ -28,112 +30,203 @@ function _handle(&$event, $param) { $event->stopPropagation(); - if ($_SERVER['REQUEST_METHOD'] == 'POST' && - isset($_POST['sectok']) && - !($err = $this->_handle_post())) { - if ($event->name === 'AJAX_CALL_UNKNOWN') { - /* To signal success to AJAX. */ - header('HTTP/1.1 204 No Content'); - return; + global $INPUT; + + // early output to trigger display msgs even via AJAX. + echo ' '; + tpl_flush(); + if ($INPUT->server->str('REQUEST_METHOD') === 'POST') { + try { + $this->handlePost(); + if ($event->name === 'AJAX_CALL_UNKNOWN') { + $this->ajaxSuccess(); // To signal success to AJAX. + } else { + msg($this->getLang('thanks'), 1); + } + return; // we're done here + } catch (\Exception $e) { + msg($e->getMessage(), -1); } - echo 'Thanks for recommending our site.'; + } + + echo $this->getForm(); + } + + /** + * Page menu item + * + * @param Doku_Event $event + * @return void + */ + public function handleMenu(Doku_Event $event) + { + if ($event->data['view'] !== 'page') return; + // menu item is only for logged in users + if (empty($_SERVER['REMOTE_USER'])) return; + + array_splice($event->data['items'], -1, 0, [new \dokuwiki\plugin\recommend\MenuItem()]); + } + + /** + * Autocomplete + * @param Doku_Event $event + * @throws Exception + * @author Andreas Gohr + * + */ + public function autocomplete(Doku_Event $event) + { + + if ($event->data !=='plugin_recommend_ac') { return; } - /* To display msgs even via AJAX. */ - echo ' '; - if (isset($err)) { - msg($err, -1); + + $event->preventDefault(); + $event->stopPropagation(); + + /** @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + global $INPUT; + + if (!$auth->canDo('getUsers')) { + throw new Exception('The user backend can not search for users'); } - $this->_show_form(); - } - function _show_form() { - $r_name = isset($_REQUEST['r_name']) ? $_REQUEST['r_name'] : ''; - $r_email = isset($_REQUEST['r_email']) ? $_REQUEST['r_email'] : ''; - $s_name = isset($_REQUEST['s_name']) ? $_REQUEST['s_name'] : ''; - $s_email = isset($_REQUEST['s_email']) ? $_REQUEST['s_email'] : ''; - $comment = isset($_REQUEST['comment']) ? $_REQUEST['r_comment'] : ''; - if (isset($_REQUEST['id'])) { - $id = $_REQUEST['id']; - } else { - global $ID; - if (!isset($ID)) { - msg('Unknown page', -1); - return; - } - $id = $ID; + header('Content-Type: application/json'); + + // check minimum length + $lookup = trim($INPUT->str('search')); + if (utf8_strlen($lookup) < 3) { + echo json_encode([]); + return; + } + + // find users by login and name + $logins = $auth->retrieveUsers(0, 10, ['user' => $lookup]); + if (count($logins) < 10) { + $logins = array_merge($logins, $auth->retrieveUsers(0, 10, ['name' => $lookup])); } - $form = new Doku_Form('recommend_plugin', '?do=recommend'); - $form->addHidden('id', $id); - $form->startFieldset('Recommend page “' . hsc($id). '”'); - if (isset($_SERVER['REMOTE_USER'])) { + + // reformat result for jQuery UI Autocomplete + $users = []; + foreach ($logins as $login => $info) { + $users[] = [ + 'label' => $info['name'] . ' [' . $login . ']', + 'value' => $login + ]; + } + + echo json_encode($users); + } + + /** + * Returns rendered form + * + * @return string + */ + protected function getForm() + { + global $INPUT; + + $id = getID(); // we may run in AJAX context + if ($id === '') throw new \RuntimeException('No ID given'); + + $form = new \dokuwiki\Form\Form([ + 'action' => wl($id, ['do' => 'recommend'], false, '&'), + 'id' => 'plugin__recommend', + ]); + $form->setHiddenField('id', $id); // we need it for the ajax call + + /** @var helper_plugin_recommend_assignment $helper */ + $helper = plugin_load('helper', 'recommend_assignment'); + $template = $helper->loadMatchingTemplate(); + + if ($INPUT->server->has('REMOTE_USER')) { global $USERINFO; - $form->addHidden('s_name', $USERINFO['name']); - $form->addHidden('s_email', $USERINFO['mail']); + $form->setHiddenField('s_name', $USERINFO['name']); + $form->setHiddenField('s_email', $USERINFO['mail']); } else { - $form->addElement(form_makeTextField('s_name', $s_name, 'Your name')); - $form->addElement(form_makeTextField('s_email', $s_email, - 'Your email address')); - } - $form->addElement(form_makeTextField('r_name', $r_name, 'Recipient name')); - $form->addElement(form_makeTextField('r_email', $r_email, - 'Recipient email address')); - $form->addElement(''); - $helper = null; - if(@is_dir(DOKU_PLUGIN.'captcha')) $helper = plugin_load('helper','captcha'); - if(!is_null($helper) && $helper->isEnabled()){ - $form->addElement($helper->getHTML()); - } - - $form->addElement(form_makeButton('submit', '', 'Send recommendation')); - $form->addElement(form_makeButton('submit', 'cancel', 'Cancel')); - $form->printForm(); + $form->addTextInput('s_name', $this->getLang('yourname'))->addClass('edit'); + $form->addTextInput('s_email', $this->getLang('youremailaddress'))->addClass('edit'); + } + + $form->addTextInput('r_email', $this->getLang('recipients')) + ->addClass('edit') + ->val($template['user'] ?? ''); + $form->addTextInput('subject', $this->getLang('subject')) + ->addClass('edit') + ->val($template['subject'] ?? ''); + $form->addTextarea('comment', $this->getLang('message')) + ->attr('rows', '8') + ->attr('cols', '40') + ->addClass('edit') + ->val($template['message'] ?? ''); + + /** @var helper_plugin_captcha $captcha */ + $captcha = plugin_load('helper', 'captcha'); + if ($captcha) $form->addHTML($captcha->getHTML()); + + $form->addTagOpen('div')->addClass('buttons'); + $form->addButton('submit', $this->getLang('send'))->attr('type', 'submit'); + $form->addTagClose('div'); + + return $form->toHTML(); } - function _handle_post() { - $helper = null; - if(@is_dir(DOKU_PLUGIN.'captcha')) $helper = plugin_load('helper','captcha'); - if(!is_null($helper) && $helper->isEnabled() && !$helper->check()) { - return 'Wrong captcha'; + /** + * Handles form submission + * + * @throws Exception + */ + protected function handlePost() + { + global $INPUT; + + if (!checkSecurityToken()) { + throw new \Exception('Security token did not match'); } - /* Validate input. */ - if (!isset($_POST['r_email']) || !mail_isvalid($_POST['r_email'])) { - return 'Invalid recipient email address submitted'; + /** @var helper_plugin_recommend_mail $mailHelper */ + $mailHelper = plugin_load('helper', 'recommend_mail'); + + // Captcha plugin + $captcha = null; + if (@is_dir(DOKU_PLUGIN . 'captcha')) $captcha = plugin_load('helper','captcha'); + if (!is_null($captcha) && $captcha->isEnabled() && !$captcha->check()) { + throw new \Exception($this->getLang('err_captcha')); } - if (!isset($_POST['r_name']) || trim($_POST['r_name']) === '') { - return 'Invalid recipient name submitted'; + + /* Validate input */ + $recipients = $INPUT->str('r_email'); + + if (empty($recipients)) { + throw new \Exception($this->getLang('err_recipient')); } - $r_name = $_POST['r_name']; - $recipient = $r_name . ' <' . $_POST['r_email'] . '>'; + + $recipients = $mailHelper->resolveRecipients($recipients); + $recipients = implode(',', $recipients); if (!isset($_POST['s_email']) || !mail_isvalid($_POST['s_email'])) { - return 'Invalid sender email address submitted'; + throw new \Exception($this->getLang('err_sendermail')); } if (!isset($_POST['s_name']) || trim($_POST['s_name']) === '') { - return 'Invalid sender name submitted'; + throw new \Exception($this->getLang('err_sendername')); } $s_name = $_POST['s_name']; $sender = $s_name . ' <' . $_POST['s_email'] . '>'; - if (!isset($_POST['id']) || !page_exists($_POST['id'])) { - return 'Invalid page submitted'; - } - $page = $_POST['id']; + $id = $INPUT->filter('cleanID')->str('id'); + if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page')); - $comment = isset($_POST['comment']) ? $_POST['comment'] : null; + $comment = $INPUT->str('comment'); - /* Prepare mail text. */ - $mailtext = file_get_contents(dirname(__FILE__).'/template.txt'); + /* Prepare mail text */ + $mailtext = file_get_contents($this->localFN('template')); global $conf; - global $USERINFO; - foreach (array('NAME' => $r_name, - 'PAGE' => $page, + foreach (array('PAGE' => $id, 'SITE' => $conf['title'], - 'URL' => wl($page, '', true), + 'URL' => wl($id, '', true), 'COMMENT' => $comment, 'AUTHOR' => $s_name) as $var => $val) { $mailtext = str_replace('@' . $var . '@', $val, $mailtext); @@ -141,10 +234,24 @@ function _handle_post() { /* Limit to two empty lines. */ $mailtext = preg_replace('/\n{4,}/', "\n\n\n", $mailtext); - /* Perform stuff. */ - mail_send($recipient, 'Page recommendation', $mailtext, $sender); - $log = new Plugin_Recommend_Log(date('Y-m')); - $log->writeEntry($page, $sender, $recipient, $comment); - return false; + $mailHelper->sendMail($recipients, $mailtext, $sender); + + /** @var helper_plugin_recommend_log $log */ + $log = new helper_plugin_recommend_log(date('Y-m')); + $log->writeEntry($id, $sender, $recipients, $comment); + } + + /** + * show success message in ajax mode + */ + protected function ajaxSuccess() + { + echo '
'; + echo '
'; + echo ''; + echo '

' . $this->getLang('done') . '

'; + echo ''; + echo '
'; + echo '
'; } } diff --git a/admin.php b/admin.php index 26e3128..a4ccd98 100644 --- a/admin.php +++ b/admin.php @@ -1,52 +1,154 @@ month = $_REQUEST['rec_month']; } else { $this->month = date('Y-m'); } - $log = new Plugin_Recommend_Log($this->month); + $log = new helper_plugin_recommend_log($this->month); $this->entries = $log->getEntries(); - $this->logs = Plugin_Recommend_Log::getLogs(); + $this->logs = $log->getLogs(); + + global $INPUT; + global $ID; + + /** @var helper_plugin_recommend_assignment $assignmentsHelper */ + $assignmentsHelper = plugin_load('helper', 'recommend_assignment'); + + if ($INPUT->str('action') && $INPUT->arr('assignment') && checkSecurityToken()) { + $assignment = $INPUT->arr('assignment'); + if ($INPUT->str('action') === 'delete') { + $ok = $assignmentsHelper->removeAssignment($assignment); + if (!$ok) { + msg('failed to remove pattern', -1); + } + } elseif ($INPUT->str('action') === 'add') { + if ($assignment['pattern'][0] == '/') { + if (@preg_match($assignment['pattern'], null) === false) { + msg('Invalid regular expression. Pattern not saved', -1); + } else { + $ok = $assignmentsHelper->addAssignment($assignment); + if (!$ok) { + msg('failed to add pattern', -1); + } + } + } else { + $ok = $assignmentsHelper->addAssignment($assignment); + if (!$ok) { + msg('failed to add pattern', -1); + } + } + + } + + send_redirect(wl($ID, array('do' => 'admin', 'page' => 'recommend'), true, '&')); + } } - function getTOC() { - return array_map('recommend_make_toc', $this->logs); + public function getTOC() { + return array_map([$this, 'recommendMakeTOC'], $this->logs); } - function html() { + public function html() { + echo $this->locale_xhtml('intro'); + if (!$this->logs) { echo 'No recommendations.'; - return; } if (!$this->entries) { echo 'No recommendations were made in ' . $this->month . '.'; - return; } + + echo '

' . $this->getLang('headline_snippets') . '

'; + + echo $this->getForm(); + + echo '

' . $this->getLang('headline_logs') . '

'; echo '

In ' . $this->month . ', your users made the following ' . count($this->entries) . ' recommendations:

'; echo ''; } -} -function recommend_make_toc($month) { - global $ID; - return html_mktocitem('?do=admin&page=recommend&id=' . $ID . '&rec_month=' . $month, $month, 1, ''); + protected function getForm() + { + global $ID; + $assignments = helper_plugin_recommend_assignment::getAssignments(); + + $form = '
'; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + + // header + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + + // existing assignments + foreach ($assignments as $assignment) { + $pattern = $assignment['pattern']; + $user = $assignment['user']; + $subject = $assignment['subject']; + $message = $assignment['message']; + + $link = wl( + $ID, + [ + 'do' => 'admin', + 'page' => 'recommend', + 'action' => 'delete', + 'sectok' => getSecurityToken(), + 'assignment[pattern]' => $pattern, + 'assignment[user]' => $user, + 'assignment[subject]' => $subject, + 'assignment[message]' => $message, + ] + ); + + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + } + + // new assignment form + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + $form .= ''; + + $form .= '
' . $this->getLang('assign_pattern') . '' . $this->getLang('assign_user') . '' . $this->getLang('assign_subject') . '' . $this->getLang('assign_message') . '
' . hsc($pattern) . '' . hsc($user) . '' . hsc($subject) . '' . nl2br($message) . '' . $this->getLang('assign_del') . '
'; + $form .= '
'; + + return $form; + } + + protected function recommendMakeTOC($month) { + global $ID; + return html_mktocitem('?do=admin&page=recommend&id=' . $ID . '&rec_month=' . $month, $month, 2, ''); + } } diff --git a/admin.svg b/admin.svg new file mode 100644 index 0000000..2e6aa01 --- /dev/null +++ b/admin.svg @@ -0,0 +1,3 @@ + + + diff --git a/conf/default.php b/conf/default.php index c789b94..05acb11 100644 --- a/conf/default.php +++ b/conf/default.php @@ -1,2 +1,2 @@ path = DOKU_INC . 'data/cache/recommend'; + if (!file_exists($this->path)) { + mkdir($this->path); + } + $this->path .= '/' . $month . '.log'; + } + + public function getLogs() + { + return array_map([$this, 'recommend_strip_extension'], glob(DOKU_INC . 'data/cache/recommend/*.log')); + } + + public function getEntries() + { + return @file($this->path); + } + + public function writeEntry($page, $sender, $receiver, $comment) + { + $comment = str_replace(["\n", '"'], ['', '\''], $comment); + $logfile = fopen($this->path, 'a'); + fwrite($logfile, date('r') . ': ' . + "“${sender}” recommended “${page}” to " . + "“${receiver}” with comment “${comment}”.\n"); + fclose($logfile); + } + + + protected function recommend_strip_extension($str) { + return substr(basename($str), 0, -4); + } +} diff --git a/helper/mail.php b/helper/mail.php new file mode 100644 index 0000000..75ae0b6 --- /dev/null +++ b/helper/mail.php @@ -0,0 +1,115 @@ +bcc($recipient); + $mailer->from($sender); + + $subject = $INPUT->str('subject'); + $mailer->subject($subject); + $mailer->setBody($mailtext); + $mailer->send(); + } + + /** + * Processes recipients from input and returns an array of emails + * with user groups resolved to individual users + * + * @param string $recipients + * @return array + * @throws Exception + */ + public function resolveRecipients($recipients) + { + $resolved = []; + + $recipients = explode(',', $recipients); + + foreach ($recipients as $recipient) { + $recipient = trim($recipient); + + if ($recipient[0] === '@') { + $this->resolveGroup($resolved, $recipient); + } elseif (strpos($recipient, '@') === false) { + $this->resolveUser($resolved, $recipient); + } else { + if (!$this->emailIsValid($recipient)) { + throw new \Exception($this->getLang('err_recipient')); + } + $resolved[] = $recipient; + } + } + return $resolved; + } + + /** + * @param array $resolved + * @param string $recipient + * @return void + * @throws Exception + */ + protected function resolveGroup(&$resolved, $recipient) + { + /** @var AuthPlugin $auth */ + global $auth; + if (!$auth->canDo('getUsers')) { + throw new \Exception('Auth cannot fetch users by group.'); + } + + $users = $auth->retrieveUsers(0, 0, ['grps' => substr($recipient, 1)]); + foreach ($users as $user) { + $resolved[] = $user['mail']; + } + } + + /** + * @param array $resolved + * @param string $recipient + * @return void + */ + protected function resolveUser(&$resolved, $recipient) + { + /** @var AuthPlugin $auth */ + global $auth; + $user = $auth->getUserData($recipient); + if ($user) $resolved[] = $user['mail']; + } + + /** + * Checks validity of given mail. With config 'wikionly' set to true + * also checks if user with this email is known. + * + * @param $mail + * @return bool + * @throws Exception + */ + protected function emailIsValid($mail) + { + if(!$this->getConf('wikionly')) return mail_isvalid($mail); + + /** @var AuthPlugin $auth */ + global $auth; + if (!$auth->canDo('getUsers')) { + throw new \Exception('Auth cannot fetch users by email.'); + } + + $user = $auth->retrieveUsers(0, 1, ['mail' => $mail]); + return (bool)$user; + } +} diff --git a/lang/de/intro.txt b/lang/de/intro.txt new file mode 100644 index 0000000..1cbfaca --- /dev/null +++ b/lang/de/intro.txt @@ -0,0 +1,9 @@ +===== Recommend ===== + +Hier kannst du Standardwerte für Nachrichten hinterlegen. + +Seite/Namensraum: + * Seiten-ID + * Namensräume, mit Ausnahme von untergeordneten Namensräumen, werden als ''namespace:*'' definiert. + * Namensräume, einschließlich untergeordneten Namensräumen, werden als ''namespace:**'' definiert. + * Reguläre Ausdrücke, welche mit ''/'' beginnen und enden, werden mit einem vorangestellten '':'' mit der kompletten Seiten-ID verglichen diff --git a/lang/de/lang.php b/lang/de/lang.php new file mode 100644 index 0000000..a65c44b --- /dev/null +++ b/lang/de/lang.php @@ -0,0 +1,32 @@ +namespace:*'' + * Namespace including subnamespaces are defined as ''namespace:**'' + * Regular expressions starting and ending with ''/'' are matched against a '':'' prefixed full page id diff --git a/lang/en/lang.php b/lang/en/lang.php new file mode 100644 index 0000000..3096b2f --- /dev/null +++ b/lang/en/lang.php @@ -0,0 +1,32 @@ +path = DOKU_INC . 'data/cache/recommend'; - if (!file_exists($this->path)) { - mkdir($this->path); - } - $this->path .= '/' . $month . '.log'; - } - - function getLogs() { - return array_map('recommend_strip_extension', glob(DOKU_INC . 'data/cache/recommend/*.log')); - } - - function getEntries() { - return @file($this->path); - } - - function writeEntry($page, $sender, $receiver, $comment) { - $logfile = fopen($this->path, 'a'); - fwrite($logfile, date('r') . ': ' . - "“${sender}” recommended “${page}” to " . - "“${receiver}” with comment “${comment}”.\n"); - fclose($logfile); - } -} - -function recommend_strip_extension($str) { - return substr(basename($str), 0, -4); -} diff --git a/plugin.info.txt b/plugin.info.txt index bd8537e..e20443c 100644 --- a/plugin.info.txt +++ b/plugin.info.txt @@ -1,7 +1,7 @@ base recommend -author Adrian Lang +author Adrian Lang, Andreas Gohr, Anna Dabrowska email dokuwiki@cosmocode.de -date 2016-07-06 -name recommend +date 2022-11-23 +name recommend desc Allows to recommend a page via email url http://www.dokuwiki.org/plugin:recommend diff --git a/script.js b/script.js index b7e2601..1e44328 100644 --- a/script.js +++ b/script.js @@ -1,78 +1,148 @@ -(function () { +/** + * jQuery rewrite is almost completely taken from infomail plugin + * @author Andreas Gohr + */ -/* Lib */ +const recommend = { + $dialog: null, -var recommend_ajax_call = 'plugin_recommend'; + /** + * Attach click handler to our link + */ + init: function () { + jQuery('a.plugin_recommend').click(recommend.initform); + jQuery('li.recommend a').click(recommend.initform); + }, -function sack_form(form, fnc) { - var ajax = new sack(DOKU_BASE + 'lib/exe/ajax.php'); - ajax.setVar('call', recommend_ajax_call); - function serializeByTag(tag) { - var inps = form.getElementsByTagName(tag); - for (var inp in inps) { - if (inps[inp].name) { - ajax.setVar(inps[inp].name, inps[inp].value); - } + /** + * Initializes the form dialog on click + * + * @param {Event} e + */ + initform: function (e) { + e.stopPropagation(); + e.preventDefault(); + + let url = new URL(e.currentTarget.href); + // searchParams only works, when no URL rewriting takes place + // from Dokuwiki - else there is no parameter id and this + // returns null + let id = url.searchParams.get('id'); + if ( id === null ) { + // Convert url to string an get the last part without + // any parameters from actions and the like + url = String(url); + id = url.split('/').pop().split('?')[0]; } - } - serializeByTag('input'); - serializeByTag('textarea'); - ajax.onCompletion = fnc; - ajax.runAJAX(); - return false; -} -function bind(fnc, val) { - return function () { - return fnc(val); - }; -} + recommend.$dialog = jQuery('
'); + recommend.$dialog.dialog( + { + modal: true, + title: LANG.plugins.recommend.formname + ' ' + id, + minWidth: 680, + height: "auto", + close: function () { + recommend.$dialog.dialog('destroy') + } + } + ); -function change_form_handler(forms, handler) { - if (!forms) return; - for (var formid in forms) { - var form = forms[formid]; - form.onsubmit = bind(handler, form); - } -} + jQuery.get( + DOKU_BASE + 'lib/exe/ajax.php', + { + 'call': 'recommend', + 'id': id + }, + recommend.handleResult, + 'html' + ); + }, -/* Recommend */ + /** + * Display the result and attach handlers + * + * @param {string} data The HTML + */ + handleResult: function (data) { -function recommend_box(content) { - var div = $('recommend_box'); - if (!div) { - div = document.createElement('div'); - div.id = 'recommend_box'; - } else if (content === '') { - div.parentNode.removeChild(div); - return; - } - div.innerHTML = content; - document.body.appendChild(div); - return div; -} + function commasplit( val ) { + return val.split( /,\s*/ ); + } -function recommend_handle() { - if (this.response === "AJAX call '" + recommend_ajax_call + "' unknown!\n") { - /* No user logged in. */ - return; - } - if (this.responseStatus[0] === 204) { - var box = recommend_box('
FinishedThanks for recommending our site.

'); - } else { + recommend.$dialog.html(data); + recommend.$dialog.find('button[type=reset]').click(recommend.cancel); + recommend.$dialog.find('button[type=submit]').click(recommend.send); + recommend.$dialog.find('input[name=r_email]').autocomplete({ + source: function (request, cb) { + let term = request.term; + term = commasplit(term).pop(); - var box = recommend_box(this.response); - box.getElementsByTagName('label')[0].focus(); - change_form_handler(box.getElementsByTagName('form'), - function (form) {return sack_form(form, recommend_handle); }); - } - var inputs = box.getElementsByTagName('input'); - inputs[inputs.length - 1].onclick = function() {recommend_box(''); return false;}; -} + const payload = {}; + payload['call'] = 'plugin_recommend_ac'; + payload['search'] = term; + + jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', payload, cb, 'json') + .fail(function (result) { + if (result.responseJSON) { + if (result.responseJSON.stacktrace) { + console.error(result.responseJSON.error + "\n" + result.responseJSON.stacktrace); + } + alert(result.responseJSON.error); + } else { + // some fatal error occurred, get a text only version of the response + alert(jQuery(result.responseText).text()); + } + }); + }, + focus: function() { + // prevent value inserted on focus + return false; + }, + select: function( event, ui ) { + let terms = commasplit( this.value ); + // remove the current input + terms.pop(); + // add the selected item + terms.push( ui.item.value ); + // add placeholder to get the comma-and-space at the end + terms.push( "" ); + this.value = terms.join( ", " ); + return false; + } + }); + }, -addInitEvent(function () { - change_form_handler(getElementsByClass('btn_recommend', document, 'form'), - function (form) {return sack_form(form, recommend_handle); }); - }); + /** + * Cancel the recommend form + * + * @param {Event} e + */ + cancel: function (e) { + e.preventDefault(); + e.stopPropagation(); + recommend.$dialog.dialog('destroy'); + }, -}()); + /** + * Serialize the form and send it + * + * @param {Event} e + */ + send: function (e) { + e.preventDefault(); + e.stopPropagation(); + + let data = recommend.$dialog.find('form').serialize(); + data = data + '&call=recommend'; + + recommend.$dialog.html('...'); + jQuery.post( + DOKU_BASE + 'lib/exe/ajax.php', + data, + recommend.handleResult, + 'html' + ); + } +}; +jQuery(recommend.init); diff --git a/style.css b/style.css index 8305428..5d24abe 100644 --- a/style.css +++ b/style.css @@ -11,48 +11,48 @@ background: white; } -div.recommend_plugin { +div.plugin__recommend { width: 50%; text-align: center; font-size: 120%; padding: 2em; } -form#recommend_plugin { +form#plugin__recommend { width: 100%; text-align: center; } -form#recommend_plugin p { +form#plugin__recommend p { font-size: 90%; text-align: left; } -form#recommend_plugin fieldset { +form#plugin__recommend fieldset { width: 90%; } -form#recommend_plugin label { +form#plugin__recommend label { display: block; overflow: auto; margin: 5px; } -form#recommend_plugin label span { - width: 48%; +form#plugin__recommend label span { + width: 28%; text-align: right; display: block; float: left; } -form#recommend_plugin label input { +form#plugin__recommend label input { float: left; margin-left: 5px; } -form#recommend_plugin label textarea.edit, -form#recommend_plugin label input.edit { - width: 48%; +form#plugin__recommend label textarea.edit, +form#plugin__recommend label input.edit { + width: 68%; display: block; float: left; margin-left: 5px; diff --git a/template.txt b/template.txt deleted file mode 100644 index 3d8566d..0000000 --- a/template.txt +++ /dev/null @@ -1,9 +0,0 @@ -Hi @NAME@, - -I would like to recommend you the page “@PAGE@” on @SITE@ (@URL@). - -@COMMENT@ - -Bye, - -@AUTHOR@