Pragmatics of Declarative Ajax XTech 2007 May 15-18, Paris Dave Johnson CTO, Nitobi [email_address]
Agenda <ul><li>Who Am I </li></ul><ul><li>Rule of Least Power </li></ul><ul><li>Declarative Languages </li></ul><ul><ul><l...
Who Is this Guy? <ul><li>Enterprise Ajax book (Addison Wesley) </li></ul><ul><li>Nitobi Enterprise Ajax Podcast </li></ul>...
Anything Else? <ul><li>Nitobi CTO + Co-founder </li></ul><ul><li>Located in Vancouver, Canada </li></ul><ul><li>Declarativ...
 
Nitobi Clients
Agenda <ul><li>Who Is this Guy? </li></ul>http://flickr.com/photos/jjd/24164311/ ME THUNK HTML ROCZ!!!
The Rule of Least Power <ul><li>Tim Berners-Lee </li></ul><ul><li>Noah Mendelsohn  </li></ul><ul><li>www.w3.org/2001/tag/d...
Principle “ Powerful languages inhibit information reuse.”
Inhibiting Information Reuse <ul><li>Humans like complicated </li></ul><ul><li>Pen and paper or memory stick? </li></ul><u...
Good Practice “ Use the least powerful language suitable for expressing information, constraints or programs on the World ...
http://www.flickr.com/photos/doglotion/154496890/
http://www.flickr.com/photos/dpade1337/429996161/
WS-*???
Benefits of Less Power? <ul><li>More robust and secure </li></ul><ul><li>Easier for people to use </li></ul><ul><li>Theref...
110,000,000
http://flickr.com/photos/oceanyamaha/186146223/ DEKLARATIVE WUT???
Declarative What? <ul><li>It is about  what  not  how </li></ul><ul><li>There is no sign of an algorithm </li></ul><ul><li...
Declarative Languages <ul><li>HTML </li></ul><ul><li>XForms </li></ul><ul><li>SVG </li></ul><ul><li>MXML </li></ul><ul><li...
Ham and Cheese <ul><li>“ declarative” vs “imperative” </li></ul><ul><li>“ library” vs “roll your own” </li></ul>
 
