enables a more elaborate 'persistent' mode for toggling plugins - which btw is the...
authorThierry Parmentelat <thierry.parmentelat@inria.fr>
Thu, 4 Apr 2013 13:03:33 +0000 (15:03 +0200)
committerThierry Parmentelat <thierry.parmentelat@inria.fr>
Thu, 4 Apr 2013 13:03:33 +0000 (15:03 +0200)
trash/sliceview.py
unfold/js/plugin.js
unfold/plugin.py
unfold/templates/plugin.html

index 2811bb6..9139454 100644 (file)
@@ -38,12 +38,11 @@ def slice_view (request, slicename=tmp_default_slice):
         page=page,
         title="Slice view for %s"%slicename,
         domid='thestack',
-#        togglable=False,
+        togglable=False,
         sons=[Tabs (
                 page=page,
                 title="2 tabs : w/ and w/o checkboxes",
                 domid='thetabs',
-#                toggled=False,
                 active_domid='checkboxes',
                 sons=[
                     Hazelnut ( 
@@ -62,30 +61,38 @@ def slice_view (request, slicename=tmp_default_slice):
                         checkboxes=True,
                         # this is the query at the core of the slice list
                         query=main_query,
-                        # this of course should be automatic in hazelnut
-                        # for now we turn off sorting on the checkboxes columns this way
-                        datatables_options = { 'aoColumns' : [ None, None, None, None, {'bSortable': False} ] },
+                        datatables_options = { 
+                            # for now we turn off sorting on the checkboxes columns this way
+                            # this of course should be automatic in hazelnut
+                            'aoColumns' : [ None, None, None, None, {'bSortable': False} ],
+                            'iDisplayLength' : 25,
+                            'bLengthChange' : True,
+                            },
                         ),
                     ]),
               Hazelnut ( 
                 page=page,
                 title='not in tabs',
                 domid='standalone',
-#                toggled=False,
                 # this is the query at the core of the slice list
                 query=main_query,
                 columns=['hrn','hostname'],
                 ),
+              # you don't *have to* set a domid, but if you plan on using toggled=persistent then it's required
+              # because domid is the key for storing toggle status in the browser
               QueryCode (
                 page=page,
-                title='xmlrpc code',
+                title='xmlrpc code (toggled=False)',
                 query=main_query,
-#                toggled=False,
+#                domid='xmlrpc',
+                toggled=False,
                 ),
               QuickFilter (
                 page=page,
-                title="QuickFilter is currently the only one that requires metadata",
-                criterias=quickfilter_criterias
+                title="QuickFilter - requires metadata (toggled=False)",
+                criterias=quickfilter_criterias,
+                domid='filters',
+                toggled=False,
                 ),
               ])
 
