[Evocms-plugins-commits] SF.net SVN: evocms-plugins: [287] starrating_plugin/trunk
Brought to you by:
blueyed
From: <per...@us...> - 2007-03-31 16:22:50
|
Revision: 287 http://svn.sourceforge.net/evocms-plugins/?rev=287&view=rev Author: personman2 Date: 2007-03-31 09:22:49 -0700 (Sat, 31 Mar 2007) Log Message: ----------- Importing files Added Paths: ----------- starrating_plugin/trunk/README.html starrating_plugin/trunk/_starrating.plugin.php starrating_plugin/trunk/infoicon.gif starrating_plugin/trunk/infoiconeee.gif starrating_plugin/trunk/js.js starrating_plugin/trunk/scriptaculous/ starrating_plugin/trunk/scriptaculous/effects.js starrating_plugin/trunk/scriptaculous/prototype.js starrating_plugin/trunk/scriptaculous/scriptaculous.js starrating_plugin/trunk/star_rating.gif starrating_plugin/trunk/star_rating.png starrating_plugin/trunk/star_ratingeee.gif starrating_plugin/trunk/stars.css Added: starrating_plugin/trunk/README.html =================================================================== --- starrating_plugin/trunk/README.html (rev 0) +++ starrating_plugin/trunk/README.html 2007-03-31 16:22:49 UTC (rev 287) @@ -0,0 +1,90 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> + +<head> +<title>Star Rating plugin help</title> +</head> + +<body> + +<h1>Star Rating plugin</h1> + +<p id="starrating_plugin_short_desc"> +Add a star rating to your blog posts. +</p> + +<h2 id="starrating_plugin_long_desc">Detailed Description</h2> +<p> +This plugin allows your visitors to rate your posts using star ratings. By default they can rate the posts out of five stars, but it's easy to change that value in the backoffice plugin settings. Users with JavaScript enabled can vote without reloading the page using an AJAX call. The plugin works when JavaScript is disabled by the reader, too. By default, each vote is checked against a list of IP addresses to make sure that it's not a duplicate, but this can be disabled in the backoffice. +</p> + + +<h2 id="starrating_plugin_installation">Installation</h3> +<ol> + <li>Copy the <span class="filename">starrating_plugin</span> folder into the "plugins" folder of your b2evolution installation.</li> + <li>Login to the administrative interface for your blog.</li> + <li>Install the Star Rating plugin from the Settings::Plug-ins::Available plugins table using the [Install] link.</li> + <li>There are three bits of code to place in the _main.php file for any skin where you want the star ratings to be used. + <ol style="list-style-type:lower-alpha"> + <li>Put this one in the post loop inside the bSmallPrint div or just below the post title: + <blockquote><code> + <?php $Plugins->call_by_code( 'starrating', array('id' => $Item->ID ) ); ?> + </code></blockquote> + </li> + <li>If you use pop-up notices, which are enabled by default, you need to add this to your skin, just after the opening body tag: + <blockquote><code> + <?php $Plugins->call_by_code( 'starrating', array('display' => 'notice' ) ); ?> + </code></blockquote> + + </li> + <li>(Optional) If you want to show the top rated posts in the sidebar, add this code to the sidebar: + <blockquote><code> + <?php $Plugins->call_by_code( 'starrating', array('display' => 'toprated', 'limit' => 5, 'minvote' => 2 ) ); ?> +</code></blockquote> + By default, it shows links to the top five posts, but you can change the 'limit' param to get different results. You can also edit the minvote setting so that a certain number of votes are required before an item can make it into the top rated list. + </li> + </ol> + </li> + +</ol> + + +<h2 id="starrating_plugin_settings">Plugin Settings</h2> + +<p id="starrating_plugin_outof"> +<strong>Out of</strong>: +Choose the number of stars possible. The default is five. It's best to only chenge this value right after installing the plugin. If there are already votes cast using another max value, then your results will be skewed if you change this value. Uninstall the plugin, then reinstall it to clear any old votes, then change the value.</p> + +<p> +<strong>Check IP</strong>: +By default, each vote is checked against a list of IP addresses to make sure it's not a duplicate. You can disable the check using this setting. +</p> + +<strong>Pop-up info</strong>: +This option, which is enabled by default, displays details about a rating and notices (after you vote) in a javascript popup that fades in and then back out after 4 seconds. If you use this feature, be sure to place the additional skin tag (notice) just after your opening body tag (see above). This option requires a little more work to set up and requires that the user have javascript enabled, but it is more attractive and does not disrupt your site layout when someone votes. +</p> + +<strong>Inline info</strong>: +If you check this box, details about a rating and notices (after a vote) are placed just below the stars. This does not require the notice skin tag or javascript, but it may disrupt your site layout when someone votes. It is possible to use both of the info options at the same time, but it could be considered a bit redundant. +</p> + +<p> +<strong>Apply rendering</strong>: +This plugin doesn't really use a renderer, but it uses the renderer checkbox setting to know which posts should have the star rating available. Edit this plugin setting to set whether the checkbox is checked by default. For example, if you only want a few of your posts to have the rating system, then set 'Apply rendering' to 'opt-in'. Then, posts won't have the stars unless you check the box when you're writing a post. If you want all or almost all of the posts to have the rating system, then set the 'Apply rendering' in the plugin settings to 'opt-out'. Then, all posts will have the stars unless you uncheck the box in the write tab. +</p> + +<h2 id="starrating_plugin_usage">Usage</h2> +<p>Once you have the plugin installed and the settings the way you want them, then go the write tab and create a post. If you want the post to have the rating system, then make sure that there's a check in the box next to 'Star Rating' in the 'Text renderers' section in the lower right.</p> + +<p>Now the stars should appear next to your post. To vote, click on the star you're voting for. If JavaScript is enabled, it will say 'Loading . . .', then display the new rating and thank you for your vote. If JavaScript is disabled, then the page will reload and the new rating will be shown.</p> + +<h2>Customization</h2> +<p> +<strong>Change star image</strong>: It's not hard to change the star image. First, download the default image and look at it. It's three stars stacked on top of each other. The top star is the empty version, the middle star is the hover version, and the bottom star is the normal one that shows the average rating. Create your new image to match this template, then upload it to the /starrating_plugin/ folder. Then, edit the stars.css file to match your new file name. If your image has a width that's different than 20px, then you'll need to edit the two lines toward the top of stars.css that set the width. Then edit _starrating.plugin.php and find "var $width = 20;" and edit the value to match your image's width. +</p> + + +<h2>Credits</h2> +<p>This plugin was made for b2evoltution by <a href="http://www.brendoman.com/dbc">Danny Ferguson</a> and it is based on <a href="http://www.masuga.com/thelab/ajaxrate/">Ajax Rating</a> by Ryan Masuga.</p> +</body> +</html> Added: starrating_plugin/trunk/_starrating.plugin.php =================================================================== --- starrating_plugin/trunk/_starrating.plugin.php (rev 0) +++ starrating_plugin/trunk/_starrating.plugin.php 2007-03-31 16:22:49 UTC (rev 287) @@ -0,0 +1,363 @@ +<?php +/** + * This file implements the Star Rating plugin for + * {@link http://b2evolution.net b2evolution}. + * + */ +if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); + +/** + */ +class starrating_plugin extends Plugin +{ + var $version = '0.5-dev'; + var $priority = 50; + var $code = 'starrating'; + var $author = 'Danny Ferguson'; + var $help_url = ''; + var $width = 20; // Width of individual star in px. + var $apply_rendering = 'opt-in'; + + /** + * Set name and desc. + */ + function starrating_plugin() + { + $this->name = T_('Star Rating'); + $this->short_desc = T_('AJAX-powered star ratings for posts.'); + } + + + function GetDefaultSettings() + { + return array( + 'outof' => array( + 'label' => T_( 'Out of' ), + 'defaultvalue' => 5, + 'note' => T_('How many stars are possible?'), + 'type' => 'integer', + 'size' => '2' + ), + 'checkip' => array( + 'label' => T_( 'Check IP' ), + 'defaultvalue' => 1, + 'note' => T_( 'Check IP to prevent multiple votes on one post from one person.'), + 'type' => 'checkbox' + ), + 'popup' => array( + 'label' => T_( 'Pop-up info' ), + 'defaultvalue' => 1, + 'note' => T_( 'Show info and notices in pop-ups that fade in and out. Requires javascript, but does not disrupt layout. This option requires an additional skin tag, see the Readme file.'), + 'type' => 'checkbox' + ), + 'inline' => array( + 'label' => T_( 'Inline info' ), + 'defaultvalue' => 0, + 'note' => T_( 'Show info and notices just below the stars. Works with or without javascript enabled, but may disrupt layout.'), + 'type' => 'checkbox' + ) + ); + } + + + /** + * Create the table to store the rating votes + * + * @return array + */ + function GetDbLayout() + { + return array( + "CREATE TABLE ".$this->get_sql_table('ratings')." ( + + `id` varchar(11) NOT NULL, + `total_votes` int(11) NOT NULL default '0', + `total_value` int(11) NOT NULL default '0', + `used_ips` longtext, + `blog_id` int(11) NOT NULL default '0', + PRIMARY KEY (`id`) + );", + ); + } + + + function RenderItemAsHtml( & $params ) + { + // This is not actually a renderer, + // we're just using the checkbox + // to see if we should display for + // the given post. + } + + function SkinBeginHtmlHead( & $params ) + { + global $plugins_url; + + $outof = $this->Settings->get('outof'); + + // Display the head code: + + echo '<script type="text/javascript" src="'.$plugins_url.'starrating_plugin/js.js"></script>'."\n". + '<script type="text/javascript" src="'.$plugins_url.'starrating_plugin/scriptaculous/prototype.js"></script>'."\n". + '<script type="text/javascript" src="'.$plugins_url.'starrating_plugin/scriptaculous/scriptaculous.js?load=effects"></script>'."\n". + '<link rel="stylesheet" href="'.$plugins_url.'starrating_plugin/stars.css" type="text/css" />'."\n"; + ?> + <style type="text/css"> + .unit-rating {width: <?php echo $outof * $this->width ?>px;} + <?php + for ($ncount = 1; $ncount <= $outof; $ncount++) { ?>.unit-rating a.r<?php echo $ncount ?>-unit {left: <?php echo ($ncount - 1) * $this->width ?>px; } .unit-rating a.r<?php echo $ncount ?>-unit:hover {width: <?php echo $ncount * $this->width ?>px; } +<?php } ?> + </style> + <?php + + return true; + } + + + function SkinTag( $params ) + { + global $plugins_url, $DB, $Item, $Plugins, $blog, $Blog; + $outof = $this->Settings->get('outof'); + if(!isset($params['display'])) $params['display'] = 'stars'; + + if ($params['display'] == 'notice') { + echo '<div id="ratingResults" style="display:none"></div>'; + } elseif ($params['display'] == 'toprated') + { + + // Display the Top Rated block in the sidebar: + + /** + * Default params: + */ + // This is what will enclose the block in the skin: + if(!isset($params['block_start'])) $params['block_start'] = '<div class="bSideItem">'; + if(!isset($params['block_end'])) $params['block_end'] = "</div>\n"; + + // Title: + if(!isset($params['title'])) $params['title'] = '<h3>Top Rated</h3>'; + // This is what will enclose the category list: + if(!isset($params['list_start'])) $params['list_start'] = '<ol>'; + if(!isset($params['list_end'])) $params['list_end'] = "</ol>\n"; + + // This is what will separate the category links: + if(!isset($params['line_start'])) $params['line_start'] = '<li>'; + if(!isset($params['line_end'])) $params['line_end'] = "</li>\n"; + + // What comes before and after the comment count: + if(!isset($params['before_rating'])) $params['before_rating'] = ' ('; + if(!isset($params['after_rating'])) $params['after_rating'] = ')'; + + // Limit: How many of the top posts to show + if(!isset($params['limit'])) $params['limit'] = 5; + + // Minimum number of votes required to be in the list + if(!isset($params['minvote'])) $params['minvote'] = 1; + + // START DISPLAY: + echo $params['block_start']; + echo $params['title']; + + // Stuff goes here + $sql = "SELECT DISTINCT post_ID , post_urltitle , + total_value / total_votes AS rating, total_votes + FROM ( T_posts , ".$this->get_sql_table('ratings').") + INNER JOIN T_postcats ON post_ID = postcat_post_ID + INNER JOIN T_categories ON postcat_cat_ID = cat_ID + WHERE cat_blog_id = ".$blog." + AND ".$this->get_sql_table('ratings').".id = T_posts.post_ID + AND total_votes >= ".$params['minvote']." + ORDER BY `rating` DESC + LIMIT ".$params['limit']; + $results = $DB->get_results($sql); + echo $params['list_start']; + for ($i = 0; $i < $params['limit']; $i++) { + // Stop the loop if you get to a post with 0 comments + if (empty( $results[$i]->rating ) ) break; + // Create a new 1 post itemlist for each result (for access to permalinks) + $list = new ItemList($blog, array(), '', '', -1, '', array(), + '', 'DESC', '', 1, '', '', '' ,'', '', '', '', '', '', 'now', + $results[$i]->post_urltitle); + while ($rated_item = $list->get_item()) { + echo $params['line_start']; + echo "<a href=\"", $rated_item->permanent_url(); + echo "\">", $rated_item->title('','',false), "</a> "; + } + echo $params['before_rating'].number_format($results[$i]->rating, 1).$params['after_rating']." <span class='notes'>".$results[$i]->total_votes." votes</span>"; + echo $params['line_end']; + } + echo $params['list_end']; + + + + + echo $params['block_end']; + + + } else { + + // Display the rating code for an Item: + + // Check to see if we want a rating for this post + $renders = $Plugins->validate_list( $Item->get_renderers() ); + // If the renderer checkbox is unchecked, then display nothing + if (!in_array($this->code, $renders)) return false; + + $ip = $_SERVER['REMOTE_ADDR']; + + $r = $DB->get_row( 'SELECT total_votes, total_value, used_ips FROM '.$this->get_sql_table('ratings').' WHERE id="'.$params['id'].'"'); + if (isset($r)) $tense = ($r->total_votes == 1) ? "vote" : "votes"; + ?> + <div id="unit_long<?php echo $Item->ID ?>"> + + <ul class="unit-rating"> + <li class='current-rating' style="width:<?php echo @number_format($r->total_value / $r->total_votes , 2 ) * $this->width; ?>px;">Currently <?php echo @number_format($r->total_value / $r->total_votes , 2 ); ?>/<?php echo $outof ?></li> + <?php + for ($ncount = 1; $ncount <= $outof; $ncount++) { ?> + <?php + // AJAX url: + $hturl = $this->get_htsrv_url('vote', array('vote' => $ncount, 'ip' => $ip, 'id' => $Item->ID, 'blog' => $blog ) ); + // Url for non-JS browsers + $current_url = $Blog->get('url'); + $hturlnojs = $this->get_htsrv_url('vote', array('vote' => $ncount, 'ip' => $ip, 'id' => $Item->ID, 'returnto' => $current_url, 'blog' => $blog ) ); + ?> + + <li><a href="<?php echo $hturlnojs ?>" title="<?php echo $ncount ?> out of <?php echo $outof ?>" class="r<?php echo $ncount ?>-unit" onclick="javascript:sndReq('<?php echo $Item->ID ?>', '<?php echo $hturl ?>');return false"><?php echo $ncount ?></a></li> + <? } + $ncount=0; // resets the count + ?> + <?php + if (!empty($r->total_votes)) { + $avg = @number_format($r->total_value / $r->total_votes, 1); + $total = $r->total_votes; + } else { + $avg = '0.0'; + $total = 0; + } + $tense = ($total == 1) ? "vote" : "votes"; + if ($this->Settings->get('popup')) { + print "<a href='javascript:void(0);' onClick=\"disp_notice('<p class=\'ratingNotes\'>Rating: <strong>$avg</strong> out of $total $tense cast</p>'); return false;\" class='starinfo'><span>i</span></a>"; + } ?> + </ul> + <?php + if ($this->Settings->get('inline')) { ?> + <p class="ratingNotes">Rating: <strong> <?php echo $avg ?></strong> out of <?php echo $total ?> <?php echo $tense ?> cast </p> + <?php } ?> + </div> + <?php + return true; + } + } + + + // Set the plugin up to take AJAX calls + function GetHtsrvMethods() + { + return array( 'vote' ); + } + + function htsrv_vote( & $params ) + { + global $DB; + $outof = $this->Settings->get('outof'); + $ip_num = $params['ip']; + $id_sent = $params['id']; + $vote_sent = $params['vote']; + $blog = $params['blog']; + $tableName = $this->get_sql_table('ratings'); + + $r = $DB->get_row( 'SELECT total_votes, total_value, used_ips FROM '.$this->get_sql_table('ratings').' WHERE id="'.$params['id'].'"'); + $checkIP = (empty( $r->used_ips) ? NULL : unserialize($r->used_ips) ); + $count = (empty( $r->total_votes ) ? NULL : $r->total_votes); + $current_rating = (empty( $r->total_value ) ? 0 : $r->total_value); + $sum = $params['vote'] + $current_rating; + $tense = ($count == 1) ? "vote" : "votes"; + + //check see if this ip has voted before or not + + if ($this->Settings->get('checkip')) { + $voted = $DB->get_var("SELECT count(*) FROM $tableName WHERE used_ips LIKE '%".$ip_num."%' AND id='$id_sent' "); + } + // the above pattern match ip:suggested by Bramus! //http://www.bram.us/ + + if(!empty($voted)){ + $new_back = + "<ul class=\"unit-rating\">\n". + "<li class=\"current-rating\" style=\"width:". @number_format($current_rating/$count,2) * $this->width ."px;\">Current rating.</li>\n"; + for ($ncount = 1; $ncount <= $outof; $ncount++) { + $new_back .= "<li class=\"r{$ncount}-unit\">{$ncount}</li>\n"; + } + + if ($this->Settings->get('popup')) { + $new_back .= "<a href='javascript:void(0);' onClick=\"disp_notice('<p class=\'ratingNotes\'>Rating: <strong> ".@number_format($r->total_value / $r->total_votes, 1)."</strong> out of $r->total_votes $tense cast</p>'); return false;\" class='starinfo'><span>i</span></a>"; + } + $new_back .= "</ul>"; + $notice = "<p class=\"ratingNotes\">Rating: <strong>".@number_format($current_rating/$count,1)."</strong> out of ".$count." ".$tense." cast". + "<br />\n <span class='error'>You have previously voted!</span></p>";//show the current value of the vote with the current numbers + + //if not, echo the new changes + }else{ + + if($sum==0){ + $added=0;//checking to see if the first vote has been tallied + }else{ + $added=$count+1;//increment the current number of votes + } + + if(is_array($checkIP)){ + array_push($checkIP,$ip_num);//if it is an array i.e. already has entries the push in another value + }else{ + $checkIP=array($ip_num);//for the first entry + } + + $insert=serialize($checkIP); + + // see if the ID already exists + $idexists = $DB->get_var("SELECT count(*) FROM $tableName WHERE id=$id_sent "); + + if($idexists==true) { + $DB->query("UPDATE $tableName SET total_votes='".$added."', total_value='".$sum."', used_ips='".$insert."', blog_id='".$blog."' WHERE id='$id_sent'"); + } else { + $DB->query("INSERT INTO $tableName VALUES ('$id_sent', '".$added."','".$sum."', '".$insert."', '$blog')"); + } + + //update the database and echo back the new stuff + + $r = $DB->get_row("SELECT total_votes, total_value, used_ips FROM $tableName WHERE id='$id_sent' ")or die(" Error: ".mysql_error()); + $count = $r->total_votes; //how many votes total + $current_rating = $r->total_value;//total number of rating added together and stored + + + $new_back = + "<ul class=\"unit-rating\">\n". + "<li class=\"current-rating\" style=\"width:". @number_format($current_rating/$count,2) * $this->width ."px;\">Current rating.</li>\n"; + for ($ncount = 1; $ncount <= $outof; $ncount++) { + $new_back .= "<li class=\"r{$ncount}-unit\">{$ncount}</li>\n"; + } + if ($this->Settings->get('popup')) { + $new_back .= "<a href='javascript:void(0);' onClick=\"disp_notice('<p class=\'ratingNotes\'>Rating: <strong> ".@number_format($r->total_value / $r->total_votes, 1)."</strong> out of $r->total_votes $tense cast</p>'); return false;\" class='starinfo'><span>i</span></a>"; + } + $new_back .= "</ul>"; + $tense = ($count == 1) ? "vote" : "votes"; + $notice = "<p class=\"ratingNotes\">Rating: <strong>".@number_format($sum/$added,1)."</strong> out of ".$added." ".$tense." cast". + "<br /><span class='success'>Thank you for your vote!</span></p></div>";//show the updated value of the vote + + + } + // If JavaScript is off, then just send them back to the referer + if (isset($params['returnto'])) + { + header("location: ".$params['returnto']); + } else { + //name of the div id to be updated | the html that needs to be changed + //$output = "unit_long$id_sent|$new_back"; + $output = "unit_long$id_sent|$new_back"; + if ($this->Settings->get('inline')) $output .= "$notice"; + if ($this->Settings->get('popup')) $output .= "|ratingResults|$notice"; + echo $output; + } + } +} + + +?> Added: starrating_plugin/trunk/infoicon.gif =================================================================== (Binary files differ) Property changes on: starrating_plugin/trunk/infoicon.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: starrating_plugin/trunk/infoiconeee.gif =================================================================== (Binary files differ) Property changes on: starrating_plugin/trunk/infoiconeee.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: starrating_plugin/trunk/js.js =================================================================== --- starrating_plugin/trunk/js.js (rev 0) +++ starrating_plugin/trunk/js.js 2007-03-31 16:22:49 UTC (rev 287) @@ -0,0 +1,117 @@ +var xmlhttp +/*@cc_on @*/ +/*@if (@_jscript_version >= 5) + try { + xmlhttp=new ActiveXObject("Msxml2.XMLHTTP") + } catch (e) { + try { + xmlhttp=new ActiveXObject("Microsoft.XMLHTTP") + } catch (E) { + xmlhttp=false + } + } +@else + xmlhttp=false +@end @*/ +if (!xmlhttp && typeof XMLHttpRequest!='undefined') { + try { + xmlhttp = new XMLHttpRequest(); + } catch (e) { + xmlhttp=false + } +} +function myXMLHttpRequest() { + var xmlhttplocal; + try { + xmlhttplocal= new ActiveXObject("Msxml2.XMLHTTP") + } catch (e) { + try { + xmlhttplocal= new ActiveXObject("Microsoft.XMLHTTP") + } catch (E) { + xmlhttplocal=false; + } + } + +if (!xmlhttplocal && typeof XMLHttpRequest!='undefined') { + try { + var xmlhttplocal = new XMLHttpRequest(); + } catch (e) { + var xmlhttplocal=false; + alert('couldn\'t create xmlhttp object'); + } +} +return(xmlhttplocal); +} + + +function sndReq(id_num, hturl) { + + var element = document.getElementById('unit_long'+id_num); + //new Effect.Fade(element); + element.innerHTML = '<div style="height: 20px;"><em>Loading ...</em></div>'; + + xmlhttp.open('get', hturl); + xmlhttp.onreadystatechange = handleResponse; + xmlhttp.send(null); + +} + +function handleResponse() { + if(xmlhttp.readyState == 4){ + //if (xmlhttp.status == 200){ + if (1){ + var response = xmlhttp.responseText; + var update = new Array(); + //alert (response) + if(response.indexOf('|') != -1) { + update = response.split('|'); + changeText(update[0], update[1]); + if (update[2]) disp_notice(update[3]); + new Effect.Highlight(update[0], {startcolor: '#ff9900', endcolor: '#EEEEEE'}); + + } + } + } +} + +function disp_notice(text) +{ + elid = 'ratingResults'; + changeText( elid, text ); + el = document.getElementById(elid); + var theTop = 30; + if (window.innerHeight) + { + pos = window.pageYOffset + } + else if (document.documentElement && document.documentElement.scrollTop) + { + pos = document.documentElement.scrollTop + } + else if (document.body) + { + pos = document.body.scrollTop + } + if (pos < theTop) pos = theTop; + else pos += 30; + el.style.top = pos +'px'; + new Effect.Appear(elid, {from: 0.0, to: 0.8}); + setTimeout('new Effect.Fade("ratingResults")', 4000); +} + +function changeText( div2show, text ) { + // Detect Browser + var IE = (document.all) ? 1 : 0; + var DOM = 0; + if (parseInt(navigator.appVersion) >=5) {DOM=1}; + + // Grab the content from the requested "div" and show it in the "container" + + if (DOM) { + var viewer = document.getElementById(div2show) + viewer.innerHTML=text + } + else if(IE) { + document.all[div2show].innerHTML=text + } +} Added: starrating_plugin/trunk/scriptaculous/effects.js =================================================================== --- starrating_plugin/trunk/scriptaculous/effects.js (rev 0) +++ starrating_plugin/trunk/scriptaculous/effects.js 2007-03-31 16:22:49 UTC (rev 287) @@ -0,0 +1,977 @@ +// script.aculo.us effects.js v1.6.4, Wed Sep 06 11:30:58 CEST 2006 + +// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// See scriptaculous.js for full license. + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if(this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if(this.slice(0,1) == '#') { + if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if(this.length==7) color = this.toLowerCase(); + } + } + return(color.length==7 ? color : (arguments[0] || this)); +} + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +} + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +} + +Element.setContentZoom = function(element, percent) { + element = $(element); + Element.setStyle(element, {fontSize: (percent/100) + 'em'}); + if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); +} + +Element.getOpacity = function(element){ + var opacity; + if (opacity = Element.getStyle(element, 'opacity')) + return parseFloat(opacity); + if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(opacity[1]) return parseFloat(opacity[1]) / 100; + return 1.0; +} + +Element.setOpacity = function(element, value){ + element= $(element); + if (value == 1){ + Element.setStyle(element, { opacity: + (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? + 0.999999 : 1.0 }); + if(/MSIE/.test(navigator.userAgent) && !window.opera) + Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); + } else { + if(value < 0.00001) value = 0; + Element.setStyle(element, {opacity: value}); + if(/MSIE/.test(navigator.userAgent) && !window.opera) + Element.setStyle(element, + { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')' }); + } +} + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +} + +Element.childrenWithClassName = function(element, className, findFirst) { + var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); + var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { + return (c.className && c.className.match(classNameRegExp)); + }); + if(!results) results = []; + return results; +} + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +Array.prototype.call = function() { + var args = arguments; + this.each(function(f){ f.apply(this, args) }); +} + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + tagifyText: function(element) { + if(typeof Builder == 'undefined') + throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); + + var tagifyStyle = 'position:relative'; + if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1'; + element = $(element); + $A(element.childNodes).each( function(child) { + if(child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + Builder.node('span',{style: tagifyStyle}, + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if(((typeof element == 'object') || + (typeof element == 'function')) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || {}); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || {}); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +var Effect2 = Effect; // deprecated + +/* ------------- transitions ------------- */ + +Effect.Transitions = {} + +Effect.Transitions.linear = Prototype.K; + +Effect.Transitions.sinoidal = function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; +} +Effect.Transitions.reverse = function(pos) { + return 1-pos; +} +Effect.Transitions.flicker = function(pos) { + return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; +} +Effect.Transitions.wobble = function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; +} +Effect.Transitions.pulse = function(pos) { + return (Math.floor(pos*10) % 2 == 0 ? + (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10))); +} +Effect.Transitions.none = function(pos) { + return 0; +} +Effect.Transitions.full = function(pos) { + return 1; +} + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(); +Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = (typeof effect.options.queue == 'string') ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if(!this.interval) + this.interval = setInterval(this.loop.bind(this), 40); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if(this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + this.effects.invoke('loop', timePos); + } +}); + +Effect.Queues = { + instances: $H(), + get: function(queueName) { + if(typeof queueName != 'string') return queueName; + + if(!this.instances[queueName]) + this.instances[queueName] = new Effect.ScopedQueue(); + + return this.instances[queueName]; + } +} +Effect.Queue = Effect.Queues.get('global'); + +Effect.DefaultOptions = { + transition: Effect.Transitions.sinoidal, + duration: 1.0, // seconds + fps: 25.0, // max. 25fps due to Effect.Queue implementation + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' +} + +Effect.Base = function() {}; +Effect.Base.prototype = { + position: null, + start: function(options) { + this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); + this.currentFrame = 0; + this.state = 'idle'; + this.startOn = this.options.delay*1000; + this.finishOn = this.startOn + (this.options.duration*1000); + this.event('beforeStart'); + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).add(this); + }, + loop: function(timePos) { + if(timePos >= this.startOn) { + if(timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if(this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); + var frame = Math.round(pos * this.options.fps * this.options.duration); + if(frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + render: function(pos) { + if(this.state == 'idle') { + this.state = 'running'; + this.event('beforeSetup'); + if(this.setup) this.setup(); + this.event('afterSetup'); + } + if(this.state == 'running') { + if(this.options.transition) pos = this.options.transition(pos); + pos *= (this.options.to-this.options.from); + pos += this.options.from; + this.position = pos; + this.event('beforeUpdate'); + if(this.update) this.update(pos); + this.event('afterUpdate'); + } + }, + cancel: function() { + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if(this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>'; + } +} + +Effect.Parallel = Class.create(); +Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if(effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Opacity = Class.create(); +Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || {}); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(); +Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Bug in Opera: Opera returns the "real" position of a static element or + // relative element that does not have top/left explicitly set. + // ==> Always set top and left for position relative elements in your stylesheets + // (to 0 if you do not need them) + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if(this.options.mode == 'absolute') { + // absolute movement, so we need to calc deltaX and deltaY + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: Math.round(this.options.x * position + this.originalLeft) + 'px', + top: Math.round(this.options.y * position + this.originalTop) + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); +}; + +Effect.Scale = Class.create(); +Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { + initialize: function(element, percent) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or {} with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || {}); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = {}; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if(fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if(this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if(/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if(!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if(this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = {}; + if(this.options.scaleX) d.width = Math.round(width) + 'px'; + if(this.options.scaleY) d.height = Math.round(height) + 'px'; + if(this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if(this.elementPositioning == 'absolute') { + if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if(this.options.scaleY) d.top = -topd + 'px'; + if(this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(); +Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if(this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { + backgroundImage: this.element.getStyle('background-image') }; + this.element.setStyle({backgroundImage: 'none'}); + if(!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if(!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = Class.create(); +Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + this.start(arguments[1] || {}); + }, + setup: function() { + Position.prepare(); + var offsets = Position.cumulativeOffset(this.element); + if(this.options.offset) offsets[1] += this.options.offset; + var max = window.innerHeight ? + window.height - window.innerHeight : + document.body.scrollHeight - + (document.documentElement.clientHeight ? + document.documentElement.clientHeight : document.body.clientHeight); + this.scrollStart = Position.deltaY; + this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; + }, + update: function(position) { + Position.prepare(); + window.scrollTo(Position.deltaX, + this.scrollStart + (position*this.delta)); + } +}); + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if(effect.options.to!=0) return; + effect.element.hide(); + effect.element.setStyle({opacity: oldOpacity}); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from); + effect.element.show(); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element) + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.setStyle(oldStyle); } + }, arguments[1] || {}) + ); +} + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + } + }, arguments[1] || {}) + ); +} + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || {})); +} + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned(); + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.undoPositioned(); + effect.element.setStyle({opacity: oldOpacity}); + } + }) + } + }, arguments[1] || {})); +} + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); + } + }, arguments[1] || {})); +} + +Effect.Shake = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + effect.element.undoPositioned(); + effect.element.setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +} + +Effect.SlideDown = function(element) { + element = $(element); + element.cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.firstChild.makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); }, + afterUpdateInternal: function(effect) { + effect.element.firstChild.setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + // IE will crash if child is undoPositioned first + if(/MSIE/.test(navigator.userAgent) && !window.opera){ + effect.element.undoPositioned(); + effect.element.firstChild.undoPositioned(); + }else{ + effect.element.firstChild.undoPositioned(); + effect.element.undoPositioned(); + } + effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +Effect.SlideUp = function(element) { + element = $(element); + element.cleanWhitespace(); + var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + restoreAfterFinish: true, + beforeStartInternal: function(effect) { + effect.element.makePositioned(); + effect.element.firstChild.makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping(); + effect.element.show(); }, + afterUpdateInternal: function(effect) { + effect.element.firstChild.setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.firstChild.undoPositioned(); + effect.element.undoPositioned(); + effect.element.setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, + { restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(effect.element); }, + afterFinishInternal: function(effect) { + effect.element.hide(effect.element); + effect.element.undoClipping(effect.element); } + }); +} + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide(); + effect.element.makeClipping(); + effect.element.makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}); + effect.effects[0].element.show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); + } + }, options) + ) + } + }); +} + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned(); + effect.effects[0].element.makeClipping(); }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.undoClipping(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); } + }, options) + ); +} + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || {}; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 3.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +} + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + Element.makeClipping(element); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.setStyle(oldStyle); + } }); + }}, arguments[1] || {})); +}; + +['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', + 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( + function(f) { Element.Methods[f] = Element[f]; } +); + +Element.Methods.visualEffect = function(element, effect, options) { + s = effect.gsub(/_/, '-').camelize(); + effect_class = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[effect_class](element, options); + return $(element); +}; + +Element.addMethods(); \ No newline at end of file Added: starrating_plugin/trunk/scriptaculous/prototype.js =================================================================== --- starrating_plugin/trunk/scriptaculous/prototype.js (rev 0) +++ starrat... [truncated message content] |