http://www.flickr.com/photos/refractedmoments/399890975/
Computability <ul><li>But is the Jambon et Fromage Touring complete? </li></ul><ul><li>You can’t change the recipe </li></...
Pareto’s Principle <ul><li>Call it what you will </li></ul><ul><ul><li>80-20 rule </li></ul></ul><ul><ul><li>Law of the vi...
Design VS Program <ul><li>Declarative “design” gets us 80% </li></ul><ul><li>Programming gets the other 20% </li></ul><ul>...
Popular Tools <ul><li>HTML – how many HTML pages? </li></ul><ul><li>JSON – relatively new compared to <XML> </li></ul><ul>...
Not Just About XML <ul><li>Declarative does not have to be XML </li></ul><ul><li>Imperative languages can  look  declarati...
Layering Languages <ul><li>Languages get more simple as we share more information </li></ul><ul><li>Consider a factorial f...
Machine Code
Assembly <ul><li>main: </li></ul><ul><li>movl $5, %eax </li></ul><ul><li>movl $1, %ebx </li></ul><ul><li>L1: cmpl $0, %eax...
C++ <ul><li>int factorial(int n) { </li></ul><ul><li>if(n <= 1) return 1; </li></ul><ul><li>return n * factorial(n - 1); <...
Python <ul><li>fac = lambda n:[1,0][n>0] or fac(n-1)*n  </li></ul>
Still All Clearly Imperative <ul><li>Conditional statements </li></ul><ul><li>However, once you start using the factorial ...
Agenda I CULD DO ZAT http://flickr.com/photos/stevecaddy/474542238/
Declarative User Interface <ul><li>Who cares about calculating factorials </li></ul><ul><li>Power is in design </li></ul>
Declarative Maps?
In JavaScript <ul><li><script type=“text/javascript”> </li></ul><ul><li>gmap.init = function() { </li></ul><ul><li>var map...
In (X)HTML <ul><li><g:map id=&quot;map&quot; width=&quot;370px&quot; height=&quot;380px&quot; smallmapcontrol=&quot;true&q...
Same but Different new GLatLng(49.265788, -123.069877) <g:point lat=&quot;49.265788&quot; lng=&quot;-123.069877&quot; /> n...
Practical Differences <ul><li>Both could have auto-complete support </li></ul><ul><li>Designability and IDE support </li><...
The Bugaboo <ul><li>Imperative can be  nearly  as good as declaration </li></ul><ul><li>“ JavaScript objects need more tha...
<ul><li>var input = new Input(); </li></ul><ul><li>input.hint = “Please enter a number”; </li></ul><ul><li><input> </li></...
<ul><li>var input = new Input(); </li></ul><ul><li>input. setHint (“Please enter a number”); </li></ul><ul><li>Input.proto...
Benefits? <ul><li>Designable </li></ul><ul><ul><li>easy IDE tooling </li></ul></ul><ul><li>Declarative patterns </li></ul>...
Write Once, Deploy Anywhere
http://flickr.com/photos/elmyra/9335163/ WUT IZ ISNIDE?
Problems <ul><li>Firefox – served as HTML </li></ul><ul><ul><li>DOM traversal </li></ul></ul><ul><ul><li>Self closing tags...
Firefox HTML DOM Traversal <ul><li><div id=&quot;div1&quot;> </li></ul><ul><li><ntb:button id=&quot;button1&quot;>button</...
getElementsByTagNameNS <ul><li>ns.getElementsByTagNameNS = function(tag, np, context) { </li></ul><ul><li>context = contex...
Styling Namespaced Elements <ul><li>Internet Explorer </li></ul><ul><li>ntb:* { </li></ul><ul><li>display:none; </li></ul>...
Other Approaches <ul><li>Custom attribute </li></ul><ul><ul><li><div oatype=&quot;ntb:grid&quot; ... /> </li></ul></ul><ul...
Standards Approach <ul><li>Use HTML  role  attribute </li></ul><ul><li>Accessibility of Rich Internet Applications (ARIA) ...
W3C Accessibility <ul><li>tabindex=&quot;-1&quot; </li></ul><ul><li>role=&quot;wairole:checkbox&quot; </li></ul><ul><li>pr...
What are Others Doing? <ul><li>XML-Script </li></ul><ul><li>Dojo Toolkit </li></ul><ul><li>XForms </li></ul>
XML-Script <ul><li><script type=&quot;text/xml-script&quot;> </li></ul><ul><li><page xmlns=&quot;http://schemas.microsoft....
Dojo Toolkit <ul><li><BUTTON widgetId=&quot;helloButton&quot; dojoType=&quot;Button&quot;>Hello World!</BUTTON> </li></ul>...
XForms <ul><li><html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; </li></ul><ul><li>xmlns:f=&quot;http://www.w3.org/2002...
Summary <ul><li>Declarative is “least power” approach </li></ul><ul><li>Facilitates sharing of information </li></ul><ul><...
Q&A? Dave Johnson [email_address] http://blogs.nitobi.com/dave
Upcoming SlideShare
Loading in...5
×

Pragmatics of Declarative Ajax

2,148

Published on

Declarative Ajax

Published in: Business, Travel
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,148
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
72
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Transcript of "Pragmatics of Declarative Ajax"

    1. 1. Pragmatics of Declarative Ajax XTech 2007 May 15-18, Paris Dave Johnson CTO, Nitobi [email_address]
    2. 2. Agenda <ul><li>Who Am I </li></ul><ul><li>Rule of Least Power </li></ul><ul><li>Declarative Languages </li></ul><ul><ul><li>Programming Basics </li></ul></ul><ul><ul><li>Web User Interfaces </li></ul></ul><ul><ul><li>Common Problems </li></ul></ul><ul><li>Summary </li></ul>
    3. 3. Who Is this Guy? <ul><li>Enterprise Ajax book (Addison Wesley) </li></ul><ul><li>Nitobi Enterprise Ajax Podcast </li></ul><ul><li>http://blogs.nitobi.com/dave </li></ul>
    4. 4. Anything Else? <ul><li>Nitobi CTO + Co-founder </li></ul><ul><li>Located in Vancouver, Canada </li></ul><ul><li>Declarative Ajax user-interface components for the enterprise </li></ul>
    5. 6. Nitobi Clients
    6. 7. Agenda <ul><li>Who Is this Guy? </li></ul>http://flickr.com/photos/jjd/24164311/ ME THUNK HTML ROCZ!!!
    7. 8. The Rule of Least Power <ul><li>Tim Berners-Lee </li></ul><ul><li>Noah Mendelsohn </li></ul><ul><li>www.w3.org/2001/tag/doc/leastPower </li></ul>
    8. 9. Principle “ Powerful languages inhibit information reuse.”
    9. 10. Inhibiting Information Reuse <ul><li>Humans like complicated </li></ul><ul><li>Pen and paper or memory stick? </li></ul><ul><li>What does this have to do with the Web? </li></ul>
    10. 11. Good Practice “ Use the least powerful language suitable for expressing information, constraints or programs on the World Wide Web.”
    11. 12. http://www.flickr.com/photos/doglotion/154496890/
    12. 13. http://www.flickr.com/photos/dpade1337/429996161/
    13. 14. WS-*???
    14. 15. Benefits of Less Power? <ul><li>More robust and secure </li></ul><ul><li>Easier for people to use </li></ul><ul><li>Therefore, more people use them </li></ul><ul><li>Be mindful of the success of HTML </li></ul>
    15. 16. 110,000,000
    16. 17. http://flickr.com/photos/oceanyamaha/186146223/ DEKLARATIVE WUT???
    17. 18. Declarative What? <ul><li>It is about what not how </li></ul><ul><li>There is no sign of an algorithm </li></ul><ul><li>We are not talking functional languages </li></ul><ul><li>HTML – canonical declarative language </li></ul>
    18. 19. Declarative Languages <ul><li>HTML </li></ul><ul><li>XForms </li></ul><ul><li>SVG </li></ul><ul><li>MXML </li></ul><ul><li>XAML </li></ul><ul><li>JSON </li></ul>
    19. 20. Ham and Cheese <ul><li>“ declarative” vs “imperative” </li></ul><ul><li>“ library” vs “roll your own” </li></ul>
    20. 22. http://www.flickr.com/photos/refractedmoments/399890975/
    21. 23. Computability <ul><li>But is the Jambon et Fromage Touring complete? </li></ul><ul><li>You can’t change the recipe </li></ul><ul><li>If there is no way to specify what you want to do then how can you do it? </li></ul><ul><ul><li>Make the sandwich yourself </li></ul></ul><ul><ul><li>Bring your own mustard </li></ul></ul><ul><li>Why bother? </li></ul>
    22. 24. Pareto’s Principle <ul><li>Call it what you will </li></ul><ul><ul><li>80-20 rule </li></ul></ul><ul><ul><li>Law of the vital few </li></ul></ul><ul><ul><li>Principle of factor sparsity </li></ul></ul><ul><ul><li>90-10 rule in software engineering </li></ul></ul><ul><li>Declarative gets you most of the way! </li></ul>
    23. 25. Design VS Program <ul><li>Declarative “design” gets us 80% </li></ul><ul><li>Programming gets the other 20% </li></ul><ul><li>One of two evils </li></ul><ul><ul><li>Easy to design </li></ul></ul><ul><ul><li>Easy to program </li></ul></ul>
    24. 26. Popular Tools <ul><li>HTML – how many HTML pages? </li></ul><ul><li>JSON – relatively new compared to <XML> </li></ul><ul><li>Microformats – hCard </li></ul><ul><li>Twitter – how many messages? </li></ul><ul><ul><li>Twitter vision L:Paris </li></ul></ul>
    25. 27. Not Just About XML <ul><li>Declarative does not have to be XML </li></ul><ul><li>Imperative languages can look declarative </li></ul><ul><ul><li>Using imperative language to encapsulate non-declarative ideas </li></ul></ul><ul><li>You don’t have to bake the bread for your sandwich … nor mill the grain </li></ul>
    26. 28. Layering Languages <ul><li>Languages get more simple as we share more information </li></ul><ul><li>Consider a factorial function in a few different languages? </li></ul>
    27. 29. Machine Code
    28. 30. Assembly <ul><li>main: </li></ul><ul><li>movl $5, %eax </li></ul><ul><li>movl $1, %ebx </li></ul><ul><li>L1: cmpl $0, %eax </li></ul><ul><li>je L2 </li></ul><ul><li>imull %eax, %ebx </li></ul><ul><li>decl %eax </li></ul><ul><li>jmp L1 </li></ul><ul><li>L2: ret </li></ul>
    29. 31. C++ <ul><li>int factorial(int n) { </li></ul><ul><li>if(n <= 1) return 1; </li></ul><ul><li>return n * factorial(n - 1); </li></ul><ul><li>} </li></ul>
    30. 32. Python <ul><li>fac = lambda n:[1,0][n>0] or fac(n-1)*n </li></ul>
    31. 33. Still All Clearly Imperative <ul><li>Conditional statements </li></ul><ul><li>However, once you start using the factorial function it appears declarative </li></ul>
    32. 34. Agenda I CULD DO ZAT http://flickr.com/photos/stevecaddy/474542238/
    33. 35. Declarative User Interface <ul><li>Who cares about calculating factorials </li></ul><ul><li>Power is in design </li></ul>
    34. 36. Declarative Maps?
    35. 37. In JavaScript <ul><li><script type=“text/javascript”> </li></ul><ul><li>gmap.init = function() { </li></ul><ul><li>var map = new GMap2(document.getElementById(&quot;map&quot;)); </li></ul><ul><li>map.setCenter(new GLatLng(49.290327, -123.11348), 12); </li></ul><ul><li>var polyline = new GPolyline([ </li></ul><ul><li>new GLatLng(49.265788, -123.069877), </li></ul><ul><li>new GLatLng(49.276988, -123.069534), </li></ul><ul><li>new GLatLng(49.276988, -123.099746), </li></ul><ul><li>new GLatLng(49.278108, -123.112106), </li></ul><ul><li>new GLatLng(49.2949043, -123.136825)], </li></ul><ul><li>&quot;#ff0000&quot;, 10); </li></ul><ul><li>map.addOverlay(polyline); </li></ul><ul><li>} </li></ul><ul><li>window.onload = gmap.init; </li></ul><ul><li></script> </li></ul>
    36. 38. In (X)HTML <ul><li><g:map id=&quot;map&quot; width=&quot;370px&quot; height=&quot;380px&quot; smallmapcontrol=&quot;true&quot; maptypecontrol=&quot;true&quot;> </li></ul><ul><li><g:center zoom=&quot;14&quot;> </li></ul><ul><li><g:point lat=&quot;49.2853&quot; lng=&quot;-123.11348&quot;></g:point> </li></ul><ul><li></g:center> </li></ul><ul><li><g:polyline color=&quot;#FF0000&quot; size=&quot;10&quot;> </li></ul><ul><li><g:point lat=&quot;49.265788&quot; lng=&quot;-123.069877&quot;></g:point> </li></ul><ul><li><g:point lat=&quot;49.276988&quot; lng=&quot;-123.069534&quot;></g:point> </li></ul><ul><li><g:point lat=&quot;49.276988&quot; lng=&quot;-123.099746&quot;></g:point> </li></ul><ul><li><g:point lat=&quot;49.278108&quot; lng=&quot;-123.112106&quot;></g:point> </li></ul><ul><li><g:point lat=&quot;49.294904&quot; lng=&quot;-123.136825&quot;></g:point> </li></ul><ul><li></g:polyline> </li></ul><ul><li></g:map> </li></ul>
    37. 39. Same but Different new GLatLng(49.265788, -123.069877) <g:point lat=&quot;49.265788&quot; lng=&quot;-123.069877&quot; /> new GLatLng( -123.069877 , 49.265788 ) <g:point lng=&quot; -123.069877 &quot; lat=&quot; 49.265788 &quot; />
    38. 40. Practical Differences <ul><li>Both could have auto-complete support </li></ul><ul><li>Designability and IDE support </li></ul><ul><li>HTML writer support on servers </li></ul><ul><li>Order matters … to a less degree in XML </li></ul><ul><li>Declarative can be less code </li></ul><ul><li>People don’t like JavaScript </li></ul><ul><li>Remember, HTML is a success for a reason </li></ul>
    39. 41. The Bugaboo <ul><li>Imperative can be nearly as good as declaration </li></ul><ul><li>“ JavaScript objects need more than just setting properties” </li></ul>
    40. 42. <ul><li>var input = new Input(); </li></ul><ul><li>input.hint = “Please enter a number”; </li></ul><ul><li><input> </li></ul><ul><ul><li><hint>Please enter a number</hint> </li></ul></ul><ul><li></input> </li></ul>
    41. 43. <ul><li>var input = new Input(); </li></ul><ul><li>input. setHint (“Please enter a number”); </li></ul><ul><li>Input.prototype.setHint = function() { </li></ul><ul><li>// setup any event hooks etc… </li></ul><ul><li>} </li></ul>
    42. 44. Benefits? <ul><li>Designable </li></ul><ul><ul><li>easy IDE tooling </li></ul></ul><ul><li>Declarative patterns </li></ul><ul><ul><li>succinct, reproducible solutions </li></ul></ul><ul><li>Rich semantics </li></ul><ul><ul><li>frameworks can easily read and interpret </li></ul></ul><ul><ul><li>server or client side interpretation </li></ul></ul>
    43. 45. Write Once, Deploy Anywhere
    44. 46. http://flickr.com/photos/elmyra/9335163/ WUT IZ ISNIDE?
    45. 47. Problems <ul><li>Firefox – served as HTML </li></ul><ul><ul><li>DOM traversal </li></ul></ul><ul><ul><li>Self closing tags </li></ul></ul><ul><li>Internet Explorer – can’t be served as XHTML </li></ul><ul><ul><li>DOM methods </li></ul></ul><ul><ul><li>Namespace </li></ul></ul><ul><li>Namespaces </li></ul><ul><ul><li>XHTML </li></ul></ul><ul><ul><li>CSS </li></ul></ul><ul><li>Validation </li></ul>
    46. 48. Firefox HTML DOM Traversal <ul><li><div id=&quot;div1&quot;> </li></ul><ul><li><ntb:button id=&quot;button1&quot;>button</ntb:button> </li></ul><ul><li><ntb:button id=&quot;button2&quot;>button 2</ntb:button> </li></ul><ul><li><ntb:panel id=&quot;panel1&quot;> </li></ul><ul><li><ntb:title id=&quot;title1&quot;> </li></ul><ul><li><div id=&quot;div2&quot;>panel title 1</div> </li></ul><ul><li></ntb:title> </li></ul><ul><li><ntb:contents id=&quot;contents1&quot;> </li></ul><ul><li><div id=&quot;div3&quot;>Contents div3</div> </li></ul><ul><li><div id=&quot;div4&quot;>Contents div4</div> </li></ul><ul><li></ntb:contents> </li></ul><ul><li></ntb:panel> </li></ul><ul><li></div> </li></ul>
    47. 49. getElementsByTagNameNS <ul><li>ns.getElementsByTagNameNS = function(tag, np, context) { </li></ul><ul><li>context = context || document; </li></ul><ul><li>var qname = np + &quot;:&quot; + tag; </li></ul><ul><li>if (ns.IE) qname = tag; </li></ul><ul><li>var elems = context.getElementsByTagName(qname); </li></ul><ul><li>if (ns.IE) { </li></ul><ul><li>realElems = []; </li></ul><ul><li>for (var i=0; i<elems.length; i++) { </li></ul><ul><li>if (elems[i].scopeName == ns) </li></ul><ul><li>realElems.push(elems[i]); </li></ul><ul><li>} </li></ul><ul><li>elems = realElems; </li></ul><ul><li>} </li></ul><ul><li>return elems; </li></ul><ul><li>} </li></ul>
    48. 50. Styling Namespaced Elements <ul><li>Internet Explorer </li></ul><ul><li>ntb:* { </li></ul><ul><li>display:none; </li></ul><ul><li>} </li></ul><ul><li>W3C </li></ul><ul><li>@namespace ntb &quot;http://www.nitobi.com&quot;; </li></ul><ul><li>ntb|* { </li></ul><ul><li>display:none; </li></ul><ul><li>} </li></ul>
    49. 51. Other Approaches <ul><li>Custom attribute </li></ul><ul><ul><li><div oatype=&quot;ntb:grid&quot; ... /> </li></ul></ul><ul><li>Microformats </li></ul><ul><ul><li><div class=“ntb_grid” … /> </li></ul></ul><ul><li>XBL / HTC </li></ul><ul><li>JSON </li></ul><ul><ul><li><div oatype=“{widget:’grid’,colums:[‘Col1’,Col2’]}” /> </li></ul></ul><ul><li>Many, many more </li></ul>
    50. 52. Standards Approach <ul><li>Use HTML role attribute </li></ul><ul><li>Accessibility of Rich Internet Applications (ARIA) as part of Web Accessibility Initiative </li></ul>
    51. 53. W3C Accessibility <ul><li>tabindex=&quot;-1&quot; </li></ul><ul><li>role=&quot;wairole:checkbox&quot; </li></ul><ul><li>property:checked=&quot;true“ </li></ul><ul><li><div tabindex=“-1” </li></ul><ul><li>role=“wairole:checkbox” </li></ul><ul><li>property:checked=“true”> </li></ul><ul><li></div> </li></ul>
    52. 54. What are Others Doing? <ul><li>XML-Script </li></ul><ul><li>Dojo Toolkit </li></ul><ul><li>XForms </li></ul>
    53. 55. XML-Script <ul><li><script type=&quot;text/xml-script&quot;> </li></ul><ul><li><page xmlns=&quot;http://schemas.microsoft.com/xml-script/2005&quot;> </li></ul><ul><li><components> </li></ul><ul><li><textbox id=&quot;searchText&quot; /> </li></ul><ul><li><button id=&quot;searchButton&quot;> </li></ul><ul><li><bindings> </li></ul><ul><li><binding property=&quot;enabled&quot; dataContext=&quot;searchText&quot; dataPath=&quot;text.length&quot; transform=&quot;NumberToBoolean&quot; /> </li></ul><ul><li></bindings> </li></ul><ul><li><click> </li></ul><ul><li><invokeMethod target=&quot;searchMethod&quot; method=&quot;invoke&quot; /> </li></ul><ul><li></click> </li></ul><ul><li></button> </li></ul><ul><li><serviceMethod id=&quot;searchMethod&quot;> </li></ul><ul><li><bindings> </li></ul><ul><li><binding property=&quot;parameters&quot; propertyKey=&quot;query&quot; dataContext=&quot;searchText&quot; dataPath=&quot;text&quot; /> </li></ul><ul><li></bindings> </li></ul><ul><li></serviceMethod> </li></ul><ul><li></components> </li></ul><ul><li></page> </li></ul><ul><li></script> </li></ul>
    54. 56. Dojo Toolkit <ul><li><BUTTON widgetId=&quot;helloButton&quot; dojoType=&quot;Button&quot;>Hello World!</BUTTON> </li></ul><ul><li><?xml:namespace prefix=dojo/> </li></ul><ul><li><dojo:widget></dojo:widget> </li></ul><ul><li><DIV dojoType=&quot;widget&quot;> </li></ul><ul><li><DIV class=dojo-widget></DIV> </li></ul><ul><li></DIV> </li></ul>
    55. 57. XForms <ul><li><html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; </li></ul><ul><li>xmlns:f=&quot;http://www.w3.org/2002/xforms&quot;> </li></ul><ul><li><head> </li></ul><ul><li><title>Search</title> </li></ul><ul><li><f:model> </li></ul><ul><li><f:submission action=&quot;http://example.com/search“ method=&quot;get&quot; id=&quot;s&quot;/> </li></ul><ul><li></f:model> </li></ul><ul><li></head> </li></ul><ul><li><body> </li></ul><ul><li><p> </li></ul><ul><li><f:input ref=&quot;q&quot;><f:label>Find</f:label></f:input> </li></ul><ul><li><f:submit submission=&quot;s&quot;><f:label>Go</f:label></f:submit> </li></ul><ul><li></p> </li></ul><ul><li></body> </li></ul><ul><li></html> </li></ul>
    56. 58. Summary <ul><li>Declarative is “least power” approach </li></ul><ul><li>Facilitates sharing of information </li></ul><ul><li>User interface designability and skinnability are paramount </li></ul>
    57. 59. Q&A? Dave Johnson [email_address] http://blogs.nitobi.com/dave
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×