index 599d079..8efe77c 100644 (file)
@@ -1,65 +1,63 @@
-// xxx NOTE : pending move towards a more elaborate mode for 'toggled'
-// for now it's just True or False and most of this code is not in action yet
-// init_all_plugins does kick in though
+//
+// storing toggle's status in localStorage
+// NOTE that localStorage only stores strings, so true becomes "true"
 var plugin = {
 
-    debug:true,
+    debug:false,
 
     ////////// use local storage to remember open/closed toggles
-    store_status : function (domid) {
-       var plugin=$('#'+domid);
-       key='toggle.'+domid;
-       if (debug) console.log('storing toggle status for '+domid);
-       $.localStorage.setItem(key,plugin.visible());
+    store_status : function (domid,status) {
+       var key='toggle.'+domid;
+       if (plugin.debug) console.log("storing toggle status " + status + " for " + domid + " key=" + key);
+       $.localStorage.setItem(key,status);
     },
     // restore last status
-    restore_last_status : function (domid) {
-       key='toggle.'+domid;
+    retrieve_last_status : function (domid) {
+       var key='toggle.'+domid;
        // don't do anything if nothing stored
-       var retrieved=$.localStorage.getItem(key,undefined);
-       if (retrieved===null) return;
-       if (debug) console.log ("Applying retrieved status " + retrieved +  " to " + domid);
-       set_visible(domid,retrieved);
+       var retrieved=$.localStorage.getItem(key);
+       // set default to true
+       if (retrieved==null) retrieved="true";
+       if (plugin.debug) console.log ("retrieved toggle status for " + domid + " (key=" + key + ") -> " + retrieved);
+       return retrieved;
     },
-    toggle : function (domid) {
-       var plugin=$('#'+domid);
-       plugin.toggle();
+    set_toggle_status : function (domid,status) {
+       var plugindiv=$('#'+domid);
        var showbtn=$('#show-'+domid);
        var hidebtn=$('#hide-'+domid);
-       if (plugin.visible()) {
-           hidebtn.show();
-           showbtn.hide();
-       } else {
-           hidebtn.hide();
-           showbtn.show();
-       }
-       plugin.store_status(domid);
+       if (status=="true")     { plugindiv.slideDown(); hidebtn.show(); showbtn.hide(); }
+       else                    { plugindiv.slideUp();   hidebtn.hide(); showbtn.show(); }
+       plugin.store_status(domid,status);
     },
-    // 'target' is retrieved from storage so essentially a string 'true' or 'false'
-    set_visible : function (domid, target) {
-       var plugin=$('#'+domid);
-       if (plugin.visible()!=target) {
-           if (debug) console.log('set_visible: toggling ' + domid);
-           plugin.toggle (domid);
-       }
+    set_from_saved_status : function (domid) {
+       var previous_status=plugin.retrieve_last_status (domid);
+       if (plugin.debug) console.log("restoring initial status for domid " + domid + " -> " + previous_status);
+       plugin.set_toggle_status (domid,previous_status);
     },
     // triggered upon $(document).ready
-    init_all_plugins: function() {
+    init_all_plugins : function() {
+       // plugins marked as persistent start with all 3 parts turned off
+       // let us first make sure the right parts are turned on 
+       $('.persistent-toggle').each(function() {
+           var domid=this.id.replace('complete-','');
+           plugin.set_from_saved_status(domid);
+       });
+       // program the hide buttons so they do the right thing
        $('.plugin-hide').each(function() {
            $(this).click(function () { 
-               var plugin='#'+this.id.replace('hide-',''); 
-               var show='#'+this.id.replace('hide-','show-'); 
-               $(plugin).slideUp(); $(show).show(); $(this).hide();});
-       });
+               var domid=this.id.replace('hide-','');
+               plugin.set_toggle_status(domid,"false");
+           })});
+       // same for show buttons
        $('.plugin-show').each(function() {
            $(this).click(function () { 
-               var plugin='#'+this.id.replace('show-',''); 
-               var hide='#'+this.id.replace('show-','hide-'); 
-               $(plugin).slideDown(); $(hide).show(); $(this).hide();});
-       });
+               var domid=this.id.replace('show-','');
+               plugin.set_toggle_status(domid,"true");
+           })});
+       // arm tooltips
        $('.plugin-tooltip').each(function(){ $(this).tooltip({'selector':'','placement':'right'}); });
     },
