Yii Framework Forum: How to add the functinality of opening/closing widgets to the blog demo - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

How to add the functinality of opening/closing widgets to the blog demo Rate Topic: -----

#1 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 25 February 2009 - 06:47 AM

It seems to be departing from Yii, because this script is completely written in javascript, however I think it is a kind of a tip for making use of Yii in a sense. Anyway I would like to share this tip with you guys.

I have made our widgets for the blog demo open/close and keep their status between the pages as seen below. Closing a widget is to click the header (title line) of the widget when it is opened. Opening a widget is also to click the header of the widget when it is closed.

Posted Image

[howto begins]

We need to hold the status of the widgets anywhere, because we will see all the widgets are opened when we move to another page without the persistent status of the widgets.

# PersistJS
I have designed to make use of [persistJS](http://pablotron.org/?cid=1557) in order to hold the client status without cookies. There are several backend storages which are not unified, for browsers. Thanks to the `persistJS` however, we are able to hold the client-side informations in the browser in a unified way.

# Installation
* Comment a following line out (for major users who are using IE :P).
~~~
                'urlManager'=>array(
-                      'urlFormat'=>'path',
+                    //  'urlFormat'=>'path',
                        'rules'=>array(
~~~

* Insert following lines before the title tag of `protected/views/layouts/main.php`.
~~~
+ <script type="text/javascript" src="<?php echo Yii::app()->request->baseUrl; ?>/js/jquery-1.3.2.min.js"></script>
+ <script type="text/javascript" src="<?php echo Yii::app()->request->baseUrl; ?>/js/persist-min.js"></script>
<title><?php echo $this->pageTitle; ?></title>
~~~

* Download jQuery from http://www.yiiframew...16.0;attach=178 and persistJS from http://www.yiiframew...16.0;attach=179 and store them to `js` directory just under the blog demo.
[EDIT]Check following google code out because there must be updates.

# Source code
As usual, the source code is available from google code http://code.google.c...demo-enhanced/.

# Limitation
In terms of IE, `persistJS` uses ie backend storage which seems to be dependent to the absolute path of the page. This is why I have commented this line ('urlFormat'=>'path') out.
On the contrary, it is OK for you to use path format in terms of firefox and chrome, though I have not tested all browsers on all platforms.

# Terms & Conditions
This script is fully dependent to JQuery and PersistJS. Please consult the original terms and conditions.
FYI, jQuery: both MIT and GPL licenses, PersistJS: No license?

Have fun ;)

Attached File(s)


0

#2 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,857
  • Joined: 04-October 08
  • Location:DC, USA

Posted 25 February 2009 - 07:27 AM

Good job!
0

#3 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 25 February 2009 - 07:44 AM

Thanks Qiang.

BTW, if you are being annoyed by flashing the page of the blog demo, you can remove the clock widget, because it seems to be slow.
0

#4 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 25 February 2009 - 11:18 PM

I have fixed a bug that the different web application use a common storage key. New source can be found in r8 of google codehttp://code.google.c...urce/detail?r=8. Please use this rather than attaced files on the previous posts.

0

#5 User is offline   qwerty 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 290
  • Joined: 20-November 08

Posted 26 February 2009 - 06:37 PM

Hi,
it`s fine feature. I wonder on implementing this feature in database. That is to say that the status was saved in the user table.
I change status by jquery.toggle but I don`t know how to write the current status in database by widget? Is it possible to do by widget?

Thanx for help.
0

#6 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 26 February 2009 - 08:13 PM

Thanks for your good question.

Actually, I started to develop this feature using ajax in order to store the client-side data to the host. You know there are trade offs between the two approaches.

Ajax:
  + No need to have a cross browser storage
PersistJS:
  + Fast
  + Convenient when frequent interactions between the master and the storage exists

I gave up ajax approach mainly because of the last reason, though my investigation was not enough. I will be able to finish the ajax (or CStatePersister, may be) version after some investigations.

Quote

I change status by jquery.toggle but I don`t know how to write the current status in database by widget? Is it possible to do by widget?

As you may know jQuery has several functions on ajax, I think it is better to use it to transmit the client-side informations to the host. And there are many widgets on a page, it is efficient to transmit those data once, not per widget bases.

0

#7 User is offline   qwerty 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 290
  • Joined: 20-November 08

Posted 27 February 2009 - 02:29 AM

Quote

As you may know jQuery has several functions on ajax, I think it is better to use it to transmit the client-side informations to the host. And there are many widgets on a page, it is efficient to transmit those data once, not per widget bases.


That I would like to use ajax functions form jQuery to transmit client-side inforamtion to the host. But I have to create an additional controller to the appropriate action or can use only widget?

0

#8 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 27 February 2009 - 06:31 AM

Quote

That I would like to use ajax functions form jQuery to transmit client-side inforamtion to the host. But I have to create an additional controller to the appropriate action or can use only widget?


My javascript structure in a pseudo code looks as follows.


Always: {
    Load the status from storage; // e.g. '1,1,1'  (0:closing, 1:opening)
    Open/close widgets according to the status;
}
On click: {
    Find the widget clicked and invert the status; // e.g. '0,1,1'
    Store the status to the storage;
}


You can simply change this local storage to the ajax call such as,


$.get(
ajaxLoad,
{ widget_key: key },
function(retval) {
        :
});

and

  $.get(
    ajaxStore,
      { widget_key: key,
        widget_status: title_vals.join()
      }
);


Other thing you should make is the counterpart methods in the PostController such as,

  public function actionAjaxLoad() {
  $appName = 'blog_enhanced';
  $widgetKey = 'widget_key';
  if (isset($_GET[$widgetKey])) {
        $key = $_GET[$widgetKey];
        $status = $_SESSION[$appName][$key];
        echo $status;
  }
  }

and

public function actionAjaxStore() {
      $appName = 'blog_enhanced';
      $widgetKey = 'widget_key';
      $widgteStatus = 'widget_status';
      if (isset($_GET[$widgetKey])) {
      $key = $_GET[$widgetKey];
      $status = $_GET[$widgteStatus];
      $_SESSION[$appName][$key] = $status;
    }
}
.

In this case, I am using $_SESSION variable as a host-side storage. Hope this helps. ;)

0

#9 User is offline   qwerty 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 290
  • Joined: 20-November 08

Posted 27 February 2009 - 06:48 AM

Hi,
thanx for help. My question is that PostController is controller responsible for the transmission of data post method (not get) other responsible for post in blog?
0

#10 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 27 February 2009 - 11:31 AM

Quote

My question is that PostController is controller responsible for the transmission of data post method (not get) other responsible for post in blog?

Though widgets opening/closing is not related post action at all, you can use counterpart ajax action in the PostController (or other, of course) using ajax function such as 'index.php?r=post/ajax'.

0

#11 User is offline   qwerty 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 290
  • Joined: 20-November 08

Posted 27 February 2009 - 11:55 AM

Or create your own extended class CController with action ajax.
I have the right?
0

#12 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 27 February 2009 - 11:45 PM

Yeah, either is OK. If you create actionAjaxLoad method in the PostController, then you should call it as 'index.php?r=post/ajaxLoad&parameter=value...' from jQuery ajax function. Or, if you extend CController and named it AjaxController, you should call it as 'index.php?r=ajax/ajaxLoad&...'.
I do not think this is important because these URL is not exposed to the users, though.
0

#13 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 28 February 2009 - 03:32 AM

Having tried some modification from client-side storage to host-side one, I found pages sometimes flickering. This comes from the latency(*) of the page rendering.

(1) A widget is rendered as opened
(2) Ajax method retrieves the status from the host (*)
(3) A widget is rendered as closed according to the status

Obviously, it takes longer for the distant host, than the local storage. In order to cope with it, how about following idea?

(A) Modify the code of Portlet as follows.

<?php
class Portlet extends CWidget
{
        public $title;
        public $cssClass='portlet';
        public $headerCssClass='header';
        public $contentCssClass='content';
        public $visible=true;
        public $opened=true;

        public function init()
        {
                if(!$this->visible)
                        return;
                echo "<div class="{$this->cssClass}">n";
                if($this->title!==null)
                        echo "<div class="{$this->headerCssClass}">{$this->title}</div>n";
                if(!$this->opened)
                        return;
                echo "<div class="{$this->contentCssClass}">n";
        }

        public function run()
        {
                if(!$this->visible)
                        return;
                if($this->opened) {
                  $this->renderContent();
                  echo "</div><!-- {$this->contentCssClass} -->n";
                }
                echo "</div><!-- {$this->cssClass} -->";
        }

        protected function renderContent()
        {
        }
}


(B) Create a widget controller having a ajax functionality to tell which widget is opened and closed.

There may not be flickering in this case, I think.
0

#14 User is offline   qwerty 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 290
  • Joined: 20-November 08

Posted 28 February 2009 - 04:28 AM

:) thanx, i just trying something similar in my module.
0

#15 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 28 February 2009 - 05:06 AM

Quote

:) thanx, i just trying something similar in my module.

Nice to hear that :). BTW, I have corrected above code as below.

-        public $opened=false;
+        public $opened=true;

Of course the default value should be ture. This is because I just tested modified code ($opened=false) to see all widgets are closed at the first rendering, and it worked fine.

0

#16 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 424
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 19 March 2009 - 01:56 AM

Finally, I have changed this to use CClientScript as well as ExtendedClientScript that can merge several JS and CSS files. You can get the latest version from the google code.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users