jQuery Loves Developers - SWDC2009

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    1 Favorite

    jQuery Loves Developers - SWDC2009 - Presentation Transcript

    1. jQuery <3 Developers
    2. Hi, I'm Remy. Enjoys: JavaScript & dressing (sort of) like Mr T.
    3. Unobtrusive JavaScript
    4. Worst example <a href=\"javascript:window.open( 'help.html')\">Help</a>
    5. Just as bad <a href=\"#\" onclick=\"window.open( 'help.html')\">Help</a>
    6. \"Why? Doesn't everyone have JavaScript turned on?\"
    7. No!
    8. Corporate policies NoScript Firefox plugin No! Network script stripping proxies
    9. Corporate policies NoScript Firefox plugin No! Network script stripping proxies
    10. Unobtrusive way <a href=\"help.html\">Help</a> DOM scripting way
    11. Graceful Degradation ????? What's the difference ???? Progressive Enhancement
    12. GD vs. PE
    13. GD vs. PE • Old way • Top down • All singing all dancing first • Add fail cases • Run out of time, you're caught out
    14. GD vs. PE • Old way • New way • Top down • Bottom up • All singing all dancing • Layered development first • No environment • Add fail cases assumptions • Run out of time, you're • Works by default caught out
    15. \"Find something, do something to it\"
    16. Why jQuery?
    17. Why a DOM Library?
    18. • Cross browser quirks handled for you • DOM scripting made easy
    19. Less donkey work More problem solving
    20. Less donkey work More problem solving
    21. What's so special about jQuery?
    22. It's pretty popular...
    23. Community!
    24. Community
    25. APIs docs.jquery.com api.jquery.com visualjquery.com Community
    26. APIs Blogs, tutorials, screencasts, docs.jquery.com plugins, development sprints api.jquery.com visualjquery.com Community
    27. APIs Blogs, tutorials, screencasts, docs.jquery.com plugins, development sprints api.jquery.com visualjquery.com Google Groups jquery-en jquery-dev Community jquery-ui-en jquery-ui-dev jquery-a11y
    28. APIs Blogs, tutorials, screencasts, docs.jquery.com plugins, development sprints api.jquery.com visualjquery.com Google Groups jquery-en Twitter jquery-dev @jquery Community jquery-ui-en jquery-ui-dev @jquerysites @jqueryui jquery-a11y
    29. APIs Blogs, tutorials, screencasts, docs.jquery.com plugins, development sprints api.jquery.com visualjquery.com Google Groups jquery-en Twitter jquery-dev @jquery Community jquery-ui-en jquery-ui-dev @jquerysites @jqueryui jquery-a11y IRC channel freenode.net/#jquery
    30. What's in the box?
    31. • Selector engine: Sizzle • DOM manipulation • Events • Effects • Ajax • Utilities What's in the box?
    32. ew in N 1.3 Sizzlejs.com
    33. The bling function
    34. $ == jQuery
    35. $('div') == jQuery('div')
    36. $ • Selectors - CSS1, CSS2 and some CSS3
    37. $ • Selectors - CSS1, CSS2 and some CSS3 • DOM elements
    38. $ • Selectors - CSS1, CSS2 and some CSS3 • DOM elements • Raw HTML
    39. $ • Selectors - CSS1, CSS2 and some CSS3 • DOM elements • Raw HTML • \"Ready\" functions
    40. $('ul')
    41. $('ul') $(document.createElement('ul'))
    42. $('ul') $(document.createElement('ul')) $('<ul />') or $('<ul></ul>')
    43. jQuery(document).ready(fn) $(document).ready(fn) $(fn) jQuery(function ($) { // private instance of $ })
    44. jQuery(document).ready(fn) $(document).ready(fn) $(fn) jQuery(function ($) { // private instance of $ })
    45. jQuery(document).ready(fn) $(document).ready(fn) $(fn) jQuery(function ($) { // private instance of $ })
    46. jQuery(document).ready(fn) $(document).ready(fn) $(fn) jQuery(function ($) { // private instance of $ })
    47. Custom Selectors • :visible, :hidden • :first, :last • :even, :odd • :animated • :has
    48. $('li a') <ul> <li>1st</li> <li>2nd</li> <li><a href=\"#third\">3rd</a></li> <li>4th</li> </ul>
    49. $('li a') <ul> <li>1st</li> <li>2nd</li> <li><a href=\"#third\">3rd</a></li> <li>4th</li> </ul>
    50. $('li:has(a)') <ul> <li>1st</li> <li>2nd</li> <li><a href=\"#third\">3rd</a></li> <li>4th</li> </ul>
    51. $('li:has(a)') <ul> <li>1st</li> <li>2nd</li> <li><a href=\"#third\">3rd</a></li> <li>4th</li> </ul>
    52. ew in N 1.3 Selector Attributes • selector, e.g. $('li').find('a').selector == 'li a' • context
    53. Extending Selectors $.extend($.expr[':'], { visible : function(elem){ return elem.offsetWidth > 0 || elem.offsetHeight > 0; } });
    54. Extending Selectors $.extend($.expr[':'], { visible : function(elem){ return elem.offsetWidth > 0 || elem.offsetHeight > 0; } });
    55. Extending Selectors $.extend($.expr[':'], { visible : function(elem){ return elem.offsetWidth > 0 || elem.offsetHeight > 0; } });
    56. Extending Selectors $.extend($.expr[':'], { visible : function(elem){ return elem.offsetWidth > 0 || elem.offsetHeight > 0; } });
    57. Behind the Scenes • getElementById • getElementsByTagName • querySelectorAll • getElementsByClassName
    58. $ returns a new object
    59. ...that also has array like properties.
    60. >>> $('li') [li, li] >>> $('li')[0] <li> >>> $('li').length 2
    61. Does Selector Exist? if ( $(expr).length ) { // do stuff }
    62. Plugin Architecture $.fn.myPlugin = function () { return this.each(function () { // do stuff }); }
    63. Plugin Architecture $.fn.myPlugin = function () { return this.each(function () { // do stuff }); }
    64. Plugin Architecture $.fn.myPlugin = function () { return this.each(function () { // do stuff }); }
    65. Plugin Architecture $.fn.myPlugin = function () { return this.each(function () { // do stuff }); }
    66. Chaining
    67. Common $('a').addClass('ready').click(fn);
    68. Common $('a').addClass('ready').click(fn);
    69. Common $('a').addClass('ready').click(fn);
    70. Common $('a').addClass('ready').click(fn);
    71. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    72. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    73. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    74. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    75. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    76. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    77. One line! $img = $('<img />') .addClass('loading') .load(function () { $img.removeClass('loading'); }) .error(function () { $img.addClass('error') .attr('src', 'empty.gif'); }) .attr('src', 'somebigimage.jpg') .appendTo('body');
    78. DOM Navigation
    79. Finding
    80. $('li a') $('li').find('a') $('a').next() $('a').parent() $('a').parents('ul')
    81. <ul> $('li a') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    82. <ul> $('li a') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    83. <ul> $('li a').next() <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    84. <ul> $('li a').next() <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    85. <ul> $('li a').next().parent() <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    86. <ul> $('li a').next().parent() <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    87. <ul> $('li a').parents('ul') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    88. <ul> $('li a').parents('ul') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    89. ew in N 1.3 .closest('expr') <ul> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    90. ew in N 1.3 $('img').closest('ul') <ul> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    91. ew in N 1.3 $('img').closest('ul') <ul> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    92. ew in N 1.3 $('img').closest('ul') <ul> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> </ul>
    93. Filtering
    94. $('li').filter(':first') $('a').not(':has(span)') $('a').slice(1, 1)
    95. <li> $('li') <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    96. <li> $('li') <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    97. <li> $('li').filter(':has(img)') <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    98. <li> $('li').filter(':has(img)') <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    99. <li> $('li').not(':first') <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    100. <li> $('li').not(':first') <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    101. <li> $('li').slice(0, 2) <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    102. <li> $('li').slice(0, 2) <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <li> <a href=\"#second\">2nd</a> <img src=\"two.gif\"> </li> <li> <a href=\"#third\">3rd</a> </li>
    103. Manipulation
    104. • append, appendTo, prepend, prependTo • after, before, insertAfter, insertBefore • wrap, wrapAll, wrapInner • empty, remove • clone • html, text
    105. $('li').append('<span />') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li>
    106. $('li').append('<span />') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> <span></span> </li>
    107. $('li').prepend('<span />') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li>
    108. $('li').prepend('<span />') <li> <span></span> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li>
    109. $('#foo').prependTo('li') <li> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li> <img id=\"foo\" src=\"foo.gif\">
    110. $('#foo').prependTo('li') <li> <img id=\"foo\" src=\"foo.gif\"> <a href=\"#first\">1st</a> <img src=\"one.gif\"> </li>
    111. $('ul').wrap('<div />') <ul> <li><a href=\"#first\">1st</a></li> </ul> <ul> <li><a href=\"#second\">2nd</a></li> </ul>
    112. $('ul').wrap('<div />') <div> <ul> <li><a href=\"#first\">1st</a></li> </ul> </div> <div> <ul> <li><a href=\"#second\">2nd</a></li> </ul> </div>
    113. $('ul').wrapAll('<div />') <div> <ul> <li><a href=\"#first\">1st</a></li> </ul> <ul> <li><a href=\"#second\">2nd</a></li> </ul> </div>
    114. $('li').wrapInner('<em />') <ul> <li><em><a href=\"#first\">1st</a></ em></li> </ul> <ul> <li><em><a href=\"#second\">2nd</ a></em></li> </ul>
    115. Style Manipulation
    116. Key/Value Pair // get $('input').attr('title'); $('a').css('font-weight'); // set $('input').attr('title', 'Name'); $('a').css('font-weight', 'bold');
    117. Changing Multiples $('input').attr({ 'title' : 'Your username', 'value' : 'Enter your username' }); $('a').css({ 'font-weight' : 'bold', 'background-color' : '#c00' });
    118. $('a').attr({ class : 'home', href : '/home' }); <a href=\"/logout\" class=\"logout\">Go</a>
    119. $('a').attr({ class : 'home', href : '/home' }); <a href=\"/home\" class=\"home\">Go</a>
    120. Dimensions & Position
    121. • width, height • innerHeight, innerWidth • outerHeight, outerWidth (pass true to include margins) • scrollLeft, scrollTop • offset, position (includes margin)
    122. Events
    123. bind, trigger & unbind
    124. bind, trigger & unbind ...and .one(fn) (which unbinds on trigger)
    125. $('a').bind('click', function () { alert('you clicked'); return false; }).trigger('click');
    126. $('a').bind('click', function () { alert('you clicked'); return false; }).trigger('click');
    127. $('a').bind('click', function () { alert('you clicked'); return false; }).trigger('click');
    128. $('a').bind('click', function () { alert('you clicked'); return false; }).trigger('click');
    129. $('a').bind('click', function () { alert('you clicked'); return false; }).trigger('click');
    130. $('a').bind('click', function (event, msg) { alert('you clicked: ' + msg); return false; }).trigger('click', ['ok']);
    131. $('a').bind('click', function (event, msg) { alert('you clicked: ' + msg); return false; }).trigger('click', ['ok']);
    132. $('a').bind('click', function (event, msg) { alert('you clicked: ' + msg); return false; }).trigger('click', ['ok']);
    133. $('a').bind('click', function (event, msg) { alert('you clicked: ' + msg); return false; }).trigger('click', ['ok']);
    134. $('a').bind('click', function (event, msg) { alert('you clicked: ' + msg); return false; }).trigger('click', ['ok']);
    135. blur mousemove change * mouseout click mouseover dblclick mouseup error ready focus resize hover scroll keydown select keypress submit keyup toggle load unload mousedown
    136. triggerHandler(event, data)
    137. triggerHandler(event, data) Watch out: doesn't chain!
    138. Event object • preventDefault() • stopPropagation() • return false (preventDefault + stopPropagation) • stopImmediatePropagation() ew in N 1.3
    139. ew in N 1.3 Live Events
    140. $('.remove').live('click',function(){ $(this).closest('tr').remove(); });
    141. http://remysharp.com/demo/live.html
    142. http://remysharp.com/demo/live.html
    143. Live support • Supported: click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup • Not supported: blur, focus, mouseenter, mouseleave, change, submit
    144. Effects
    145. Built in Effects • show, hide, toggle • fadeIn, fadeOut, fadeTo • slideUp, slideDown, slideToggle • animate - roll your own!
    146. http://remysharp.com/demo/hide-with-margins.html
    147. http://remysharp.com/demo/hide-with-margins.html
    148. .animate(prop, speed, callback)
    149. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    150. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    151. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    152. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    153. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    154. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    155. $('#block').animate({ 'opacity' : 0.5, 'width' : '-=20px', 'height' : '-=20px', 'top' : (winHeight - 168) + 'px' }, 400, 'easeOutBounce').animate({ 'foo' : 1 // acts as a pause }, 500).animate({ 'left' : '150%' // fly off screen }, 500, function () { $(this).hide(); });
    156. http://remysharp.com/demo/animate.html
    157. http://remysharp.com/demo/animate.html
    158. Bespoke Steps $('div').queue(function () { $(this).removeClass('newcolor'); // pass back to sequence $(this).dequeue(); });
    159. Bespoke Steps $('div').queue(function () { $(this).removeClass('newcolor'); // pass back to sequence $(this).dequeue(); });
    160. Bespoke Steps $('div').queue(function () { $(this).removeClass('newcolor'); // pass back to sequence $(this).dequeue(); });
    161. ew in N 1.3 $.fx.off = true
    162. Enchantment
    163. Enchantment http://jqueryui.com/docs/Effects/Methods
    164. UI Effects Core • addClass, removeClass, toggleClass • show, hide, toggle • animate
    165. http://jqueryui.com/demos/addClass/default.html
    166. http://jqueryui.com/demos/addClass/default.html
    167. Ajax
    168. Über Easy Ajax $(expr).load - squirt into expr $('#info').load('info.html #links li');
    169. Über Easy Ajax $(expr).load - squirt into expr $('#info').load('info.html #links li');
    170. Über Easy Ajax $(expr).load - squirt into expr $('#info').load('info.html #links li');
    171. Über Easy Ajax $(expr).load - squirt into expr $('#info').load('info.html #links li');
    172. Über Easy Ajax $(expr).load - squirt into expr $('#info').load('info.html #links li');
    173. Ajax Shortcuts • $.get • $.post • $.getScript • $.getJSON
    174. $.ajax • Full control • Global setup available • Much easier to debug • http://docs.jquery.com/Ajax/ jQuery.ajax#options
    175. $.ajax({ url: 'http://www.twitter.com/ statuses/user_timeline/rem.json? callback=?', dataType: 'jsonp', cache: false, success: function(data) { // this == XMLHttpRequest object $('#status').html(data[0].text); }, error: function(xhr, status, e) { // debugging enabled console.log(arguments); } });
    176. $.ajax({ url: 'http://www.twitter.com/ statuses/user_timeline/rem.json? callback=?', dataType: 'jsonp', cache: false, success: function(data) { // this == XMLHttpRequest object $('#status').html(data[0].text); }, error: function(xhr, status, e) { // debugging enabled console.log(arguments); } });
    177. $.ajax({ url: 'http://www.twitter.com/ statuses/user_timeline/rem.json? callback=?', dataType: 'jsonp', cache: false, success: function(data) { // this == XMLHttpRequest object $('#status').html(data[0].text); }, error: function(xhr, status, e) { // debugging enabled console.log(arguments); } });
    178. $.ajax({ url: 'http://www.twitter.com/ statuses/user_timeline/rem.json? callback=?', dataType: 'jsonp', cache: false, success: function(data) { // this == XMLHttpRequest object $('#status').html(data[0].text); }, error: function(xhr, status, e) { // debugging enabled console.log(arguments); } });
    179. $.ajax({ url: 'http://www.twitter.com/ statuses/user_timeline/rem.json? callback=?', dataType: 'jsonp', cache: false, success: function(data) { // this == XMLHttpRequest object $('#status').html(data[0].text); }, error: function(xhr, status, e) { // debugging enabled console.log(arguments); } });
    180. Server Side Tip! // sent headers include: X-Requested-With = XMLHttpRequest
    181. Utilities
    182. Tests, Iterators & Operations • $.inArray, $.isFunction, $.isArray, • $.each, $.extend, $.grep, $.map • $.merge, $.unique, $.makeArray
    183. Good Guys Come Last 1. Include other library first (that uses $) 2. Then include jQuery, then: $.noConflict(); // or $j = $.noConflict();
    184. Sniffing
    185. Old Way • $.browser • $.browser.version
    186. ew in N 1.3 $.support
    187. ew in N 1.3 $.support boxModel leadingWhitespace opacity cssFloat noCloneEvent scriptEval hrefNormalized objectAll style htmlSerialize tbody
    188. Remy Sharp @rem remy@leftlogic.com http://remysharp.com http://jqueryfordesigners.com http://full-frontal.org P h o t o s by charliebrewer, manfrys, magw21, abbydonkrafts, nicora, leecullivan, jaako, thetruthabout, artisandhu, sundazed, otterfreak, frf_kmeron, mattlogelin, dandiffendale, mwagner, stanrandom, anniewong, legin, kerotab

    + Remy SharpRemy Sharp, 5 months ago

    custom

    1203 views, 1 favs, 0 embeds more stats

    Covering jQuery and the details behind the features more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 1203
      • 1203 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 1
    • Downloads 43
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories