Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Plone Interactivity

1,284 views

Published on

Using KSS and jQuery to extend your Plone site.

Published in: Technology
  • Be the first to comment

Plone Interactivity

  1. 1. Adding Interactivity to your Plone Site
  2. 2. Me
  3. 3. Me • Eric Steele
  4. 4. Me • Eric Steele • Programmer @ WebLion
  5. 5. Me • Eric Steele • Programmer @ WebLion • Plone Products
  6. 6. Me • Eric Steele • Programmer @ WebLion • Plone Products • Faculty/Staff Directory
  7. 7. Me • Eric Steele • Programmer @ WebLion • Plone Products • Faculty/Staff Directory • GloWorm
  8. 8. Me • Eric Steele • Programmer @ WebLion • Plone Products • Faculty/Staff Directory • GloWorm • Plone 4 release manager
  9. 9. Adding Interactivity to your Plone Site
  10. 10. or...
  11. 11. I Suck at JavaScript... and So Can You
  12. 12. I Suck at JavaScript... and So Can You ~
  13. 13. I Suck at JavaScript... and So Can You ~ A half-assed guide to interactive JavaScript
  14. 14. The Stuff
  15. 15. The Stuff • The Boring Stuff • Resources
  16. 16. The Stuff • The Boring Stuff • The Fun Stuff • Resources • KSS • jQuery
  17. 17. Resources
  18. 18. Resources • JavaScript • CSS • KSS
  19. 19. Including JavaScripts <tal:block metal:fill-slot="javascript_head_slot"> <script type="text/javascript" src="myscript.js" /> </tal:block>
  20. 20. Including JavaScripts <tal:block metal:fill-slot="javascript_head_slot"> <script type="text/javascript" src="myscript.js" /> </tal:block> • Only need script on one page/template
  21. 21. Including JavaScripts <tal:block metal:fill-slot="javascript_head_slot"> <script type="text/javascript" src="myscript.js" /> </tal:block> • Only need script on one page/template • Performance isn’t an issue
  22. 22. Resource Registries
  23. 23. Resource Registries
  24. 24. Resource Registries • Control inclusion, order
  25. 25. Resource Registries • Control inclusion, order • Automatic merging, compression
  26. 26. Resource Registries • Control inclusion, order • Automatic merging, compression • Improved cacheability
  27. 27. Generic Setup jsregistry.xml <?xml version="1.0"?> <object name="portal_javascripts"> <javascript cacheable="True" compression="safe" cookable="True" enabled="True" expression="" id="myscripts.js" inline="False" insert-after="dropdown.js"/> </object>
  28. 28. External Scripts
  29. 29. External Scripts <javascript ... id="http://ajax.googleapis.com/ ajax/libs/jquery/1.2.6/jquery.min.js" ... />
  30. 30. External Scripts <javascript ... id="http://ajax.googleapis.com/ ajax/libs/jquery/1.2.6/jquery.min.js" ... /> • New in Plone 3.3
  31. 31. External Scripts <javascript ... id="http://ajax.googleapis.com/ ajax/libs/jquery/1.2.6/jquery.min.js" ... /> • New in Plone 3.3 • Include JavaScript from external sources
  32. 32. Google AJAX Libraries
  33. 33. Google AJAX Libraries http://code.google.com/apis/ajaxlibs/
  34. 34. Google AJAX Libraries http://code.google.com/apis/ajaxlibs/ • jQuery • Dojo • jQuery UI • SWFObjectNew • Prototype • Yahoo! User Interface Library (YUI) • script.aculo.us • MooTools
  35. 35. Browser Resources
  36. 36. Browser Resources • Component Architecture (Zope 3) way of defining resources
  37. 37. Browser Resources
  38. 38. Browser Resources <browser:resource name="myscript.js" image="myscript.js" />
  39. 39. Browser Resources <browser:resource name="myscript.js" image="myscript.js" /> http://myplonesite/++resource++myscript.js
  40. 40. Browser Resources <?xml version="1.0"?> jsregistry.xml <object name="portal_javascripts"> <javascript cacheable="True" compression="safe" cookable="True" enabled="True" expression="" id="++resource++myscript.js" inline="False" insert-after="dropdown.js"/> </object>
  41. 41. Browser Resources
  42. 42. Browser Resources <browser:resource name="myscript.js" image="myscript.js" for="..interfaces.IMyCustomType” />
  43. 43. Browser Resources <browser:resource name="myscript.js" image="myscript.js" for="..interfaces.IMyCustomType” /> <browser:resource name="myscript.js" image="myscript.js" layer="..interfaces.IMySkinLayer” />
  44. 44. Browser Resources
  45. 45. Browser Resources <browser:resourceDirectory name="myResources" directory="stuff" />
  46. 46. Browser Resources <browser:resourceDirectory name="myResources" directory="stuff" /> http://myplonesite/++resource++myResources/ checkout.png
  47. 47. JavaScript Libraries
  48. 48. A JavaScript library is a library of pre-written JavaScript controls which allow for easier development of JavaScript-based applications, especially for AJAX and other web-centric technologies. http://en.wikipedia.org/wiki/JavaScript_library
  49. 49. Why?
  50. 50. Why? • Save time
  51. 51. Why? • Save time • Reuse existing code
  52. 52. Why? • Save time • Reuse existing code • You don’t need to be an expert
  53. 53. Why? • Save time • Reuse existing code • You don’t need to be an expert • Browser “quirks”
  54. 54. Two Types • Easy • “Right”
  55. 55. KSS
  56. 56. KSS • “Kinetic Style Sheets” • JavaScript/AJAX framework • Declare behaviors using CSS format • Built into Plone 3.0+ • Also works with Grok, Pylons, Django
  57. 57. KSS Rules #mykssbutton:click { action-client: alert; alert-message: ‘Hello World!’; }
  58. 58. KSS Rules CSS Selector #mykssbutton:click { action-client: alert; alert-message: ‘Hello World!’; }
  59. 59. KSS Rules Action Type #mykssbutton:click { action-client: alert; alert-message: ‘Hello World!’; }
  60. 60. KSS Rules Action #mykssbutton:click { action-client: alert; alert-message: ‘Hello World!’; }
  61. 61. KSS Rules Action Parameter #mykssbutton:click { action-client: alert; alert-message: ‘Hello World!’; } name value
  62. 62. KSS Rules evt-click-preventdefault: True;
  63. 63. KSS Rules #mykssbutton:click { evt-click-preventdefault: True; action-client: alert; alert-message: ‘Hello World!’; } <a href=”front-page” id=”mykssbutton”>Click me! </a>
  64. 64. `
  65. 65. Client Actions
  66. 66. Client Actions • alert
  67. 67. Client Actions • alert • addClass / removeClass / toggleClass
  68. 68. Client Actions • alert • addClass / removeClass / toggleClass • setAttribute
  69. 69. Client Actions • alert • addClass / removeClass / toggleClass • setAttribute • setStyle
  70. 70. Client Actions • alert • addClass / removeClass / toggleClass • setAttribute • setStyle • replaceInnerHTML
  71. 71. Client Actions • alert • addClass / removeClass / toggleClass • setAttribute • setStyle • replaceInnerHTML • log
  72. 72. Parameter Providers
  73. 73. Parameter Providers • nodeAttr
  74. 74. Parameter Providers • nodeAttr • nodeContent
  75. 75. Parameter Providers • nodeAttr • nodeContent • currentFormVar
  76. 76. Parameter Providers • nodeAttr • nodeContent • currentFormVar • formVar
  77. 77. Tying Them Together
  78. 78. Tying Them Together <form id="myForm"> <input name="color" /> <input type="submit" class="submit" /> </form> <div tal:define="color request/form/color|string:nothing;"> You chose <span id="selectedColor" tal:content="color"> </span>. </div>
  79. 79. Tying Them Together <form id="myForm"> <input name="color" /> <input type="submit" class="submit" /> </form> <div tal:define="color request/form/color|string:nothing;"> You chose <span id="selectedColor" tal:content="color"> </span>. </div> #myForm .submit:click { evt-click-preventdefault: True; action-client: replaceInnerHTML; replaceInnerHTML-kssSelector: '#selectedColor'; replaceInnerHTML-html: currentFormVar(color); }
  80. 80. Tying Them Together <form id="myForm"> <input name="color" /> <input type="submit" class="submit" /> </form> <div tal:define="color request/form/color|string:nothing;"> You chose <span id="selectedColor" tal:content="color"> </span>. </div> #myForm .submit:click { evt-click-preventdefault: True; action-client: replaceInnerHTML; replaceInnerHTML-kssSelector: '#selectedColor'; replaceInnerHTML-html: currentFormVar(color); }
  81. 81. Fallback
  82. 82. Server Actions
  83. 83. Server Actions #myForm .submit:click { evt-click-preventdefault: True; action-server: transformColor; transformColor-color: currentFormVar(color); }
  84. 84. Server Actions #myForm .submit:click { evt-click-preventdefault: True; action-server: transformColor; transformColor-color: currentFormVar(color); } transformColor.py from kss.core.ttwapi import (startKSSCommands, getKSSCommandSet, renderKSSCommands) startKSSCommands(context, context.REQUEST) uColor = color.upper() core = getKSSCommandSet('core') core.replaceInnerHTML('#selectedColor', uColor) return renderKSSCommands()
  85. 85. Server Actions #myForm .submit:click { evt-click-preventdefault: True; action-server: transformColor; transformColor-color: currentFormVar(color); } transformColor.py from kss.core.ttwapi import (startKSSCommands, getKSSCommandSet, renderKSSCommands) startKSSCommands(context, context.REQUEST) uColor = color.upper() core = getKSSCommandSet('core') core.replaceInnerHTML('#selectedColor', uColor) return renderKSSCommands()
  86. 86. Command Sets • Core • Zope • getCssSelector • refreshProvider • addClass • refreshViewlet • removeClass • Plone • issuePortalMessage • refreshPortlet
  87. 87. Registering KSS • portal_kss registry
  88. 88. kssregistry.xml <?xml version="1.0"?> <object name="portal_kss" meta_type="KSS Registry"> <kineticstylesheet cacheable="True" compression="safe" cookable="True" enabled="1" expression="" id="mykssrules.kss"/> </object>
  89. 89. Debugging KSS
  90. 90. Debugging KSS • Firebug
  91. 91. Debugging KSS • Firebug • Firebug
  92. 92. Debugging KSS • Firebug • Firebug • Firebug
  93. 93. Debugging KSS • Firebug • Firebug • Firebug • Or Firebug Lite (getfirebug.com/lite.html)
  94. 94. Debugging KSS • KSS fails silently • Turn on debugging in portal_javascript • Messages will appear in Firebug console
  95. 95. Debugging KSS
  96. 96. Debugging KSS • Firekiss http://kssproject.org/download/firekiss.xpi/
  97. 97. KSS Plugins • kss.plugin.cacheabilty • kss.plugin.jsmath • kss.plugin.cns • kss.plugin.timer • kss.plugin.fadeeffect • kss.plugin.yuidnd • kss.plugin.history
  98. 98. Documentation • http://kssproject.org/ • http://plone.org/events/regional/plone- symposium-2008/skinning-with-plone-3
  99. 99. KSS Recap • Simple, CSS-style syntax • JavaScript, without the JavaScript
  100. 100. But here’s the thing...
  101. 101. It’s not really the best solution
  102. 102. Huh?
  103. 103. WTF?
  104. 104. • It’s huge
  105. 105. • It’s huge • Lack of adoption
  106. 106. • It’s huge • Lack of adoption • Sparse documentation
  107. 107. • It’s huge • Lack of adoption • Sparse documentation • Will be dropped as a core component (at some point)
  108. 108. jQuery
  109. 109. jQuery
  110. 110. jQuery • DOM-focused
  111. 111. jQuery • DOM-focused • Simple syntax
  112. 112. jQuery • DOM-focused • Simple syntax • Extensible
  113. 113. jQuery • DOM-focused • Simple syntax • Extensible • 19K
  114. 114. jQuery • DOM-focused • Simple syntax • Extensible • 19K • Well-documented
  115. 115. Factory
  116. 116. Factory • jQuery() • $() • jq()
  117. 117. Selectors
  118. 118. Selectors • CSS
  119. 119. Selectors • CSS • Tag name: jq(‘p’)
  120. 120. Selectors • CSS • Tag name: jq(‘p’) • Id: jq(‘#itemId’)
  121. 121. Selectors • CSS • Tag name: jq(‘p’) • Id: jq(‘#itemId’) • Class: jq(‘.someClass’)
  122. 122. Selectors • CSS • Tag name: jq(‘p’) • Id: jq(‘#itemId’) • Class: jq(‘.someClass’) • XPath: jq(‘a[title]’)
  123. 123. Pseudo-Selectors
  124. 124. Pseudo-Selectors • :first and :last
  125. 125. Pseudo-Selectors • :first and :last • :not jq(‘#portal-column-content p:not(.discreet)’)
  126. 126. Pseudo-Selectors • :first and :last • :not jq(‘#portal-column-content p:not(.discreet)’) • :first-child, :nth-child, and :last-child jq(‘ul li:nth-child(2)’)
  127. 127. Pseudo-Selectors • :first and :last • :not jq(‘#portal-column-content p:not(.discreet)’) • :first-child, :nth-child, and :last-child jq(‘ul li:nth-child(2)’) • :even and :odd jq(‘#myTable tr:odd’)
  128. 128. Sets
  129. 129. Sets • “Implicit iteration”
  130. 130. Sets • “Implicit iteration” • jq(‘#myDiv’).hide()
  131. 131. Sets • “Implicit iteration” • jq(‘#myDiv’).hide() • jq(‘.someDivs’).hide()
  132. 132. Chaining
  133. 133. Chaining • Operations always return a result
  134. 134. Chaining • Operations always return a result • So instead of... obj.doSomething() obj.doSomethingElse(‘blah’)
  135. 135. Chaining • Operations always return a result • So instead of... obj.doSomething() obj.doSomethingElse(‘blah’) • We can write... jq(‘#myElement’).parent().addClass(‘blah’)
  136. 136. Chaining
  137. 137. Chaining • One one line... jq(‘#faq’).find(‘dd’).hide().end().find(‘dt’).click(function(){...});
  138. 138. Chaining • One one line... jq(‘#faq’).find(‘dd’).hide().end().find(‘dt’).click(function(){...}); • Or several... jq('#faq') // Find the element with id ‘faq’ .find('dd') // Get all dd elements within .hide() // Hide those elements .end() // Jump back to the ‘faq’ element .find('dt') // Find all dt elements within .click(function() {...}); // And assign an click event.
  139. 139. Events
  140. 140. Events function foo(){ alert(‘foo’); } window.onload = foo;
  141. 141. Events function foo(){ alert(‘foo’); } window.onload = foo; function bar(){ alert(‘bar’); } window.onload = bar;
  142. 142. Events function foo(){ alert(‘foo’); } window.onload = foo; function bar(){ alert(‘bar’); } window.onload = bar;
  143. 143. Events
  144. 144. Events jq(document).ready(function) { alert(‘bar’); });
  145. 145. Events jq(document).ready(function) { alert(‘foo’); }); jq(document).ready(function) { alert(‘bar’); });
  146. 146. Events jq(document).ready(function) { alert(‘foo’); jq(document).ready(function) { }); alert(‘baz’); jq(document).ready(function) { }); alert(‘bar’); });
  147. 147. Events jq(document).ready(function) { alert(‘foo’); jq(document).ready(function) { }); alert(‘baz’); jq(document).ready(function) { }); alert(‘bar’); jq(document).ready(function) { }); alert(‘blort’); });
  148. 148. Events jq(document).ready(function) { alert(‘foo’); jq(document).ready(function) { }); alert(‘baz’); jq(document).ready(function) { jq(document).ready(function) { }); alert(‘bar’); alert(‘smoo’); jq(document).ready(function) { }); }); alert(‘blort’); });
  149. 149. Events jq(document).ready(function) { alert(‘foo’); jq(document).ready(function) { }); alert(‘baz’); jq(document).ready(function) { jq(document).ready(function) { }); alert(‘bar’); alert(‘smoo’); jq(document).ready(function) { jq(document).ready(function) { }); }); alert(‘floob’); alert(‘blort’); }); });
  150. 150. Events #mykssbutton:click { evt-click-preventdefault: True; action-client: alert; alert-message: ‘Hello World!’; } <a href=”front-page” id=”mykssbutton”>Click me! </a>
  151. 151. Events jq(document).ready(function) { jq(‘#mykssbutton’).click(function(){ alert(‘Hello World!); }); }); <a href=”front-page” id=”mykssbutton”>Click me! </a>
  152. 152. Another Example jq(document).ready(function() { jq(‘a[@href$=”.pdf”]’).addclass(‘pdflink’); }); a.pdflink { background:url(‘pdficon.gif’) no-repeat; padding-left:25px; }
  153. 153. AJAX Calls
  154. 154. AJAX Calls #myForm .submit:click { evt-click-preventdefault: True; action-server: transformColor; transformColor-color: currentFormVar(color); }
  155. 155. AJAX Calls #myForm .submit:click { evt-click-preventdefault: True; action-server: transformColor; transformColor-color: currentFormVar(color); } from kss.core.ttwapi import (startKSSCommands, getKSSCommandSet, renderKSSCommands) startKSSCommands(context, context.REQUEST) uColor = color.upper() core = getKSSCommandSet('core') core.replaceInnerHTML('#selectedColor', uColor) return renderKSSCommands()
  156. 156. AJAX Calls jq_transformColor return color.upper() jq(document).ready(function(){ jq('#myForm').submit(function(){ var color = jq('input[name=color]').val(); jq('#selectedColor').load('jq_transformColor?color=' + color); return false; }); });
  157. 157. jQuery in Plone • Built into Plone 3.1+ • ‘jq’ instead of ‘$’ • Now use ‘jq’ method instead of ‘cssQuery’ or ‘registerPloneFunction’
  158. 158. Integrating jQuery Plugins http://plugins.jquery.com/
  159. 159. Integrating jQuery Plugins
  160. 160. Integrating jQuery Plugins • If the plugin uses ‘$’:
  161. 161. Integrating jQuery Plugins • If the plugin uses ‘$’: • Place it between jquery.js and jquery- integration.js <javascript ... insert-before="jquery-integration.js"/>
  162. 162. Integrating jQuery Plugins • If the plugin uses ‘$’: • Place it between jquery.js and jquery- integration.js <javascript ... insert-before="jquery-integration.js"/> • or wrap it { (function($) [your code here] })(jQuery);
  163. 163. Existing Behaviors
  164. 164. Collapsible Sections <dl class=”collapsible”> <dt class=”collapsibleHeader”> A Title </dt> <dd class=”collapsibleContent”> Your hidable content. </dd> </dl>
  165. 165. Collapsible Sections <dl class=”collapsible”> <dt class=”collapsibleHeader”> A Title </dt> <dd class=”collapsibleContent”> Your hidable content. </dd> </dl>
  166. 166. Dropdowns <dl class=”actionMenu” id=”aUniqueId”> <dt class=”actionMenuHeader”> <a href=”some_destination”>A Title</ a> </dt> <dd class=”actionMenuContent”> Your content </dd> </dl>
  167. 167. Dropdowns <dl class=”actionMenu” id=”aUniqueId”> <dt class=”actionMenuHeader”> <a href=”some_destination”>A Title</ a> </dt> <dd class=”actionMenuContent”> Your content </dd> </dl>
  168. 168. Sortable Tables <table class=”listing” id=”someId”> <thead> <tr> <th>Table header</th> </tr> </thead> <tbody> <tr> <td>Table cell 1</td> </tr> <tr> <td>Table cell 2</td> </tr> </tbody> </table>
  169. 169. Sortable Tables <table class=”listing” id=”someId”> <thead> <tr> <th>Table header</th> </tr> </thead> <tbody> <tr> <td>Table cell 1</td> </tr> <tr> <td>Table cell 2</td> </tr> </tbody> </table>
  170. 170. Sortable Tables <th class=”nosort”> Unsortable Column </th>
  171. 171. Sortable Tables <th class=”nosort”> Unsortable Column </th>
  172. 172. Products using jQuery
  173. 173. collective.flowplayer Turns code like: <a class="autoFlowPlayer" href="path/to/video-file.flv"> <img src="path/to/splashscreen.jpg" /> </a> into:
  174. 174. Deco
  175. 175. Deco
  176. 176. Others • Carousel • Plone Slimbox • FancyZoomView • FadingNavigation • plone.app.jqtools
  177. 177. plone.app.jqtools
  178. 178. plone.app.jqtools • Included in Plone 4
  179. 179. plone.app.jqtools • Included in Plone 4 • Yay SteveM!
  180. 180. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  181. 181. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  182. 182. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  183. 183. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  184. 184. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  185. 185. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  186. 186. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  187. 187. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  188. 188. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  189. 189. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  190. 190. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  191. 191. plone.app.jquerytools • Tabs • Tooltips • Overlay • Exposé • Scrollable • Flashembed
  192. 192. jQuery Documentation http://docs.jquery.com/
  193. 193. http://www.packtpub.com/jQuery/
  194. 194. Other Libraries • Yahoo User Interface (YUI) • extjs • MochiKit • MooTools • Dojo
  195. 195. Conclusions
  196. 196. • JavaScript novice? – Use KSS
  197. 197. • JavaScript novice? – Use KSS • Otherwise, use JQuery
  198. 198. Special thanks to... • David Glick http://wglick.org/jstalk.html • Joel Burton http://bit.ly/z1nLH
  199. 199. Questions?

×