[pLog-svn] r2763 - in plog/trunk: class/action/adminclass/controller js js/prototype js/ui locale templates/admintemplates/admin/xml

Mark Wu markplace at gmail.com
Tue Jan 10 10:58:13 GMT 2006


Hi All:

Here comes the first version of LifeType powered by Ajax.=20

I just rewrite/rename the adminxmlsavedraftaction.class.php to
admin/adminsavedraftarticleajaxaction.class.php with prototype Ajax =
library
( http://prototype.conio.net ). And it reduce the complexity of original
plogui.js dramatically.

I also add a new feature addArticleCategoryAjax --
admin/adminaddarticlecategoryajaxaction.class.php. It can allow user to =
add
a new article category when he is writing post, he doesn't need to =
change to
addArticleCategory page. (I learned this idea from wordpress 2.0).

And, I also think this skill can used in dynamic content, it is easier =
than
hacking smarty {dynamic} tags.

Discuss: I think the addArticleCategoryAjax for newpost is enough, do =
you
need it available in editpost?

So, how do you think?

* I already test it IE6, FF1.0.x and FF 1.5. Opera 8.5. I need your help =
to
test it konquer and Safari=20
** The dao or say action in 1.1 still buggy. For example, the post can =
not
delete. And delete the cateogories, the cache have to clear to make the =
data
clean.... I think we need to work hard on this. I will try to fixed it =
if I
could ... :D

Mark

-----Original Message-----
From: plog-svn-bounces at devel.lifetype.net
[mailto:plog-svn-bounces at devel.lifetype.net] On Behalf Of
mark at devel.lifetype.net
Sent: Tuesday, January 10, 2006 6:39 PM
To: plog-svn at devel.lifetype.net
Subject: [pLog-svn] r2763 - in plog/trunk:
class/action/adminclass/controller js js/prototype js/ui locale
templates/admintemplates/admin/xml

Author: mark
Date: 2006-01-10 10:38:38 +0000 (Tue, 10 Jan 2006)
New Revision: 2763

Added:
   =
plog/trunk/class/action/admin/adminaddarticlecategoryajaxaction.class.php=

   =
plog/trunk/class/action/admin/adminsavedraftarticleajaxaction.class.php
   plog/trunk/js/prototype/
   plog/trunk/js/prototype/prototype.js
Removed:
   plog/trunk/class/action/admin/adminxmlsavedraftaction.class.php
Modified:
   plog/trunk/class/controller/admincontrollermap.properties.php
   plog/trunk/js/ui/plogui.js
   plog/trunk/locale/locale_en_UK.php
   plog/trunk/locale/locale_zh_TW.php
   plog/trunk/templates/admin/header.template
   plog/trunk/templates/admin/newpost.template
   plog/trunk/templates/admin/xml/response.template
Log:
LifeType, powerd by Ajax now.

I just rewrite/rename the adminxmlsavedraftaction.class.php to
admin/adminsavedraftarticleajaxaction.class.php with prototype Ajax =
library
( http://prototype.conio.net ). And it reduce the complexity of original
plogui.js dramatically.

I also add a new feature addArticleCategoryAjax --
admin/adminaddarticlecategoryajaxaction.class.php. It can allow user to =
add
a new article category when he is writing post, he doesn't need to =
change to
addArticleCategory page. (I learned this idea from wordpress 2.0).

And, I also think this skill can used in dynamic content, it is easier =
than
hacking smarty {dynamic} tags.

Discuss: I think the addArticleCategoryAjax for newpost is enough, do =
you
need it available in editpost?



Added:
plog/trunk/class/action/admin/adminaddarticlecategoryajaxaction.class.php=

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
---
plog/trunk/class/action/admin/adminaddarticlecategoryajaxaction.class.php=

2006-01-08 17:43:16 UTC (rev 2762)
+++
plog/trunk/class/action/admin/adminaddarticlecategoryajaxaction.class.php=

2006-01-10 10:38:38 UTC (rev 2763)
@@ -0,0 +1,98 @@
+<?php
+
+	include_once( PLOG_CLASS_PATH."class/action/admin/adminaction.class.
php" );
+    include_once( =
PLOG_CLASS_PATH."class/dao/articlecategories.class.php"
);
+	include_once( PLOG_CLASS_PATH."class/data/textfilter.class.php" );

+	include_once(
PLOG_CLASS_PATH."class/view/admin/adminxmlview.class.php" );
+
+    /**
+     * \ingroup Action
+     * @private
+     *
+     * Action that adds a new article category to the database.
+     */
+    class AdminAddArticleCategoryAjaxAction extends AdminAction=20
+	{
+
+    	var $_categoryName;
+        var $_categoryUrl;
+		var $_properties;
+		var $_categoryDescription;
+
+    	/**
+         * Constructor. If nothing else, it also has to call the
constructor of the parent
+         * class, BlogAction with the same parameters
+         */
+        function AdminAddArticleCategoryAjaxAction( $actionInfo, =
$request )
+        {
+        	$this->AdminAction( $actionInfo, $request );
+        }
+        function validate()
+        {
+			// fetch the data, we already know it's valid and
that we can trust it!
+        	$this->_categoryName     =3D
Textfilter::filterAllHTML($this->_request->getValue( "categoryName" ));
+            $this->_categoryUrl      =3D "";
+            $this->_categoryInMainPage =3D 1;
+			$this->_categoryDescription =3D $this->_categoryName;
+			$this->_properties =3D "";	      =20
+
+            // check if there's any file to upload
+            if( empty($this->_categoryName) || $this->_categoryName =
=3D=3D "" )
{
+	            $this->_view =3D new AdminXmlView( $this->_blogInfo,
"response" );			=09
+	            $this->_view->setValue( "method", "addCategoryAjax" );
+            	$this->_view->setValue( "success", "0" );
+            	$this->_view->setValue( "message",
$this->_locale->tr("error_adding_article_category") );    	           =20
+                return false;
+            }              =20
+            return true;
+        }
+
+        /**
+         * Carries out the specified action
+         */
+        function perform()
+        {
+			// create the object...
+            $categories =3D new ArticleCategories();
+            $category   =3D new ArticleCategory( $this->_categoryName,
+                                               $this->_categoryUrl,
+                                               =
$this->_blogInfo->getId(),
+                                               =
$this->_categoryInMainPage,
+								=09
$this->_categoryDescription,
+								=09
0,
+								=09
$this->_properties );
+								=09

+			// fire the pre event...
+			$this->notifyEvent( EVENT_PRE_CATEGORY_ADD, Array(
"category" =3D> &$category ));
+
+			$this->_view =3D new AdminXmlView( $this->_blogInfo,
"response" );			=09
+			$this->_view->setValue( "method", "addCategoryAjax"
);=09
+           =20
+            // once we have built the object, we can add it to the
database!
+            $catId =3D $categories->addArticleCategory( $category );
+
+            // once we have built the object, we can add it to the =
database
+            $this->_view =3D new AdminXmlView( $this->_blogInfo, =
"response"
);			=09
+            $this->_view->setValue( "method", "addCategoryAjax" );
+            if( $catId )
+            {
+            	$this->_view->setValue( "success", "1" );
+            	$this->_view->setValue( "message",
$this->_locale->pr("category_added_ok", $this->_categoryName) );

+            =09
+                $result =3D '<id>'.$catId.'</id>';
+                $result .=3D '<name>'.$this->_categoryName.'</name>';
+                $this->_view->setValue( "result", $result );
+			=09
+				// fire the post event
+				$this->notifyEvent( EVENT_POST_CATEGORY_ADD,
Array( "category" =3D> &$category ));
+			}            =20
+            else
+            {
+            	$this->_view->setValue( "success", "0" );
+            	$this->_view->setValue( "message",
$this->_locale->tr("error_adding_article_category") );              	=20
+            }
+               =20
+            return true;=09
+        }
+    }
+?>
\ No newline at end of file

Added:
plog/trunk/class/action/admin/adminsavedraftarticleajaxaction.class.php
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
---
plog/trunk/class/action/admin/adminsavedraftarticleajaxaction.class.php	=
2006
-01-08 17:43:16 UTC (rev 2762)
+++
plog/trunk/class/action/admin/adminsavedraftarticleajaxaction.class.php	=
2006
-01-10 10:38:38 UTC (rev 2763)
@@ -0,0 +1,140 @@
+<?php
+
+	include_once( PLOG_CLASS_PATH."class/action/admin/adminaction.class.
php" );
+	include_once(
PLOG_CLASS_PATH."class/view/admin/adminxmlview.class.php" );
+	include_once( PLOG_CLASS_PATH."class/data/timestamp.class.php");
+    include_once( PLOG_CLASS_PATH."class/dao/articles.class.php" );
+=09
+    /**
+     * \ingroup Action
+     * @private
+     */
+	class AdminSaveDraftArticleAjaxAction extends AdminAction
+	{
+	=09
+		function AdminSaveDraftArticleAjaxAction( $actionInfo,
$request )
+		{
+			$this->AdminAction( $actionInfo, $request );
+		}
+	=09
+		function validate()
+		{
+        	$this->_postText     =3D $this->_request->getValue( "postText"
);
+            $this->_postExtendedText =3D $this->_request->getValue(
"postExtendedText" );
+            $this->_postTopic    =3D $this->_request->getValue( =
"postTopic"
);
+           =20
+            // if there is no text, extended text or topic there is no
point in saving anything
+            if( $this->_postText =3D=3D "" && $this->_postExtendedTExt =
=3D=3D "" &&
+                $this->_postTopic =3D=3D "" ) {
+                // nothing to do yet, so let's quit
+                $this->_view =3D new AdminXmlView( $this->_blogInfo,
"response" );
+                $this->_view->setValue( "method", =
"saveDraftArticleAjax" );
+                $this->_view->setValue( "success", "0" );
+                $this->_view->setValue( "message", $this->_locale->tr(
"error_saving_draft" ) );               =20
+               =20
+                return false;
+            }
+           =20
+            $this->_postCategories =3D $this->_request->getValue(
"postCategories" );
+            $this->_postStatus   =3D $this->_request->getValue( =
"postStatus"
);
+			$this->_postSlug =3D $this->_request->getValue(
"postSlug" );
+            $this->_sendNotification =3D $this->_request->getValue(
"sendNotification" );
+            $this->_sendTrackbacks =3D $this->_request->getValue(
"sendTrackbacks" );
+            $this->_sendPings =3D $this->_request->getValue( =
"sendPings" );
+			$this->_postId =3D $this->_request->getValue( "postId"
);
+            $this->_commentsEnabled =3D $this->_request->getValue(
"commentsEnabled" );
+            if( $this->_commentsEnabled !=3D 1 )
+            	$this->_commentsEnabled =3D false;
+            else
+            	$this->_commentsEnabled =3D true;
+		=09
+			// fetch the custom fields
+			$this->_customFields =3D $this->_request->getValue(
"customField" );
+
+            // fetch the timestamp that the post will have
+            if( $this->_config->getValue( =
"disable_javascript_calendar")) {
+            	$this->_postDay =3D $this->_request->getValue( "postDay" =
);
+                $this->_postMonth =3D $this->_request->getValue( =
"postMonth"
);
+                $this->_postHour =3D $this->_request->getValue( =
"postHour" );
+                $this->_postMinutes =3D $this->_request->getValue(
"postMinutes" );
+                $this->_postYear =3D $this->_request->getValue( =
"postYear" );
+            }
+            else {
+            	$postDateTime =3D $this->_request->getValue( =
"postDateTime" );
+                $dateTimeParts =3D explode(" ", $postDateTime);
+                $dateParts =3D explode("/", $dateTimeParts[0] );
+                $timeParts =3D explode(":",$dateTimeParts[1] );
+                $this->_postDay =3D $dateParts[0];
+                $this->_postMonth =3D $dateParts[1];
+                $this->_postYear =3D $dateParts[2];
+                $this->_postHour =3D $timeParts[0];
+                $this->_postMinutes =3D $timeParts[1];
+            }
+
+            $this->_postTimestamp =3D new Timestamp();
+            $this->_postTimestamp->setMinutes( $this->_postMinutes );
+            $this->_postTimestamp->setHour( $this->_postHour );
+            $this->_postTimestamp->setDay( $this->_postDay );
+            $this->_postTimestamp->setMonth( $this->_postMonth );
+            $this->_postTimestamp->setYear( $this->_postYear );
+            return true;	=09
+		}
+	=09
+		function perform()
+		{	=09
+            $status =3D POST_STATUS_DRAFT;
+            $articles =3D new Articles();
+            $postText =3D
Textfilter::xhtmlize($this->_postText).POST_EXTENDED_TEXT_MODIFIER.Textfi=
lte
r::xhtmlize($this->_postExtendedText);
+           =20
+            $article  =3D new Article( $this->_postTopic, $postText,
$this->_postCategories, $this->_userInfo->getId(),=20
+                                     $this->_blogInfo->getId(), =
$status, 0,
Array(), $this->_postSlug );
+            // set also the date before it's too late
+            $article->setDateObject( $this->_postTimestamp );
+            $article->setCommentsEnabled( $this->_commentsEnabled );
+            // prepare the custom fields
+            $fields =3D Array();
+            if( is_array($this->_customFields)) {
+                foreach( $this->_customFields as $fieldId =3D> =
$fieldValue )
{
+                    // 3 of those parameters are not really need when
creating a new object... it's enough that
+                    // we know the field definition id.
+                    $customField =3D new CustomFieldValue( $fieldId,
$fieldValue, "", -1, "", $artId, $this->_blogInfo->getId(), -1);
+                    array_push( $fields, $customField );
+                }
+                $article->setFields( $fields );
+            }
+           =20
+            // in case the post is already in the db
+            if( $this->_postId !=3D "" ) {
+                $article->setId( $this->_postId );
+                $postSavedOk =3D $articles->updateArticle( $article );
+               =20
+                if( $postSavedOk )
+                    $artId =3D $this->_postId;
+                else
+                    $artId =3D false;
+            }
+            else {
+                $artId =3D $articles->addArticle( $article );
+            }
+           =20
+            // once we have built the object, we can add it to the =
database
+            $this->_view =3D new AdminXmlView( $this->_blogInfo, =
"response"
);			=09
+            $this->_view->setValue( "method", "saveDraftArticleAjax" );

+            if( $artId )
+            {
+                $this->_view->setValue( "success", "1" );
+                $this->_view->setValue( "message", $this->_locale->pr(
"draft_saved_ok", $this->_postTopic ) );
+               =20
+                $result =3D '<id>'.$artId.'</id>';
+                $this->_view->setValue( "result", $result );

+            }
+            else
+            {
+                $this->_view->setValue( "success", "0" );
+                $this->_view->setValue( "message", $this->_locale->tr(
"error_saving_draft" ) );            =09
+            }
+               =20
+            return true;		=09
+		}
+    }
+?>
\ No newline at end of file

Deleted: plog/trunk/class/action/admin/adminxmlsavedraftaction.class.php
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
---
plog/trunk/class/action/admin/adminxmlsavedraftaction.class.php	=
2006-01-08
17:43:16 UTC (rev 2762)
+++
plog/trunk/class/action/admin/adminxmlsavedraftaction.class.php	=
2006-01-10
10:38:38 UTC (rev 2763)
@@ -1,128 +0,0 @@
-<?php
-
-	include_once( PLOG_CLASS_PATH."class/action/admin/adminaction.class.
php" );
-	include_once(
PLOG_CLASS_PATH."class/view/admin/adminxmlview.class.php" );
-=09
-    /**
-     * \ingroup Action
-     * @private
-     */
-	class AdminXmlSaveDraftAction extends AdminAction
-	{
-	=09
-		function AdminXmlSaveDraftAction( $actionInfo, $request )
-		{
-			$this->AdminAction( $actionInfo, $request );
-		}
-	=09
-		function validate()
-		{
-        	$this->_postText     =3D $this->_request->getValue( "postText"
);
-            $this->_postExtendedText =3D $this->_request->getValue(
"postExtendedText" );
-            $this->_postTopic    =3D $this->_request->getValue( =
"postTopic"
);
-           =20
-            // if there is no text, extended text or topic there is no
point in saving anything
-            if( $this->_postText =3D=3D "" && $this->_postExtendedTExt =
=3D=3D "" &&
-                $this->_postTopic =3D=3D "" ) {
-                // nothing to do yet, so let's quit
-                $this->_view =3D new AdminXmlView( $this->_blogInfo,
"response" );
-                $this->_view->setValue( "method", "saveXmlDraft" );
-                $this->_view->setValue( "result", "0" );
-               =20
-                return false;
-            }
-           =20
-            $this->_postCategories =3D $this->_request->getValue(
"postCategories" );
-            $this->_postStatus   =3D $this->_request->getValue( =
"postStatus"
);
-			$this->_postSlug =3D $this->_request->getValue(
"postSlug" );
-            $this->_sendNotification =3D $this->_request->getValue(
"sendNotification" );
-            $this->_sendTrackbacks =3D $this->_request->getValue(
"sendTrackbacks" );
-            $this->_sendPings =3D $this->_request->getValue( =
"sendPings" );
-			$this->_postId =3D $this->_request->getValue( "postId"
);
-            $this->_commentsEnabled =3D $this->_request->getValue(
"commentsEnabled" );
-            if( $this->_commentsEnabled !=3D 1 )
-            	$this->_commentsEnabled =3D false;
-            else
-            	$this->_commentsEnabled =3D true;
-		=09
-			// fetch the custom fields
-			$this->_customFields =3D $this->_request->getValue(
"customField" );
-
-            // fetch the timestamp that the post will have
-            if( $this->_config->getValue( =
"disable_javascript_calendar")) {
-            	$this->_postDay =3D $this->_request->getValue( "postDay" =
);
-                $this->_postMonth =3D $this->_request->getValue( =
"postMonth"
);
-                $this->_postHour =3D $this->_request->getValue( =
"postHour" );
-                $this->_postMinutes =3D $this->_request->getValue(
"postMinutes" );
-                $this->_postYear =3D $this->_request->getValue( =
"postYear" );
-            }
-            else {
-            	$postDateTime =3D $this->_request->getValue( =
"postDateTime" );
-                $dateTimeParts =3D explode(" ", $postDateTime);
-                $dateParts =3D explode("/", $dateTimeParts[0] );
-                $timeParts =3D explode(":",$dateTimeParts[1] );
-                $this->_postDay =3D $dateParts[0];
-                $this->_postMonth =3D $dateParts[1];
-                $this->_postYear =3D $dateParts[2];
-                $this->_postHour =3D $timeParts[0];
-                $this->_postMinutes =3D $timeParts[1];
-            }
-
-            $this->_postTimestamp =3D new Timestamp();
-            $this->_postTimestamp->setMinutes( $this->_postMinutes );
-            $this->_postTimestamp->setHour( $this->_postHour );
-            $this->_postTimestamp->setDay( $this->_postDay );
-            $this->_postTimestamp->setMonth( $this->_postMonth );
-            $this->_postTimestamp->setYear( $this->_postYear );
-            return true;	=09
-		}
-	=09
-		function perform()
-		{	=09
-            $status =3D POST_STATUS_DRAFT;
-            $articles =3D new Articles();
-            $postText =3D
Textfilter::xhtmlize($this->_postText).POST_EXTENDED_TEXT_MODIFIER.Textfi=
lte
r::xhtmlize($this->_postExtendedText);
-           =20
-            $article  =3D new Article( $this->_postTopic, $postText,
$this->_postCategories, $this->_userInfo->getId(),=20
-                                     $this->_blogInfo->getId(), =
$status, 0,
Array(), $this->_postSlug );
-            // set also the date before it's too late
-            $article->setDateObject( $this->_postTimestamp );
-            $article->setCommentsEnabled( $this->_commentsEnabled );
-            // prepare the custom fields
-            $fields =3D Array();
-            if( is_array($this->_customFields)) {
-                foreach( $this->_customFields as $fieldId =3D> =
$fieldValue )
{
-                    // 3 of those parameters are not really need when
creating a new object... it's enough that
-                    // we know the field definition id.
-                    $customField =3D new CustomFieldValue( $fieldId,
$fieldValue, "", -1, "", $artId, $this->_blogInfo->getId(), -1);
-                    array_push( $fields, $customField );
-                }
-                $article->setFields( $fields );
-            }
-           =20
-            // in case the post is already in the db
-            if( $this->_postId !=3D "" ) {
-                $article->setId( $this->_postId );
-                $postSavedOk =3D $articles->updateArticle( $article );
-               =20
-                if( $postSavedOk )
-                    $artId =3D $this->_postId;
-                else
-                    $artId =3D false;
-            }
-            else {
-                $artId =3D $articles->addArticle( $article );
-            }
-           =20
-            // once we have built the object, we can add it to the =
database
-            $this->_view =3D new AdminXmlView( $this->_blogInfo, =
"response"
);			=09
-            $this->_view->setValue( "method", "saveXmlDraft"
);			=09
-            if( $artId )
-                $this->_view->setValue( "result", $artId );
-            else=20
-                $this->_view->setValue( "result", "0" );
-               =20
-            return true;		=09
-		}
-    }
-?>
\ No newline at end of file

Modified: plog/trunk/class/controller/admincontrollermap.properties.php
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
---
plog/trunk/class/controller/admincontrollermap.properties.php	2006-01-08
17:43:16 UTC (rev 2762)
+++
plog/trunk/class/controller/admincontrollermap.properties.php	2006-01-10
10:38:38 UTC (rev 2763)
@@ -26,6 +26,8 @@
     $actions["newArticleCategory"] =3D "AdminNewArticleCategoryAction";
     // adds the category to the db
     $actions["addArticleCategory"] =3D "AdminAddArticleCategoryAction";
+    // adds the category to the db through Ajax
+    $actions["addArticleCategoryAjax"] =3D
"AdminAddArticleCategoryAjaxAction";   =20
     // shows the settings of the blog
     $actions["blogSettings"] =3D "AdminBlogSettingsAction";
     // updates the settings of the blog
@@ -230,7 +232,7 @@
 	$actions["xmlPing"] =3D "AdminXmlPingAction";
 	// the action below is used in cooperation with the XmlHttpRequest
object to
 	// automatically save drafts of posts in the background
-	$actions["saveXmlDraft"] =3D "AdminXmlSaveDraftAction";
+	$actions["saveDraftArticleAjax"] =3D
"AdminSaveDraftArticleAjaxAction";
 	// remove a trackback
 	$actions["deleteTrackback"] =3D "AdminDeleteTrackbackAction";
 	$actions["deleteTrackbacks"] =3D "AdminDeleteTrackbackAction";

Added: plog/trunk/js/prototype/prototype.js
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/js/prototype/prototype.js	2006-01-08 17:43:16 UTC (rev
2762)
+++ plog/trunk/js/prototype/prototype.js	2006-01-10 10:38:38 UTC (rev
2763)
@@ -0,0 +1,1038 @@
+/*  Prototype JavaScript framework, version 1.3.1
+ *  (c) 2005 Sam Stephenson <sam at conio.net>
+ *
+ *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please =
diff
+ *  against the source tree, available from the Prototype darcs =
repository.

+ *
+ *  Prototype is freely distributable under the terms of an MIT-style
license.
+ *
+ *  For details, see the Prototype web site: =
http://prototype.conio.net/
+ *
+/*----------------------------------------------------------------------=
---
-*/
+
+var Prototype =3D {
+  Version: '1.3.1',
+  emptyFunction: function() {}
+}
+
+var Class =3D {
+  create: function() {
+    return function() {=20
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract =3D new Object();
+
+Object.extend =3D function(destination, source) {
+  for (property in source) {
+    destination[property] =3D source[property];
+  }
+  return destination;
+}
+
+Object.prototype.extend =3D function(object) {
+  return Object.extend.apply(this, [this, object]);
+}
+
+Function.prototype.bind =3D function(object) {
+  var __method =3D this;
+  return function() {
+    __method.apply(object, arguments);
+  }
+}
+
+Function.prototype.bindAsEventListener =3D function(object) {
+  var __method =3D this;
+  return function(event) {
+    __method.call(object, event || window.event);
+  }
+}
+
+Number.prototype.toColorPart =3D function() {
+  var digits =3D this.toString(16);
+  if (this < 16) return '0' + digits;
+  return digits;
+}
+
+var Try =3D {
+  these: function() {
+    var returnValue;
+
+    for (var i =3D 0; i < arguments.length; i++) {
+      var lambda =3D arguments[i];
+      try {
+        returnValue =3D lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*----------------------------------------------------------------------=
---
-*/
+
+var PeriodicalExecuter =3D Class.create();
+PeriodicalExecuter.prototype =3D {
+  initialize: function(callback, frequency) {
+    this.callback =3D callback;
+    this.frequency =3D frequency;
+    this.currentlyExecuting =3D false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {=20
+        this.currentlyExecuting =3D true;
+        this.callback();=20
+      } finally {=20
+        this.currentlyExecuting =3D false;
+      }
+    }
+  }
+}
+
+/*----------------------------------------------------------------------=
---
-*/
+
+function $() {
+  var elements =3D new Array();
+
+  for (var i =3D 0; i < arguments.length; i++) {
+    var element =3D arguments[i];
+    if (typeof element =3D=3D 'string')
+      element =3D document.getElementById(element);
+
+    if (arguments.length =3D=3D 1)=20
+      return element;
+
+    elements.push(element);
+  }
+
+  return elements;
+}
+
+if (!Array.prototype.push) {
+  Array.prototype.push =3D function() {
+		var startLength =3D this.length;
+		for (var i =3D 0; i < arguments.length; i++)
+      this[startLength + i] =3D arguments[i];
+	  return this.length;
+  }
+}
+
+if (!Function.prototype.apply) {
+  // Based on code from http://www.youngpup.net/
+  Function.prototype.apply =3D function(object, parameters) {
+    var parameterStrings =3D new Array();
+    if (!object)     object =3D window;
+    if (!parameters) parameters =3D new Array();
+   =20
+    for (var i =3D 0; i < parameters.length; i++)
+      parameterStrings[i] =3D 'parameters[' + i + ']';
+   =20
+    object.__apply__ =3D this;
+    var result =3D eval('object.__apply__(' +=20
+      parameterStrings.join(', ') + ')');
+    object.__apply__ =3D null;
+   =20
+    return result;
+  }
+}
+
+String.prototype.extend({
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  escapeHTML: function() {
+    var div =3D document.createElement('div');
+    var text =3D document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div =3D document.createElement('div');
+    div.innerHTML =3D this.stripTags();
+    return div.childNodes[0].nodeValue;
+  }
+});
+
+var Ajax =3D {
+  getTransport: function() {
+    return Try.these(
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
+      function() {return new XMLHttpRequest()}
+    ) || false;
+  }
+}
+
+Ajax.Base =3D function() {};
+Ajax.Base.prototype =3D {
+  setOptions: function(options) {
+    this.options =3D {
+      method:       'post',
+      asynchronous: true,
+      parameters:   ''
+    }.extend(options || {});
+  },
+
+  responseIsSuccess: function() {
+    return this.transport.status =3D=3D undefined
+        || this.transport.status =3D=3D 0=20
+        || (this.transport.status >=3D 200 && this.transport.status < =
300);
+  },
+
+  responseIsFailure: function() {
+    return !this.responseIsSuccess();
+  }
+}
+
+Ajax.Request =3D Class.create();
+Ajax.Request.Events =3D=20
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype =3D (new Ajax.Base()).extend({
+  initialize: function(url, options) {
+    this.transport =3D Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    var parameters =3D this.options.parameters || '';
+    if (parameters.length > 0) parameters +=3D '&_=3D';
+
+    try {
+      if (this.options.method =3D=3D 'get')
+        url +=3D '?' + parameters;
+
+      this.transport.open(this.options.method, url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) {
+        this.transport.onreadystatechange =3D =
this.onStateChange.bind(this);
+        setTimeout((function() =
{this.respondToReadyState(1)}).bind(this),
10);
+      }
+
+      this.setRequestHeaders();
+
+      var body =3D this.options.postBody ? this.options.postBody :
parameters;
+      this.transport.send(this.options.method =3D=3D 'post' ? body : =
null);
+
+    } catch (e) {
+    }
+  },
+
+  setRequestHeaders: function() {
+    var requestHeaders =3D=20
+      ['X-Requested-With', 'XMLHttpRequest',
+       'X-Prototype-Version', Prototype.Version];
+
+    if (this.options.method =3D=3D 'post') {
+      requestHeaders.push('Content-type',=20
+        'application/x-www-form-urlencoded');
+
+      /* Force "Connection: close" for Mozilla browsers to work around
+       * a bug where XMLHttpReqeuest sends an incorrect Content-length
+       * header. See Mozilla Bugzilla #246651.=20
+       */
+      if (this.transport.overrideMimeType)
+        requestHeaders.push('Connection', 'close');
+    }
+
+    if (this.options.requestHeaders)
+      requestHeaders.push.apply(requestHeaders,
this.options.requestHeaders);
+
+    for (var i =3D 0; i < requestHeaders.length; i +=3D 2)
+      this.transport.setRequestHeader(requestHeaders[i],
requestHeaders[i+1]);
+  },
+
+  onStateChange: function() {
+    var readyState =3D this.transport.readyState;
+    if (readyState !=3D 1)
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  respondToReadyState: function(readyState) {
+    var event =3D Ajax.Request.Events[readyState];
+
+    if (event =3D=3D 'Complete')
+      (this.options['on' + this.transport.status]
+       || this.options['on' + (this.responseIsSuccess() ? 'Success' :
'Failure')]
+       || Prototype.emptyFunction)(this.transport);
+
+    (this.options['on' + event] ||
Prototype.emptyFunction)(this.transport);
+
+    /* Avoid memory leak in MSIE: clean up the oncomplete event handler =
*/
+    if (event =3D=3D 'Complete')
+      this.transport.onreadystatechange =3D Prototype.emptyFunction;
+  }
+});
+
+Ajax.Updater =3D Class.create();
+Ajax.Updater.ScriptFragment =3D =
'(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
+
+Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
+  initialize: function(container, url, options) {
+    this.containers =3D {
+      success: container.success ? $(container.success) : $(container),
+      failure: container.failure ? $(container.failure) :
+        (container.success ? null : $(container))
+    }
+
+    this.transport =3D Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete =3D this.options.onComplete || =
Prototype.emptyFunction;
+    this.options.onComplete =3D (function() {
+      this.updateContent();
+      onComplete(this.transport);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver =3D this.responseIsSuccess() ?
+      this.containers.success : this.containers.failure;
+
+    var match    =3D new RegExp(Ajax.Updater.ScriptFragment, 'img');
+    var response =3D this.transport.responseText.replace(match, '');
+    var scripts  =3D this.transport.responseText.match(match);
+
+    if (receiver) {
+      if (this.options.insertion) {
+        new this.options.insertion(receiver, response);
+      } else {
+        receiver.innerHTML =3D response;
+      }
+    }
+
+    if (this.responseIsSuccess()) {
+      if (this.onComplete)
+        setTimeout((function() {this.onComplete(
+          this.transport)}).bind(this), 10);
+    }
+
+    if (this.options.evalScripts && scripts) {
+      match =3D new RegExp(Ajax.Updater.ScriptFragment, 'im');
+      setTimeout((function() {
+        for (var i =3D 0; i < scripts.length; i++)
+          eval(scripts[i].match(match)[1]);
+      }).bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater =3D Class.create();
+Ajax.PeriodicalUpdater.prototype =3D (new Ajax.Base()).extend({
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete =3D this.options.onComplete;
+
+    this.frequency =3D (this.options.frequency || 2);
+    this.decay =3D 1;
+
+    this.updater =3D {};
+    this.container =3D container;
+    this.url =3D url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete =3D this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.onComplete =3D undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay =3D (request.responseText =3D=3D this.lastText ?=20
+        this.decay * this.options.decay : 1);
+
+      this.lastText =3D request.responseText;
+    }
+    this.timer =3D setTimeout(this.onTimerEvent.bind(this),=20
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater =3D new Ajax.Updater(this.container, this.url,
this.options);
+  }
+});
+
+document.getElementsByClassName =3D function(className) {
+  var children =3D document.getElementsByTagName('*') || document.all;
+  var elements =3D new Array();
+ =20
+  for (var i =3D 0; i < children.length; i++) {
+    var child =3D children[i];
+    var classNames =3D child.className.split(' ');
+    for (var j =3D 0; j < classNames.length; j++) {
+      if (classNames[j] =3D=3D className) {
+        elements.push(child);
+        break;
+      }
+    }
+  }
+ =20
+  return elements;
+}
+
+/*----------------------------------------------------------------------=
---
-*/
+
+if (!window.Element) {
+  var Element =3D new Object();
+}
+
+Object.extend(Element, {
+  toggle: function() {
+    for (var i =3D 0; i < arguments.length; i++) {
+      var element =3D $(arguments[i]);
+      element.style.display =3D=20
+        (element.style.display =3D=3D 'none' ? '' : 'none');
+    }
+  },
+
+  hide: function() {
+    for (var i =3D 0; i < arguments.length; i++) {
+      var element =3D $(arguments[i]);
+      element.style.display =3D 'none';
+    }
+  },
+
+  show: function() {
+    for (var i =3D 0; i < arguments.length; i++) {
+      var element =3D $(arguments[i]);
+      element.style.display =3D '';
+    }
+  },
+
+  remove: function(element) {
+    element =3D $(element);
+    element.parentNode.removeChild(element);
+  },
+  =20
+  getHeight: function(element) {
+    element =3D $(element);
+    return element.offsetHeight;=20
+  },
+
+  hasClassName: function(element, className) {
+    element =3D $(element);
+    if (!element)
+      return;
+    var a =3D element.className.split(' ');
+    for (var i =3D 0; i < a.length; i++) {
+      if (a[i] =3D=3D className)
+        return true;
+    }
+    return false;
+  },
+
+  addClassName: function(element, className) {
+    element =3D $(element);
+    Element.removeClassName(element, className);
+    element.className +=3D ' ' + className;
+  },
+
+  removeClassName: function(element, className) {
+    element =3D $(element);
+    if (!element)
+      return;
+    var newClassName =3D '';
+    var a =3D element.className.split(' ');
+    for (var i =3D 0; i < a.length; i++) {
+      if (a[i] !=3D className) {
+        if (i > 0)
+          newClassName +=3D ' ';
+        newClassName +=3D a[i];
+      }
+    }
+    element.className =3D newClassName;
+  },
+ =20
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    var element =3D $(element);
+    for (var i =3D 0; i < element.childNodes.length; i++) {
+      var node =3D element.childNodes[i];
+      if (node.nodeType =3D=3D 3 && !/\S/.test(node.nodeValue))=20
+        Element.remove(node);
+    }
+  }
+});
+
+var Toggle =3D new Object();
+Toggle.display =3D Element.toggle;
+
+/*----------------------------------------------------------------------=
---
-*/
+
+Abstract.Insertion =3D function(adjacency) {
+  this.adjacency =3D adjacency;
+}
+
+Abstract.Insertion.prototype =3D {
+  initialize: function(element, content) {
+    this.element =3D $(element);
+    this.content =3D content;
+   =20
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      this.element.insertAdjacentHTML(this.adjacency, this.content);
+    } else {
+      this.range =3D this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.fragment =3D =
this.range.createContextualFragment(this.content);
+      this.insertContent();
+    }
+  }
+}
+
+var Insertion =3D new Object();
+
+Insertion.Before =3D Class.create();
+Insertion.Before.prototype =3D (new
Abstract.Insertion('beforeBegin')).extend({
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+ =20
+  insertContent: function() {
+    this.element.parentNode.insertBefore(this.fragment, this.element);
+  }
+});
+
+Insertion.Top =3D Class.create();
+Insertion.Top.prototype =3D (new =
Abstract.Insertion('afterBegin')).extend({
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+ =20
+  insertContent: function() { =20
+    this.element.insertBefore(this.fragment, this.element.firstChild);
+  }
+});
+
+Insertion.Bottom =3D Class.create();
+Insertion.Bottom.prototype =3D (new =
Abstract.Insertion('beforeEnd')).extend({
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+ =20
+  insertContent: function() {
+    this.element.appendChild(this.fragment);
+  }
+});
+
+Insertion.After =3D Class.create();
+Insertion.After.prototype =3D (new =
Abstract.Insertion('afterEnd')).extend({
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+ =20
+  insertContent: function() {
+    this.element.parentNode.insertBefore(this.fragment,=20
+      this.element.nextSibling);
+  }
+});
+
+var Field =3D {
+  clear: function() {
+    for (var i =3D 0; i < arguments.length; i++)
+      $(arguments[i]).value =3D '';
+  },
+
+  focus: function(element) {
+    $(element).focus();
+  },
+ =20
+  present: function() {
+    for (var i =3D 0; i < arguments.length; i++)
+      if ($(arguments[i]).value =3D=3D '') return false;
+    return true;
+  },
+ =20
+  select: function(element) {
+    $(element).select();
+  },
+  =20
+  activate: function(element) {
+    $(element).focus();
+    $(element).select();
+  }
+}
+
+/*----------------------------------------------------------------------=
---
-*/
+
+var Form =3D {
+  serialize: function(form) {
+    var elements =3D Form.getElements($(form));
+    var queryComponents =3D new Array();
+   =20
+    for (var i =3D 0; i < elements.length; i++) {
+      var queryComponent =3D Form.Element.serialize(elements[i]);
+      if (queryComponent)
+        queryComponents.push(queryComponent);
+    }
+   =20
+    return queryComponents.join('&');
+  },
+ =20
+  getElements: function(form) {
+    var form =3D $(form);
+    var elements =3D new Array();
+
+    for (tagName in Form.Element.Serializers) {
+      var tagElements =3D form.getElementsByTagName(tagName);
+      for (var j =3D 0; j < tagElements.length; j++)
+        elements.push(tagElements[j]);
+    }
+    return elements;
+  },
+ =20
+  getInputs: function(form, typeName, name) {
+    var form =3D $(form);
+    var inputs =3D form.getElementsByTagName('input');
+   =20
+    if (!typeName && !name)
+      return inputs;
+     =20
+    var matchingInputs =3D new Array();
+    for (var i =3D 0; i < inputs.length; i++) {
+      var input =3D inputs[i];
+      if ((typeName && input.type !=3D typeName) ||
+          (name && input.name !=3D name))=20
+        continue;
+      matchingInputs.push(input);
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    var elements =3D Form.getElements(form);
+    for (var i =3D 0; i < elements.length; i++) {
+      var element =3D elements[i];
+      element.blur();
+      element.disabled =3D 'true';
+    }
+  },
+
+  enable: function(form) {
+    var elements =3D Form.getElements(form);
+    for (var i =3D 0; i < elements.length; i++) {
+      var element =3D elements[i];
+      element.disabled =3D '';
+    }
+  },
+
+  focusFirstElement: function(form) {
+    var form =3D $(form);
+    var elements =3D Form.getElements(form);
+    for (var i =3D 0; i < elements.length; i++) {
+      var element =3D elements[i];
+      if (element.type !=3D 'hidden' && !element.disabled) {
+        Field.activate(element);
+        break;
+      }
+    }
+  },
+
+  reset: function(form) {
+    $(form).reset();
+  }
+}
+
+Form.Element =3D {
+  serialize: function(element) {
+    var element =3D $(element);
+    var method =3D element.tagName.toLowerCase();
+    var parameter =3D Form.Element.Serializers[method](element);
+   =20
+    if (parameter)
+      return encodeURIComponent(parameter[0]) + '=3D' +=20
+        encodeURIComponent(parameter[1]);                  =20
+  },
+ =20
+  getValue: function(element) {
+    var element =3D $(element);
+    var method =3D element.tagName.toLowerCase();
+    var parameter =3D Form.Element.Serializers[method](element);
+   =20
+    if (parameter)=20
+      return parameter[1];
+  }
+}
+
+Form.Element.Serializers =3D {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'submit':
+      case 'hidden':
+      case 'password':
+      case 'text':
+        return Form.Element.Serializers.textarea(element);
+      case 'checkbox': =20
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+    }
+    return false;
+  },
+
+  inputSelector: function(element) {
+    if (element.checked)
+      return [element.name, element.value];
+  },
+
+  textarea: function(element) {
+    return [element.name, element.value];
+  },
+
+  select: function(element) {
+    var value =3D '';
+    if (element.type =3D=3D 'select-one') {
+      var index =3D element.selectedIndex;
+      if (index >=3D 0)
+        value =3D element.options[index].value ||
element.options[index].text;
+    } else {
+      value =3D new Array();
+      for (var i =3D 0; i < element.length; i++) {
+        var opt =3D element.options[i];
+        if (opt.selected)
+          value.push(opt.value || opt.text);
+      }
+    }
+    return [element.name, value];
+  }
+}
+
+/*----------------------------------------------------------------------=
---
-*/
+
+var $F =3D Form.Element.getValue;
+
+/*----------------------------------------------------------------------=
---
-*/
+
+Abstract.TimedObserver =3D function() {}
+Abstract.TimedObserver.prototype =3D {
+  initialize: function(element, frequency, callback) {
+    this.frequency =3D frequency;
+    this.element   =3D $(element);
+    this.callback  =3D callback;
+   =20
+    this.lastValue =3D this.getValue();
+    this.registerCallback();
+  },
+ =20
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+ =20
+  onTimerEvent: function() {
+    var value =3D this.getValue();
+    if (this.lastValue !=3D value) {
+      this.callback(this.element, value);
+      this.lastValue =3D value;
+    }
+  }
+}
+
+Form.Element.Observer =3D Class.create();
+Form.Element.Observer.prototype =3D (new =
Abstract.TimedObserver()).extend({
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer =3D Class.create();
+Form.Observer.prototype =3D (new Abstract.TimedObserver()).extend({
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*----------------------------------------------------------------------=
---
-*/
+
+Abstract.EventObserver =3D function() {}
+Abstract.EventObserver.prototype =3D {
+  initialize: function(element, callback) {
+    this.element  =3D $(element);
+    this.callback =3D callback;
+   =20
+    this.lastValue =3D this.getValue();
+    if (this.element.tagName.toLowerCase() =3D=3D 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+ =20
+  onElementEvent: function() {
+    var value =3D this.getValue();
+    if (this.lastValue !=3D value) {
+      this.callback(this.element, value);
+      this.lastValue =3D value;
+    }
+  },
+ =20
+  registerFormCallbacks: function() {
+    var elements =3D Form.getElements(this.element);
+    for (var i =3D 0; i < elements.length; i++)
+      this.registerCallback(elements[i]);
+  },
+ =20
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox': =20
+        case 'radio':
+          element.target =3D this;
+          element.prev_onclick =3D element.onclick ||
Prototype.emptyFunction;
+          element.onclick =3D function() {
+            this.prev_onclick();=20
+            this.target.onElementEvent();
+          }
+          break;
+        case 'password':
+        case 'text':
+        case 'textarea':
+        case 'select-one':
+        case 'select-multiple':
+          element.target =3D this;
+          element.prev_onchange =3D element.onchange ||
Prototype.emptyFunction;
+          element.onchange =3D function() {
+            this.prev_onchange();=20
+            this.target.onElementEvent();
+          }
+          break;
+      }
+    }   =20
+  }
+}
+
+Form.Element.EventObserver =3D Class.create();
+Form.Element.EventObserver.prototype =3D (new
Abstract.EventObserver()).extend({
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver =3D Class.create();
+Form.EventObserver.prototype =3D (new =
Abstract.EventObserver()).extend({
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+
+if (!window.Event) {
+  var Event =3D new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which =3D=3D 1)) ||
+            ((event.button) && (event.button =3D=3D 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +=20
+      (document.documentElement.scrollLeft || =
document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +=20
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {=20
+      event.preventDefault();=20
+      event.stopPropagation();=20
+    } else {
+      event.returnValue =3D false;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element =3D Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() !=3D tagName.toUpperCase())))
+      element =3D element.parentNode;
+    return element;
+  },
+
+  observers: false,
+ =20
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers =3D [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+ =20
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i =3D 0; i < Event.observers.length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] =3D null;
+    }
+    Event.observers =3D false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    var element =3D $(element);
+    useCapture =3D useCapture || false;
+   =20
+    if (name =3D=3D 'keypress' &&
+        ((navigator.appVersion.indexOf('AppleWebKit') > 0)=20
+        || element.attachEvent))
+      name =3D 'keydown';
+   =20
+    this._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    var element =3D $(element);
+    useCapture =3D useCapture || false;
+   =20
+    if (name =3D=3D 'keypress' &&
+        ((navigator.appVersion.indexOf('AppleWebKit') > 0)=20
+        || element.detachEvent))
+      name =3D 'keydown';
+   =20
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      element.detachEvent('on' + name, observer);
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+Event.observe(window, 'unload', Event.unloadCache, false);
+
+var Position =3D {
+
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,=20
+
+  // must be called before calling withinIncludingScrolloffset, every =
time
the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =3D  window.pageXOffset=20
+                || document.documentElement.scrollLeft=20
+                || document.body.scrollLeft=20
+                || 0;
+    this.deltaY =3D  window.pageYOffset=20
+                || document.documentElement.scrollTop=20
+                || document.body.scrollTop=20
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT =3D 0, valueL =3D 0;
+    do {
+      valueT +=3D element.scrollTop  || 0;
+      valueL +=3D element.scrollLeft || 0;=20
+      element =3D element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT =3D 0, valueL =3D 0;
+    do {
+      valueT +=3D element.offsetTop  || 0;
+      valueL +=3D element.offsetLeft || 0;
+      element =3D element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp =3D x;
+    this.ycomp =3D y;
+    this.offset =3D this.cumulativeOffset(element);
+
+    return (y >=3D this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >=3D this.offset[0] &&=20
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache =3D this.realOffset(element);
+
+    this.xcomp =3D x + offsetcache[0] - this.deltaX;
+    this.ycomp =3D y + offsetcache[1] - this.deltaY;
+    this.offset =3D this.cumulativeOffset(element);
+
+    return (this.ycomp >=3D this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >=3D this.offset[0] &&=20
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) { =20
+    if (!mode) return 0; =20
+    if (mode =3D=3D 'vertical')=20
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /=20
+        element.offsetHeight;
+    if (mode =3D=3D 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /=20
+        element.offsetWidth;
+  },
+
+  clone: function(source, target) {
+    source =3D $(source);
+    target =3D $(target);
+    target.style.position =3D 'absolute';
+    var offsets =3D this.cumulativeOffset(source);
+    target.style.top    =3D offsets[1] + 'px';
+    target.style.left   =3D offsets[0] + 'px';
+    target.style.width  =3D source.offsetWidth + 'px';
+    target.style.height =3D source.offsetHeight + 'px';
+  }
+}

Modified: plog/trunk/js/ui/plogui.js
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/js/ui/plogui.js	2006-01-08 17:43:16 UTC (rev 2762)
+++ plog/trunk/js/ui/plogui.js	2006-01-10 10:38:38 UTC (rev 2763)
@@ -1,166 +1,100 @@
 /**
- * when adding a new form, checks that there is at least one category
selected
+ * this function is the one called when clicking the "save draft and
continue" button
  */
-function submitNewPost(form)
+function saveDraftArticleAjax()
 {
-	if( form.postCategories.selectedIndex =3D=3D -1 ) {
-		// we have no category selected!
-		window.alert(msgErrorNoCategorySelected);
+	// if there is no category selected, then we won't save a draft!
+	form =3D document.getElementById( "newPost" );
+=09
+	if( form.postTopic.value =3D=3D '' ) {
+		window.alert( msgErrorPostTopic );
 		return false;
-    } =20
+	}
+=09
+    // Can't use form.postText.value, becasue the form.postText.value =
still
"null"
+    if( htmlAreaEnabled ) {
+		postText =3D tinyMCE.getContent('postText');
+	} else {
+		postText =3D form.postText.value;
+    }
    =20
-	return true;
+    if (postText =3D=3D '') {
+		window.alert( msgErrorPostText );
+		return false;
+	}
+=09
+	if( !submitNewPost( form ))
+		return false;=09
+
+    var formData =3D getPostEditFormElements( "newPost" );
+	var url =3D plogAdminBaseUrl;
+	var params =3D 'op=3DsaveDraftArticleAjax&'+formData;
+	var myAjax =3D new Ajax.Request(
+					url,
+					{method: 'post', parameters: params,
onComplete: saveDraftArticleResponse}
+					);   =20
 }
=20
-// object that we're going to use=20
-var xmlhttp;
-xmlhttp =3D false;
-
 /**
- * the following functions take care of sending requests to
- * save drafts of the current post using the XmlHttpRequest object
- *
- * @param req A valid XmlHttpRequest object
- * @param url The url to which we'd like to send the data
- * @param data The data we'd like to send
- * @return Returns always true, please see the processResponse method
+ * this function is the one called when clicking the "save draft and
continue" button
  */
-function sendData(url, data)=20
+function saveDraftArticleResponse(originalRequest)
 {
-	xmlhttp.onreadystatechange =3D processResponse;
-	xmlhttp.open("POST", url, true, null, null);
-	xmlhttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");=20
-    xmlhttp.setRequestHeader("Content-Length", data.length);=20
-	xmlhttp.send(data);
-
-	return true;
+	//put returned XML in the textarea
+	var xmldoc =3D originalRequest.responseXML;
+	var message =3D
xmldoc.getElementsByTagName('message')[0].firstChild.nodeValue;
+	window.alert(message);
 }
=20
 /**
- * sets the 'xmlhttp' var as an XmlHttpRequest obejct or 'false' if it =
is
not supported
- *
- * @return nothing
+ * when adding a new form, checks that there is at least one category
selected
  */
-function initXmlHttpRequestObject()
+function submitNewPost(form)
 {
-	// --
-	// the code below uses IE's conditional compilation via jscript...
it should
-	// not affect other browsers such as Safari or Mozilla
-	// --
-
-	/*@cc_on @*/
-	/*@if (@_jscript_version >=3D 5)
-	// JScript gives us Conditional compilation, we can cope with old IE
versions.
-	// and security blocked creation of the objects.
-	 try {
-	  xmlhttp =3D new ActiveXObject("Msxml2.XMLHTTP");
-	 } catch (e) {
-	  try {
-	   xmlhttp =3D new ActiveXObject("Microsoft.XMLHTTP");
-	  } catch (E) {
-	   xmlhttp =3D false;
-	  }
-	 }
-	@end @*/
-	if (!xmlhttp && typeof XMLHttpRequest!=3D'undefined' &&
xmlHttpRequestSupportEnabled ) {
-	  xmlhttp =3D new XMLHttpRequest();
-	}
-=09
+	if( form.postCategories.selectedIndex =3D=3D -1 ) {
+		// we have no category selected!
+		window.alert(msgErrorNoCategorySelected);
+		return false;
+    } =20
+   =20
 	return true;
 }
=20
 /**
- * handler that processes asynchronous responses
+ * this function is the one called when clicking the "add category" =
button
  */
-function processResponse()
+function addArticleCategoryAjax()
 {
-    // only if req shows "loaded"
-    if (xmlhttp.readyState =3D=3D 4) {
-        // only if "OK"
-        if (xmlhttp.status =3D=3D 200) {
-			// response successful, let's process the return
message
-			processResponseMessage( xmlhttp.responseText );
-        } else {
-            window.status =3D msgErrorMakingRequest;
-            alert("There was a problem retrieving the XML data:\n" +
xmlhttp.statusText);
-        }
-    }
+	var categoryName =3D $F('newCategory');
+	var url =3D plogAdminBaseUrl;
+	var params =3D 'op=3DaddArticleCategoryAjax' + '&categoryName=3D' +
encodeURIComponent(categoryName);
+	var myAjax =3D new Ajax.Request(
+					url,
+					{method: 'get', parameters: params,
onComplete: addArticleCategoryOption}
+					);
 }
=20
 /**
- * processes a successful xml message
+ * this function is the one called when clicking the "add category" =
button
  */
-function processResponseMessage( message )
+function addArticleCategoryOption(originalRequest)
 {
-	// define the regexp... we should problaby be using the dom model
for parsing this but I'm too lazy to=20
-	// learn dom. Besides, in this case the format of the response is
very easy :)
-	var regexp =3D /^.*<\?xml version=3D"1.0"\?>\n* *<response>\n*
*<method>saveXmlDraft<\/method>\n* *<result>(.*)<\/result>\n*
*<\/response>$/ig;
-=09
-	// execute the regexp and get the results
-	matches =3D regexp.exec( message );
-=09
-	if( !matches ) {
-		postId =3D "";
-		//window.alert( "There was an error in the following
response message:\n" + message );
-		window.alert( msgErrorSavingDraft );
-		window.status =3D msgErrorSavingDraft;
+	//put returned XML in the textarea
+	var xmldoc =3D originalRequest.responseXML;
+	var success =3D
xmldoc.getElementsByTagName('success')[0].firstChild.nodeValue;
+	var message =3D
xmldoc.getElementsByTagName('message')[0].firstChild.nodeValue;
+	if (!success) {
+		window.alert(message);
 	}
-	else {
-		postId =3D matches[1];
-		if( postId > 0 ) {
-			// set the value of the new post identifier
-			document.newPost.postId.value =3D postId;
-			// show a message
-			window.alert( msgDraftSavedOk + " ( id =3D " + postId
+ ")" );
-			// and update the status bar
-			window.status =3D msgDraftSavedOk + " ( id =3D " +
postId + ")";
-		}
+	else
+	{
+		var catId =3D xmldoc.getElementsByTagName('id')[0].firstChild.
nodeValue;
+		var catName =3D
xmldoc.getElementsByTagName('name')[0].firstChild.nodeValue;
+	    $( 'postCategories' ).options.add( new Option( catName, catId ),
0 );
+	    for(i=3D0; i<$( 'postCategories' ).length; i++)
+	    {
+			$( 'postCategories' ).options[i].selected =3D false;
+	    }
+	    $( 'postCategories' ).options[0].selected =3D true;
 	}
 }
-
-/**
- * this function is the one called when clicking the "save draft and
continue" button
- */
-function saveDraft()
-{
-	// if there is no category selected, then we won't save a draft!
-	form =3D document.getElementById( "newPost" );
-=09
-	if( form.postTopic.value =3D=3D '' ) {
-		window.alert( msgErrorPostTopic );
-		return false;
-	}
-=09
-    // Can't use form.postText.value, becasue the form.postText.value =
still
"null"
-    if( htmlAreaEnabled ) {
-		postText =3D tinyMCE.getContent('postText');
-	} else {
-		postText =3D form.postText.value;
-    }
-   =20
-    if (postText =3D=3D '') {
-		window.alert( msgErrorPostText );
-		return false;
-	}
-=09
-	if( !submitNewPost( form ))
-		return false;=09
-=09
-	// check if xmlhttprequest is supported in our browser by
initializing the object
-	initXmlHttpRequestObject();
-=09
-	if( !xmlhttp ) {
-		// if there is no support for xmlhttprequest, then there's
nothing to do!
-		window.alert("XmlHttpRequest is not available in this
browser!");
-		return false;
-	}
-=09
-	// if not, then continue as usual...
-    var formData =3D getPostEditFormElements( "newPost" );
-=09
-	// build up the final url
-    url =3D plogAdminBaseUrl;
-    data =3D "op=3DsaveXmlDraft&"+formData;=20
-    //window.alert(url);
-    sendData( url, data );
-}
\ No newline at end of file

Modified: plog/trunk/locale/locale_en_UK.php
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/locale/locale_en_UK.php	2006-01-08 17:43:16 UTC (rev =
2762)
+++ plog/trunk/locale/locale_en_UK.php	2006-01-10 10:38:38 UTC (rev =
2763)
@@ -227,7 +227,7 @@
 $messages['preview'] =3D 'Preview';
 $messages['add_post'] =3D 'Blog this!';
 $messages['error_saving_draft'] =3D 'There was an error saving the =
draft';
-$messages['draft_saved_ok'] =3D 'Draft saved successfully';
+$messages['draft_saved_ok'] =3D 'Draft article %s saved successfully';
 $messages['error_sending_request'] =3D 'There was an error sending the
request';
 $messages['error_no_category_selected'] =3D 'Please select at least one
category';
 $messages['error_missing_post_topic'] =3D 'Please type a post topic';

Modified: plog/trunk/locale/locale_zh_TW.php
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/locale/locale_zh_TW.php	2006-01-08 17:43:16 UTC (rev =
2762)
+++ plog/trunk/locale/locale_zh_TW.php	2006-01-10 10:38:38 UTC (rev =
2763)
@@ -227,7 +227,7 @@
 $messages['preview'] =3D '=B9w=C4=FD';
 $messages['add_post'] =3D '=B5o=AA=ED!';
 $messages['error_saving_draft'] =3D =
'=C0x=A6s=AF=F3=BDZ=B5o=A5=CD=BF=F9=BB~=A1I';
-$messages['draft_saved_ok'] =3D '=AF=F3=BDZ=A4w=B6=B6=A7Q=C0x=A6s';
+$messages['draft_saved_ok'] =3D '=AF=F3=BDZ =A1u%s=A1v =
=A4w=B6=B6=A7Q=C0x=A6s';
 $messages['error_sending_request'] =3D =
'=B6=C7=B0e=ADn=A8D=AE=C9=B5o=A5=CD=BF=F9=BB~';
 $messages['error_no_category_selected'] =3D =
'=A7A=A8S=A6=B3=BF=EF=BE=DC=A5=F4=A6=F3=A4=C0=C3=FE';
 $messages['error_missing_post_topic'] =3D =
'=BD=D0=BF=E9=A4J=A4=E5=B3=B9=BC=D0=C3D=A1I';

Modified: plog/trunk/templates/admin/header.template
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/templates/admin/header.template	2006-01-08 17:43:16 UTC =
(rev
2762)
+++ plog/trunk/templates/admin/header.template	2006-01-10 10:38:38 UTC =
(rev
2763)
@@ -27,7 +27,7 @@
 	}
 </script>
 {/literal}   =20
-
+<script type=3D"text/javascript" =
src=3D"js/prototype/prototype.js"></script>
 </head>
 <body>
=20

Modified: plog/trunk/templates/admin/newpost.template
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/templates/admin/newpost.template	2006-01-08 17:43:16 UTC =
(rev
2762)
+++ plog/trunk/templates/admin/newpost.template	2006-01-10 10:38:38 UTC =
(rev
2763)
@@ -24,8 +24,6 @@
  {/if}=20
  =20
   // some messages that we are going to need in the functions above
-  var msgErrorSavingDraft =3D "{$locale->tr("error_saving_draft")}";
-  var msgDraftSavedOk =3D "{$locale->tr("draft_saved_ok")}";
   var msgErrorMakingRequest =3D =
"{$locale->tr("error_sending_request")}";
   var msgErrorNoCategorySelected =3D
"{$locale->tr("error_no_category_selected")}";
   var xmlHttpRequestSupportEnabled =3D =
'{$xmlHttpRequestSupportEnabled}';
@@ -134,6 +132,8 @@
            <option value=3D"{$category->getId()}" {if
$smarty.foreach.categories.first} selected=3D"selected"
{/if}>{$category->getName()}</option>
            {/foreach}
          </select>
+         <input type=3D"text" name=3D"newCategory" id=3D"newCategory"
style=3D"width:70%; margin-top:3px;" size=3D"16" value=3D"" />
+         <input type=3D"button" name=3D"addCategory" =
style=3D"width:20%;
margin-top:3px;" value=3D"{$locale->tr("add")}"
onclick=3D"javascript:addArticleCategoryAjax()" />
         {include file=3D"$admintemplatepath/validate.template"
field=3DpostCategories =
message=3D$locale->tr("error_no_category_selected")}	  =20
 	   </div>
 	  =20
@@ -185,7 +185,7 @@
 	</fieldset>
     <div class=3D"buttons">
 		{if $browser->has_feature("xmlhttpreq")}
-		<input type=3D"button" name=3D"saveDraftAndContinue"
value=3D"{$locale->tr("save_draft_and_continue")}"
onclick=3D"javascript:saveDraft()" />
+		<input type=3D"button" name=3D"saveDraftAndContinue"
value=3D"{$locale->tr("save_draft_and_continue")}"
onclick=3D"javascript:saveDraftArticleAjax()" />
 		{/if}=09
 		<input type=3D"button" name=3D"previewPost"
value=3D"{$locale->tr("preview")}" =
onclick=3D"javascript:previewNewPost()" />
 		<input type=3D"submit" name=3D"addPost"
value=3D"{$locale->tr("add_post")}"/>	=09

Modified: plog/trunk/templates/admin/xml/response.template
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- plog/trunk/templates/admin/xml/response.template	2006-01-08 17:43:16
UTC (rev 2762)
+++ plog/trunk/templates/admin/xml/response.template	2006-01-10 10:38:38
UTC (rev 2763)
@@ -1,5 +1,7 @@
 <?xml version=3D"1.0"?>
 <response>
  <method>{$method}</method>
+ <success>{$success}</success>
+ <message><![CDATA[{$message}]]></message>
  <result>{$result}</result>
 </response>
\ No newline at end of file

_______________________________________________
pLog-svn mailing list
pLog-svn at devel.lifetype.net
http://devel.lifetype.net/mailman/listinfo/plog-svn



More information about the pLog-svn mailing list