//
//

{comment}

//
//
// maximum of levels to be styled var maxLevels = 20; // indent steps (pixel) var indentPixels = 40; for (i = 1; i <= maxLevels; i++) { // indent by level var indent = (i - 1) * indentPixels; $('.level' + i).parent().css({"margin-left" : indent + "px"}); $('.level' + i).parent().prev().css({"margin-left" : indent + "px"}); // build link to open comment box // save label ("Add Comment") var label = $('.level' + i).find('.prompt').html(); // display label $('

' + label + '

').insertBefore('.level' + i).children('form'); } // hide forms $('.add_comment').next('div').children('form').css({"display" : "none"}); // make label clickable $('.add_comment').css({"cursor": "pointer","font-size" : "smaller","text-decoration" : "underline"}); // add functionality to clickable label $('.add_comment').click( function() { if ( $(this).next('div').children('form').css("display") == "none" ) { // hide previously opened form $('.add_comment').next('div').children('form').stop().slideUp(200); $(this).next('div').children('form').stop().height('auto').slideDown(400); } else { $(this).next('div').children('form').stop().slideUp(200); } } ); }); // $(document).ready(function() * * comment4comment.php is an adaption of: * commentboxstyled.php Copyright 2005, 2006 Hans Bracker, an adaptation of commentbox.php by John Rankin, copyright 2004, 2005 John Rankin john.rankin@affinity.co.nz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Put commentboxplus.css file into $Farm/pub/css/ directory. Adds (:commentbox:) and (:commentboxchrono:) markups. Put (:commentbox:) at the top of a page, or a GroupHeader, latest entries appear at top, underneat the commentbox, i.e. in reverse chronological order. Put (:commentboxchrono:) at the bottom of a page, or a GroupFooter, latest entries appear at bottom, above the commentbox, i.e. in chronological order. (:commentbox SomePageName:) or (:commentboxchrono SomePageName:) will post the comment on page 'SomePageName' instead of the page where the commentbox is. Adds commentbox with chronologfical entries automatically to pages which contain 'Journal' or 'Diary' in their name. If you use forms markup instead of (:commentbox:) or (:commentboxchrono:) markup, add name=cboxform to (:input form ....:), which functions as an identifier for the internal authentication check. You can hide the commentbox for users who have no page edit permissions with conditional markup of the EXACT form: (:if auth edit:)(:commentbox:)(:if:) and set $MPAnchorFmt = "(:commentbox:)(:if:)"; if comments should be placed underneath the commentbox or (for commentboxchrono) (:if auth edit:)(:commentboxchrono:)(:if:) and set $MPAnchorChronoFmt = "(:if auth edit:)(:commentboxchrono:)"; if comments should be placed above the commentbox Otherwise users can post comments even if they don't have page edit permission. You can also set $MPAnchorFmt and $MPAnchorChronoFmt to some different string to use as an anchor for positioning the comments. For instance set $MPAnchorFmt = "[[#comments]]"; and place [[#comments]] somewhere on the page, then the comment posts will appear BENEATH this anchor. But note: setting $MPAnchorChronoFmt = "[[#comments]]"; and place [[#comments]] somewhere on the page, then the comment posts will appear ABOVE this anchor. */ # Version date $RecipeInfo['comment4comment']['Version'] = '2010-06-02'; # enable page breaks after a number of posts: set in config.php $EnablePageBreaks = 1; # requires installing pagebreak2.php. See Cookbook.BreakPage SDV($EnablePageBreaks, false); # default is No Page Breaks # with $EnablePageBreaks = 1; set number of posts per page: for instance $PostsPerPage = 50; SDV($PostsPerPage,20); # default is 20 posts. # The form check will display a warning message if user has not provided content and name. # Set to false if no javascript form check is required. SDV($EnableCommentFormCheck, 0); SDV($NoCommentMessage, '$[Please enter a comment to post]'); SDV($NoAuthorMessage, '$[Please enter your name as author]'); SDV($NoCodeMessage, '$[Please enter the code number]'); # Set $EnableAccessCode to true if you want your users to enter a random # generated access code number in order to post. # This may stop robot scripts from posting. SDV($EnableAccessCode, false); # Set $EnableWebsiteField to true if you want an extra field for users to enter # a website beside their name. SDV($EnableWebsiteField, false); # Set $EnablePreventDirectives to true if you want to prevent users from posting # any kind of directive (: ... :) SDV($EnablePreventDirectives, false); # Set $EnablPostToAnyPage = 1; if you want users to be able to post comments # to other pages than the current one, in conjunction with the use of # the markup (:commentbox GroupName.PageName:) or a postto form field. # Be aware there is a security risk in this, as users could write markup to post to # edit protected or admin only pages as in the Site group. To counteract this risk # include this script (or set $EnablePostToAnyPage =1;) ONLY FOR THOSE PAGES(s) a # commentbox form shall be used, AND PROTECT THESE PAGES by restricting edit access to them! SDV($EnablePostToAnyPage, 0); # set $EnablePostToGroupPage = 1; to allow posting to pages in the same group # as the page with the (:commentbox:) form SDV($EnablePostToGroupPage, 0); # default list of pages allowed to post to SDVA($PostToCommentPageFmt, array( '{$Group}.{$Name}-Comments', '{$Group}.{$Name}-Discuss', 'Comments.{$Group}-{$Name}', )); # set $RedirectToCommentPage = 1; if users shall be redirected after posting to a comment page # specified with (:commnetbox Group.TargetPage:). # Default is 0: users stay on the page where the commentbox form is. SDV($EnableRedirectToCommentPage, 0); # load commentbox.css for styling SDV($CommentBoxPlusUrl, (substr(__FILE__, 0, strlen($FarmD)) == $FarmD) ? '$FarmPubDirUrl/commentboxplus' : '$PubDirUrl/commentboxplus'); SDV($HTMLHeaderFmt['cbplus'], " "); if($EnableCommentFormCheck==1) { $CommentBoxCheckFmt = " "; # add markup (:cboxcheck:) for use when commentbox is constucted with (:input:) markup Markup('cboxcheck', '>block', '/\\(:cboxcheck:\\)/', Keep($CommentBoxCheckFmt)); } SDV($DiaryBoxFmt,"
$[New entry] 
". (isset($EnablePostCaptchaRequired) ? "
Enter code: \$Captcha " : ""). ($EnableAccessCode ? "
$[Enter code] \$AccessCode " : "
"). "
"); SDV($commentLevel,0); function getFormHtml($commentLevel,$id) { // set styles // (affects only the form) // (the comment as a whole is styled by javascript, documented at the beginning of this file) // margin left $styles[] = 'margin-left: ' . $commentLevel * 30 . 'px;'; // build attribute 'styles' $styles = 'style="' . implode('',$styles) . '"'; return "
$[Add Comment] 
$[Sign as Author]  ". ($EnableWebsiteField ? "
$[Website]  " : ""). (isset($EnablePostCaptchaRequired) ? "
Enter code: \$Captcha " : ""). ($EnableAccessCode ? "
$[Enter code] \$AccessCode " : ""). "

". ($EnableCommentFormCheck ? $CommentBoxCheckFmt : ""); } SDV($CommentBoxFmt,$commentBoxHtml); # date and time formats SDV($JournalDateFmt,'%d %B %Y'); SDV($JournalTimeFmt,'%H:%M'); # journal and diary patterns as part of page name SDV($JournalPattern,'/Journal$/'); SDV($DiaryPattern,'/Diary$/'); # comment authentication SDV($HandleAuth['comment'], 'read'); $HandleActions['comment'] = 'HandleCommentPost'; Markup('cbox',''.Keep(str_replace(array('\$Chrono','\$PostTo','\$AccessCode','\$CaptchaValue'), array('$1','$2',RandomAccess(), CaptchaValueRelay()), FmtPageName(getFormHtml($commentLevel,0),\$pagename)))"); Markup('dbox',''.str_replace('\$AccessCode',RandomAccess(), FmtPageName(\$GLOBALS['DiaryBoxFmt'],\$pagename))"); // Create Forms for commenting comments Markup('comment4comment',''.Keep(str_replace(array('\$Chrono','\$PostTo','\$AccessCode','\$CaptchaValue'), array('chrono','',RandomAccess(), CaptchaValueRelay()), FmtPageName(getFormHtml('$1','$2'),\$pagename)))"); if (preg_match($JournalPattern,$pagename) || preg_match($DiaryPattern,$pagename)) { $GroupHeaderFmt .= '(:if auth edit:)(:diarybox:)(:if:)(:nl:)'; if (!PageExists($pagename)) $DefaultPageTextFmt = ''; } if ($action=='print' || $action=='publish') Markup('cbox','$MaxLinkCount) ? false : true; } function HandleCommentPost($pagename, $auth) { global $commentBoxHtml,$JournalPattern, $DiaryPattern, $Author, $EnablePostCaptchaRequired, $IsPagePosted, $EnableRedirectToCommentPage, $PostToCommentPageFmt, $EnablePostToAnyPage, $EnablePostToGroupPage, $EnablePreventDirectives; $req = CBRequestArgs(); if(auditJP('', $req)==false) Redirect($pagename); if($EnablePostCaptchaRequired AND !IsCaptcha()) Redirect($pagename); if (!$req['post'] || $req['text']=='') Redirect($pagename); if ($req['author']=='') $Author = 'anonymous'; $currpage = $pagename; // set current page $currgroup = PageVar($pagename, '$Group'); // handling of postto page if (!$req['postto']=='') { $tgtpage = MakePageName($pagename, $req['postto']); $tgtgroup = PageVar($tgtpage, '$Group'); $tgtname = PageVar($tgtpage, '$Name'); if($EnablePostToAnyPage==1) $pagename = $tgtpage; if($EnablePostToGroupPage==1 AND $tgtgroup==$currgroup ) $pagename = $tgtpage; else { foreach($PostToCommentPageFmt as $n ) { $n = FmtPageName($n, $pagename); if($n==$tgtpage) { $tgt = 1; $pagename = $tgtpage; continue; } } if(!isset($tgt)) { CBMessage("ERROR: No permission to post to $tgtpage"); HandleBrowse($currpage); exit; } } } if ($EnablePreventDirectives==1) { $req['text'] = preg_replace('/\\(:/', '(:', $req['text']); $req['author'] = preg_replace('/\\(:/', '(:', $req['author']); } $page = RetrieveAuthPage($pagename, $auth, true); $HandleCommentFunction = (preg_match($JournalPattern,$pagename)) ? 'Journal' : ((preg_match($DiaryPattern,$pagename)) ? 'Diary' : 'Message'); $HandleCommentFunction = 'Handle' . $HandleCommentFunction . 'Post'; $newpage = $page; $newpage['text'] = $HandleCommentFunction($pagename, $req, $page['text']); UpdatePage($pagename, $page, $newpage); if($EnableRedirectToCommentPage==1) Redirect($pagename); if ($IsPagePosted && $tgtpage) CBMessage("Successful post to $tgtpage"); HandleBrowse($currpage); exit; } function FormatDateHeading($txt,$datefmt,$fmt) { return str_replace($txt,strftime($datefmt,time()),$fmt); } ## Journal entry function HandleJournalPost($pagename, $req, $pagetext) { global $JournalDateFmt,$JournalTimeFmt,$JPItemStartFmt,$JPItemEndFmt,$JPDateFmt,$JPTimeFmt, $Author; SDV($JPDateFmt,'>>journaldate<<(:nl:)!!!!$Date'); SDV($JPTimeFmt,"\n>>journalhead<<\n!!!!!– \$Time –\n"); SDV($JPItemStartFmt,">>journalitem<<\n"); SDV($JPItemEndFmt,""); $date = FormatDateHeading('$Date',$JournalDateFmt,$JPDateFmt); $time = $date . FormatDateHeading('$Time',$JournalTimeFmt,$JPTimeFmt); $entry = $time.$JPItemStartFmt.stripmagic($req['text']).$JPItemEndFmt; $text = (strstr($pagetext, $date)) ? str_replace($date, $entry, $pagetext) : "$entry\n>><<\n\n" . $pagetext; return $text; } ## Diary entry function HandleDiaryPost($pagename, $req, $pagetext) { global $JournalDateFmt,$DPDateFmt,$DPItemStartFmt,$DPItemEndFmt,$DPItemFmt; SDV($DPDateFmt,">>diaryhead<<\n!!!!\$Date "); SDV($DPItemStartFmt,"\n>>diaryitem<<\n"); SDV($DPItemEndFmt,""); $date = FormatDateHeading('$Date',$JournalDateFmt,$DPDateFmt); $entry = $date.$DPItemStartFmt.stripmagic($req['text']).$DPItemEndFmt; $text = (strstr($pagetext, $date)) ? str_replace($date, $entry, $pagetext) : "$entry\n>><<\n\n" . $pagetext; return $text; } ## Comment entry function HandleMessagePost($pagename, $req, $pagetext) { global $commentBoxHtml,$commentLevel,$JournalDateFmt, $JournalTimeFmt, $MPDateFmt, $MPTimeFmt, $MPAuthorLink, $MPItemFmt, $MPItemStartFmt, $MPItemEndFmt, $MPDateTimeFmt, $MPAnchorFmt, $MPAnchorChronoFmt, $CommentboxMessageFmt, $MultipleItemsPerDay, $Author, $PageUrl, $PostsPerPage, $EnablePostAuthorRequired, $EnableWebsiteField, $EnablePageBreaks; // get ID of parent Post $parentID = $req['parentID']; if ($EnableWebsiteField==1) { $website = $req['website']; $weblink = '— [-[[(http://)'.$website.']]-]'; if($req['website']=='') $weblink = ''; } else $weblink = ''; $id = StringCount($pagename,">>messagehead<<")+1; if ($EnablePageBreaks==1) { $r = fmod($id-1,$PostsPerPage); if($r==0 && $id>1) SDV($MPItemEndFmt, "\n>><<\n\n(:comment breakpage:)"); else SDV($MPItemEndFmt, "\n>><<"); } else SDV($MPItemEndFmt,"\n>><<"); SDV($MPDateFmt,'>>messagedate<<(:nl:)!!!!$Date'); SDV($MPTimeFmt,"(:nl:)>>messagehead<<\n!!!!!\$Author — [-at \$Time-] $weblink \n"); SDV($MPItemStartFmt,">>messageitem<<\n"); SDV($MPDateTimeFmt,"(:nl:)>>messagehead<<\n!!!!!\$Author — [-\$Date, \$Time-] $weblink \n"); SDV($MultipleItemsPerDay,0); # set to 1 to have date above for multiple entries per day SDV($MPAuthorLink, 1); # set to 0 to disable author name as link SDV($MPAnchorFmt,"(:commentbox:)"); SDV($MPAnchorChronoFmt,"(:commentboxchrono:)"); $name = $req['author']; if ($req['author']=='') $req['author'] = 'anonymous'; # disable anonymous posts, but this looses also any message content: # if($EnablePostAuthorRequired == 1 && $name=='') Redirect($pagename); if($name=='') $name = 'anonymous'; else $name = ($MPAuthorLink==1) ? '[[~' . $name . ']]' : $name; if ($MultipleItemsPerDay) { $date = FormatDateHeading('$Date',$JournalDateFmt,$MPDateFmt); $entry = '[[#comment'.$id.']]'; $entry .= '[[#parent'.$parentID.']]'; $entry .= str_replace('$Author',$name, FormatDateHeading('$Time',$JournalTimeFmt,$MPTimeFmt)); } else { $date = ''; $entry = '[[#comment'.$id.']]'; $entry .= '[[#parent'.$parentID.']]'; $entry .= FormatDateHeading('$Date',$JournalDateFmt, str_replace('$Author',$name, FormatDateHeading('$Time',$JournalTimeFmt,$MPDateTimeFmt))); } $entry.= $MPItemStartFmt.stripmagic($req['text']); // insert markup for Form for commenting a comment $commentLevel = $req['commentlevel'] + 1; $entry .= "\n(:comment4comment $commentLevel $id:)"; $entry .= $MPItemEndFmt; $order= $req['order']; if ($order=='') { # order is not chrono, latest top if (strstr($pagetext,$MPAnchorFmt)) { $pos = strpos($pagetext,$MPAnchorFmt); $len = strlen($MPAnchorFmt); $before = substr($pagetext,0,$pos+$len)."\n"; $after = substr($pagetext,$pos+$len); } else { $before = ''; $after = $pagetext; } $entry = "$date$entry"; $after = ($MultipleItemsPerDay && strstr($after, $date)) ? str_replace($date, $entry, $after) : "$entry$after"; } else { # order is chrono, latest last $entry = "\n" . $entry; if (strstr($pagetext,$MPAnchorChronoFmt)) { $pos = strpos($pagetext,$MPAnchorChronoFmt); // new comment if ($parentID == 0) { $before = substr($pagetext,0,$pos); $after = substr($pagetext,$pos); } // comment on comment else { // start of comments $commentStartPosition = strpos($pagetext,'[[#comment'); // beginning up to comments $beforeComments = substr($pagetext,0,$commentStartPosition); // beginning up to "add new comment" $beginningToNewComment = substr($pagetext,0,$pos); // comments up to "add new comment" $comments = substr($beginningToNewComment,$commentStartPosition); //print_r("


"); $commentArray = markup2commentArray($comments); //print_r("

".'-- MAIN -- $commentArray: ');print_r($commentArray); // form for adding a (new) comment $addNewComment = substr($pagetext,$pos); // identify insertion point $insertAfterThisIndex = getIndex4commentInsertion($commentArray,$parentID); //print_r("

".'-- MAIN -- insertAfterThisIndex: ');print_r($insertAfterThisIndex); $before = $beforeComments . commentArray2markup(array_slice($commentArray,0,$insertAfterThisIndex + 1)); $after = commentArray2markup(array_slice($commentArray,$insertAfterThisIndex + 1)) . $addNewComment; //print_r("

".'-- MAIN -- $before: ');print_r($before); //print_r("

".'-- MAIN -- $after: ');print_r($after); } } else { $before = $pagetext; if ($before[strlen($before)-1]!='\n') $before .="\n"; $after = ''; } $before .= ($MultipleItemsPerDay && strstr($before, $date)) ? substr($entry,1) : "$date$entry"; } return "$before\n$after"; } /* Find the index after which the comment is to be inserted * * @param array $commentArray The comments * @param int $commentID The ID of the parent comment * * @return int The index */ function getIndex4commentInsertion($commentArray,$commentID) { //print_r("

".' -- RECURSION - Method called -- '."getIndex4commentInsertion(commentArray,$commentID)"); $siblingIdentifier = '[[#parent' . $commentID . ']]'; $commentIndex = getIndexFromCommentArray($commentArray,$siblingIdentifier,TRUE); //print_r("

-- RECURSION -- getIndexFromCommentArray(commentArray,$siblingIdentifier): ");print_r($commentIndex); // comment with parentID has no children if ($commentIndex < 0) { $commentIdentifier = '[[#comment' . $commentID . ']]'; $insertAfterThisIndex = getIndexFromCommentArray($commentArray,$commentIdentifier); //print_r("

".' -- RECURSION - IF (... < 0) -- insertAfterThisIndex: ');print_r($insertAfterThisIndex); } // comment with parentID already has children comments else { //print_r("

". '-------------------- parent comment already has children comments'); $insertAfterThisIndex = getIndexFromCommentArray($commentArray,$siblingIdentifier,TRUE); //print_r("

".' -- RECURSION - ELSE -- insertAfterThisIndex: ');print_r($insertAfterThisIndex); // get ID of the comment we identified as insertion point $checkThisID = getIDfromString($commentArray[$insertAfterThisIndex]); //print_r("

".' -- RECURSION - ELSE -- $checkThisID: ');print_r($checkThisID); // check recursive whether the comment we identified as insertion point has children $insertAfterThisIndex = getIndex4commentInsertion($commentArray,$checkThisID); } return $insertAfterThisIndex; } /* Extract the ID from a comment (an entry in the commentArray) * * @param string $commentThe comment * * @return int The ID */ function getIDfromString($comment) { $beginning = str_replace(substr($comment, strpos($comment, ']][[#parent')),'',$comment); $IDstring = substr($beginning,strpos($beginning, '[[#comment')); $ID = str_replace(substr($IDstring,strpos($IDstring, '[[#comment'),10),'',$IDstring); return $ID; } /* Builds the commentArray form markup * * @param string $markup The markup to build the commentArray from * * @return array The commentArray */ function markup2commentArray($markup) { $delimiter = '[[#comment'; $commentArray = explode($delimiter,$markup); array_shift($commentArray); foreach ($commentArray as &$comment) { $comment = $delimiter . $comment; } return $commentArray; } /* Builds markup from commentArray * * @param array $commentArray The comments to build * * @return string The markup */ function commentArray2markup($commentArray) { $returnString = implode("",$commentArray); return $returnString; } /* get index from commentArray by search string * * @param array $commentArray All comments on the page * @param string $searchString The identifier for the requested entry * @param boolean $getLast Get the last match * * @return int The requested index: * "-1" if no match * "-2" if more than 1 match and $getLast == FALSE * index if more than 1 match and $getLast == TRUE */ function getIndexFromCommentArray($commentArray,$searchString,$getLast = FALSE) { $index = -1; foreach ($commentArray as $key => $value) { if (stristr($value,$searchString)) { // first match if (($index == -1) || ($getLast == TRUE)) { $index = $key; } // multiple matches and $getLast == FALSE else { $index = -2; } } } return $index; } # add page variable {$PostCount}, # counts message items per page $FmtPV['$PostCount'] = 'StringCount($pn,">>messagehead<<")'; function StringCount($pagename,$find) { $page = ReadPage($pagename, READPAGE_CURRENT); $n = substr_count($page['text'], $find); if ($n==0) return ''; #suppressing 0 return $n; } ## get arguments from POST or GET function CBRequestArgs ($req = NULL) { if (is_null($req)) $req = array_merge($_GET, $_POST); foreach ($req as $key=>$val) { if(is_array($val)) foreach($value as $k=>$v) $req[$key][$k] = htmlspecialchars(stripmagic($v),ENT_NOQUOTES); else $req[$key] = htmlspecialchars(stripmagic($val),ENT_NOQUOTES); } return $req; } ## display message function CBMessage($msg) { global $MessagesFmt; $MessagesFmt[] = "
$[$msg]
"; } //}}} //EOF