[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 11:11:49 GMT 2006


BTW, I forgot to tell you, I also change the format of xml.template. You =
can
see the change in the following example:

<reponse>
<method>addArticleCategoryAjax</method>
<success>1</success>
<message>blah blah blah blah</message>
<results>
  <id>1</id>
  <name>test</name>
</results>
</response>=20

1. method: the method name that you defined for this Ajax action
2. success: 0-> fail, 1->success
3. message: message returned from server no matter success or fail. (we
don't need to declare the locale string in newpost.template any more)
4. results: you can defined by your self. Take this as example,  it will
return the new article category name and id

This change can make the Ajax action more generic, how you guys think? =
Need
your input.

Mark

-----Original Message-----
From: Mark Wu [mailto:markplace at gmail.com]=20
Sent: Tuesday, January 10, 2006 6:58 PM
To: 'plog-svn at devel.lifetype.net'
Subject: RE: [pLog-svn] r2763 - in plog/trunk:
class/action/adminclass/controller js js/prototype js/ui locale
templates/admintemplates/admin/xml

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