-} // global unfold
+} // global var plugin
 
 /* upon document completion, we locate all the hide and show areas, 
  * and configure their behaviour 
index 4fc946a..9189e71 100644 (file)
@@ -17,7 +17,7 @@ from unfold.prelude import Prelude
 
 DEBUG= False
 #DEBUG= [ 'SimpleList' ]
-#DEBUG=True
+DEBUG=True
 
 # decorator to deflect calls on Plugin to its Prelude through self.page.prelude
 def to_prelude (method):
@@ -47,15 +47,15 @@ class Plugin:
     #            (not quite sure what this was for)
     # . togglable: whether it can be turned on and off by clicking on the title (like PleKitToggle)
     # . toggled:   whether the plugin should startup open/shown or closed/hidden
-    #### xxx NOTE : pending move towards a more elaborate mode for 'toggled'
-    # . toggled: if togglable, what's the initial status; possible values are
-    #    .. True   : start up open/hidden
-    #    .. False  : start up closed/shown
-    #    .. 'last' : start up as it was the last time that browser showed it (based on 'domid')
-    #    .. None   : if not passed to __init__ at all, then the DefaultTaggled() method is called
-    #    ..        : anything else, defaults to True
-    #### xxx NOTE : pending move towards a more elaborate mode for 'toggled'
-    # 
+    #              possible values are
+    #   .. True         : start up open/hidden
+    #   .. False        : start up closed/shown
+    #   .. 'persistent' : start up as it was the last time that browser showed it (based on 'domid')
+    #                NOTE that it is required for you to set a domid if you want to use persistent mode
+    #                     since domid is the key for storing that data in the browser storage space
+    #   .. None         : if not passed to __init__ at all, then the default_toggled() method is called
+    #   ..              : anything else, defaults to True
+    #
     #### internal data
     # . domid: created internally, but can be set at creation time if needed
     #          useful for hand-made css, or for selecting an active plugin in a composite
@@ -66,7 +66,7 @@ class Plugin:
     # which will result in 'foo' being accessible to the template engine
     # 
     def __init__ (self, page, title, domid=None,
-                  visible=True, togglable=True, toggled=True, **settings):
+                  visible=True, togglable=True, toggled=None, **settings):
         self.page = page
         self.title=title
         # callers can provide their domid for css'ing 
@@ -76,7 +76,8 @@ class Plugin:
         self.plugin_classname=self._js_classname()
         self.visible=visible
         self.togglable=togglable
-        self.toggled=toggled
+        if toggled is not None: self.toggled=toggled
+        else:                   self.toggled=self.default_toggled()
         # what comes from subclasses
         for (k,v) in settings.iteritems():
             setattr(self,k,v)
@@ -154,8 +155,20 @@ class Plugin:
         # need_spin is used in plugin.html
         self.need_spin=self.start_with_spin()
         env.update(self.__dict__)
+        # translate high-level 'toggled' into 4 different booleans
+        print "domid",self.domid,"toggled",self.toggled
+        if self.toggled=='persistent':
+            # start with everything turned off and let the js callback do its job
+            env.update({'persistent_toggle':True,'display_hide_button':False,'display_show_button':False,'display_body':False})
+        elif self.toggled==False:
+            env.update({'persistent_toggle':False,'display_hide_button':False,'display_show_button':True,'display_body':False})
+        else:
+            env.update({'persistent_toggle':False,'display_hide_button':True,'display_show_button':False,'display_body':True})
         if self.need_debug(): 
             print "rendering plugin.html with env keys %s"%env.keys()
+            print "rendering plugin.html with env"
+            for (k,v) in env.items(): 
+                if "display" in k or "persistent" in k: print k,'->',v
         result = render_to_string ('plugin.html',env)
 
         # export this only for relevant plugins
@@ -238,6 +251,8 @@ class Plugin:
     def template_file (self):           return "undefined_template"
     def template_env (self, request):   return {}
 
+    def default_toggled (self):         return 'persistent'
+
 #    # tell the framework about requirements (for the document <header>)
 #    # the notion of 'Media' in django provides for medium-dependant
 #    # selection of css files
index 7dfbfe2..49d0560 100644 (file)
@@ -1,14 +1,14 @@
 {% if visible %}
-<div class='plugin-toggle{% if need_spin %} need-spin{% endif %}' id='complete-{{ domid }}'>
+<div id='complete-{{ domid }}' class='plugin-toggle{% if need_spin %} need-spin{% endif %}{% if persistent_toggle %} persistent-toggle{% endif %}'>
 {% if togglable %}
-<h4 id='show-{{ domid }}' class='plugin-show'{% if toggled %} style='display:none;'{% endif %}><i class="icon-hand-right"></i>
+<h4 id='show-{{ domid }}' class='plugin-show'{% if not display_show_button %} style='display:none;'{% endif %}><i class="icon-hand-right"></i>
 <a href='#' class='plugin-tooltip' data-toggle='tooltip' data-original-title='Show plugin "{{ title }}" ({{ classname }})'>{{ title }}</a></h4>
-<h4 id='hide-{{ domid }}' class='plugin-hide'{% if not toggled %} style='display:none;'{% endif %}><i class="icon-hand-down"></i>
+<h4 id='hide-{{ domid }}' class='plugin-hide'{% if not display_hide_button %} style='display:none;'{% endif %}><i class="icon-hand-down"></i>
 <a href='#' class='plugin-tooltip' data-toggle='tooltip' data-original-title='Hide plugin "{{ title }}" ({{ classname }})'>{{ title }}</a></h4>
 {% endif %}{# togglable #}
 {% endif %}{# visible #}
 
-<div class='plugin {{ classname }}' id='{{ domid }}'{% if not toggled %} style='display:none;'{% endif %}>
+<div class='plugin {{ classname }}' id='{{ domid }}'{% if not display_body %} style='display:none;'{% endif %}>
 {{ plugin_content|safe }}
 </div>{# plugin #}