I presented this lecture to the new SharePoint devs joining our team. As I take on the challenge of Surface v2 development, I felt the urge to share my knowledge of branding SharePoint portals with jQuery for the past 1 year.
3. What is jQuery? #lga{ height: 231px; } <img height="95" width="275" src="/logo2w.png" alt="Google"> What we see We generate HTML from server-side API
4. What is jQuery? What we want tosee We want a Client-Side API to manipulate generated content
5. What is jQuery? DOM Document Object Model What we want tosee We want a cross-browser framework to access DOM
6. What is jQuery? Paste code below to FireBug console, after jQuery-fying Google.com homepage jQuery("#lga").hover( function() { jQuery("#lgaimg").attr("src", "http://www.gravatar.com/avatar/6872bc097bdddbfec28a56f76d0569a7"); jQuery("#lgaimg").attr("width", "150"); jQuery("<div>Happy Birthday Zeddy</div>").insertAfter("#lgaimg"); }, function() { jQuery("#lgaimg").attr("src", "/intl/en_com/images/srpr/logo2w.png"); jQuery("#lgaimg").removeAttr("width"); jQuery("#lga div").remove(); });
7. What is jQuery? DOM Document Object Model What we want tosee cross-browser framework to access DOM ==
8. jQuery Setup The framework: http://jquery.com The jQuery-friendly browser: http://mozilla.com The DOM-inspector browser plugin: http://getfirebug.com Additional FireBug plugins: http://firequery.binaryage.com http://robertnyman.com/firefinder
9. jQuery for SharePoint Dev Use NotePad++ to open: .CSS & .JS in TEMPLATEAYOUTS .ASCX in TEMPLATEONTROLTEMPLATES Use FireBugconsole to test jQuery scripts Use FireBuginspector to edit CSS Copy the tested jQuery & CSS to NotePad++ Test in IE7+ and fix browser-compatibility issues
10. How to use jQuery Find the element the one(s) you think will help you achieve that magic look & feel Do stuff to it add hover effect, move position, replace the HTML tag with completely different tag(s), delete, animate, etc.
13. Most-used Selectors (“#ZCarousel”) selects element with id=ZCarousel (“.item”) selects element(s) with class=item (“#ZCarousel li div.item”) CSS-style selectors: select all <div> with class=item under <li> tag which is under ZCarousel element
14. Most-used Selectors (“#ZCarouselli:first”) selects the 1st <li> tag found under ZCarousel (“#ZCarouselli:last”) selects the last <li> tag found unerZCarousel (“#ZCarouselli:even”) (“#ZCarouselli:odd”) get all the even or odd <li> elements, useful for alternating effect
15. Most-used Selectors (“element [attribute=something]”) the example below grabs the 1st <tbody> emitted by the tag <asp:Calendar> the example below changes the Prev Month arrow emitted by the tag <asp:Calendar> vartbody= jQuery("#calendarArea table[title=Calendar] tbody:first"); // Change month arrows variconPrev = "<imgsrc='/_layouts/darkBlueArrow-Left.png' />"; varprevLink = jQuery("#calendarArea a[title='Go to the previous month']"); prevLink.html(iconPrev);
16. Most-used Selectors (“input[id$=‘txtCurrency1']”) element <input> with attribute id ends with ‘txtCurrency1’, eg. this ASP.NET tag: will generate this HTML: this jQuery will get that element’s value: <asp:TextBox ID="txtCurrency1" runat="server" /> <input type="text" value=“United Arab Emirates (AED)" id="ctl00_m_g_50b54854_4b09_4b72_a69d_6ded7f051845_ctl00_txtCurrency1" /> var curr1Pref = jQuery("input[id$=‘txtCurrency1']").val();
18. Most-used Methods .css(“style”, “value”) or use the map argument: .addClass(“redTheme”) .removeClass(“redTheme”) adds / removes class from element jQuery(this).css({ position: “absolute", top: “10px" left: “100px" });
19. Most-used Methods .hasClass(“certainClass”) check if element is using certainClass .is(“:visible”) if (!jQuery(this).hasClass("ui-accordion-content-active")) { spacer.insertAfter(jQuery(this)); } varleftPanel = jQuery("#s4-leftpanel"); if (leftPanel.length > 0 && leftPanel.is(":visible'"))
20. Most-used Methods Used to add horizontal scrollbar in Allitems.aspx page // If #s4-leftpanel is visible, make the table layout scrollable // so it doesn't fall to the bottom in IE8+, FF, Chrome varleftPanel = jQuery("#s4-leftpanel"); if (leftPanel.length > 0 && leftPanel.is(":visible'")) { // allow horizontal scrollbar on right column varrightCol = jQuery("#parentPlaceHolderMain"); rightCol.css("overflow-x", "auto"); if (jQuery.browser.msie && jQuery.browser.version < 8.0) { // only happens in IE 7 var height = rightCol.height(); rightCol.css("height", height + 30 + "px"); } }
21. Most-used Methods .text() gets/sets combined string of element .val() gets/sets values of form elements .hide() / .show() / .toggle() hide/show element. Use .toggle for toggling between hiding/showing var date = jQuery("input[id$='hiddenEventStartDate']").val();
22. Most-used Methods .attr() gets/sets attribute of element guess what the above does? jQuery("[id$='txtFirstName']").focus(function () { if (jQuery(this).val() == jQuery (this).attr("title")) jQuery (this).val(""); }) .blur(function () { if (jQuery(this).val() == "") jQuery(this).val(jQuery(this).attr("title")); }); Default value of field FirstNameis set in custom attribute Title (set via server-side, reading from resource). If you click on the field, the value is cleared, allowing you to type a value. When you move outside the field and no value is entered, a default value is set once again (Used for “Enter First Name here” helper)
23. Most-used Methods .clone() followed by .insertAfter() / .append() clone an element, then appends or insert it after another element guess what the above does? does .clone() persist element event-binding? var copy = tr.clone(); // Modifications copy.find("td.colNoOfShares > input").val(""); copy.find("td.colPricePerShare > input").val(""); copy.find("td.colAddRemoveButtons > a[title=delThis]").show(); tbody.append(copy);
24. Most-used Methods var copy = tr.clone(); // Modifications copy.find("td.colNoOfShares > input").val(""); copy.find("td.colPricePerShare > input").val(""); copy.find("td.colAddRemoveButtons > a[title=delThis]").show(); tbody.append(copy); Above code used to clone a row when “Add Stock” button is clicked
25. Most-used Methods .clone() only copies the HTML tag, does not copy events attached to the elements. See example for our Advanced Search below; after we clone the advanced search criteria row, we re-attach the event handlers to the cloned element var copy = jQuery(tr).clone(); // Modifications jQuery(copy).children("td.colWhereTheProperty").text(""); jQuery(copy).find("td.colAddRemoveButtons > a:eq(1)").show(); // show del button var selectors = jQuery(copy).find("div.selectorWrapper"); jQuery(selectors).each(function () { addClickHandler(this); … });
27. Most-used Events .hover() sets up on hover and on leave in one go jQuery("#ZCarousel").hover( function () { jQuery(“.divArrows”).show(); window.clearInterval(autoscroller_timer); }, function () { jQuery(“.divArrows”).hide(); setupAutoScrollerTimer(); });
28. Most-used Events .click() sets up on hover and on leave in one go guess what the above does? jQuery(“a#changeMonth”).click(function () { jQuery(monthFacadeText).text($(this).text()); jQuery("input[id$='hiddenTxtMonth']").val($(this).text()); jQuery (monthOptions).hide(); jQuery ("input[id$='btnChangeMonthYear']").trigger("click") });
29. Most-used Events jQuery(“a#changeMonth”).click(function () { jQuery(monthFacadeText).text($(this).text()); jQuery("input[id$='hiddenTxtMonth']").val($(this).text()); jQuery (monthOptions).hide(); jQuery ("input[id$='btnChangeMonthYear']").trigger("click") }); When “custom dropdown” Change Month is clicked: Set the month façade div to the selected month Set ASP.NET viewstate variable to the selected month Hide month scrollable div Trigger ASP.NET postback button with ID btnChangeMonthYear
31. How to Build a Carousel .animate() allows to animate an element style property (top, left, opacity, etc.)
32. How to Build a Carousel (1) Step 1: Output a series of <li> items to be carouseled: <divid="ZSlideShow"> <divid="container"> <ulid="carousel"> <asp:RepeaterID="carouselRepeater"runat="server"> <ItemTemplate> <li> <divclass="item"> <a href='<%# Eval("ReadMoreLink") %>'><imgsrc='<%# Eval("ImageUrl") %>' alt='<%# Eval("Title") %>'/></a> <a href='<%# Eval("ReadMoreLink") %>'><h3><%# Eval("Title") %></h3></a> <div class="description"> <%# Eval("Description")%> </div> <div class="readmore"> <a href='<%# Eval("ReadMoreLink") %>' class=“xButton"><%= ResourceReader.GetGlobal(“XWebParts", “XWebPart_ReadMore_Text")%></a> </div> </li> </ItemTemplate> </asp:Repeater> </ul> </div> <divid="prevButton"><ahref="javascript:carousel_prev();"><imgsrc="/_layouts/Images/WebParts.Ets/left_arrow.png"alt="Prev"/></a></div> <divid="nextButton"><ahref="javascript:carousel_next();"><imgsrc="/_layouts/Images/WebParts.Ets/right_arrow.png"alt="Prev"/></a></div> <asp:HiddenFieldID="hiddenIntervalTimeInSeconds"runat="server"/></div>
33. How to Build a Carousel (2) Step 2: Float items to the left & set viewport #ZSlideShowul#carousel { margin: 0; padding: 0; height: 226px; overflow: visible; position: relative; top: 0; } #ZSlideShowul#carouselli { list-style: noneoutsidenone; float: left; margin-right: 5px; height: 226px; width: 161px; } #ZSlideShow { width: 600px; background-color: #e9e7db; padding: 5px4px5px4px; display: block; overflow: hidden; position: relative; } #ZSlideShow#container { height: 226px; width: 600px; position: relative; overflow: hidden; } Viewport of 600px
34. How to Build a Carousel (3) Step 3: Set up helper CONSTANTS in .js var ITEM_WIDTH = 166; // 161 div + 5px margin var LEFT_START_OFFSET = -113; var LEFT_OPACITY_ITEM_INDEX; var RIGHT_OPACITY_ITEM_INDEX; var BACK_TO_START_LEFT_POS; var START_POS_AFTER_SLIDE; varMINIMUM_ITEMS_SCROLLABLE = 4; // only scroll if >= this number varoriginal_items; varitem_revolution_counter; // if < -(original_items.length), back to start position // if > (original_items.length), back to (start position + slide) varautoscroller_timer;
35. How to Build a Carousel (4) Step 4: Set up Carouse on when DOM is ready ` jQuery(document).ready(function() { var items = jQuery("#carousel > li"); original_items = items; // save for appending to create circular effect if (items.length >= MINIMUM_ITEMS_SCROLLABLE) { appendOriginalsToFront(); appendOriginalsToBack(); BACK_TO_START_LEFT_POS = -(original_items.length * ITEM_WIDTH) + LEFT_START_OFFSET; START_POS_AFTER_SLIDE = BACK_TO_START_LEFT_POS + ITEM_WIDTH; jQuery("#carousel").css("left", START_POS_AFTER_SLIDE + "px"); item_revolution_counter = 0; LEFT_OPACITY_ITEM_INDEX = original_items.length - 1; RIGHT_OPACITY_ITEM_INDEX = LEFT_OPACITY_ITEM_INDEX + MINIMUM_ITEMS_SCROLLABLE; makeEdgeItemsTransparent(); } // adjust the width according to no. of items varcarouselWidth = jQuery("#carousel > li").length * ITEM_WIDTH; jQuery("#carousel").css("width", carouselWidth + "px"); // setup hover for prev/next to show up, and pause auto-scrolling jQuery("#ZSlideShow").hover(function () { toggleButtons(); clearInterval(autoscroller_timer); }, function () { toggleButtons(); setupAutoScroller(); }); // setup auto-scroll setupAutoScroller(); });
37. How to Build a Carousel Visual logic: we are animating the Left property of the #carousel to slide left or right. The Viewport with overflow:hidden hides the out-of-view items Viewport of 600px We’re scrolling the Left property of #carousel
38. How to Build a Carousel (6) Step 6: Append items to front & back for smooth circular effect functionappendOriginalsToFront() { varfirstItem = jQuery("#carousel > li:first"); for (var i = 0; i < original_items.length; ++i) { var cloned = jQuery(original_items[i]).clone(); styleEtsButton_restoreHoverEffects(cloned); cloned.insertBefore(firstItem); } } functionappendOriginalsToBack() { varlastItem = jQuery("#carousel > li:last"); for (var i = original_items.length - 1; i >= 0; --i) { var cloned = jQuery(original_items[i]).clone(); styleEtsButton_restoreHoverEffects(cloned); cloned.insertAfter(lastItem); } }
39. How to Build a Carousel (7) Step 7: What happens when you click Next button functioncarousel_next() { var items = jQuery("#carousel > li"); if (items.length >= MINIMUM_ITEMS_SCROLLABLE) { ++item_revolution_counter; if (item_revolution_counter > original_items.length) { item_revolution_counter = 1; // back to 1st item -- circular effect jQuery("#carousel").css("left", START_POS_AFTER_SLIDE + "px"); LEFT_OPACITY_ITEM_INDEX = original_items.length - 1; RIGHT_OPACITY_ITEM_INDEX = LEFT_OPACITY_ITEM_INDEX + MINIMUM_ITEMS_SCROLLABLE; } makeEdgeItemsOpaque(); ++LEFT_OPACITY_ITEM_INDEX; ++RIGHT_OPACITY_ITEM_INDEX; makeEdgeItemsTransparent(); var carousel = jQuery("#carousel"); varnewLeft = carousel.position().left - ITEM_WIDTH; jQuery("#carousel").animate({ left: newLeft + "px" }, "slow"); } }
40. How to Build a Carousel (8) Step 8: What happens when you click Prev button functioncarousel_prev() { var items = jQuery("#carousel > li"); if (items.length >= MINIMUM_ITEMS_SCROLLABLE) { --item_revolution_counter; if (item_revolution_counter <= -original_items.length) { item_revolution_counter = 0; // back to 1st item -- circular effect jQuery("#carousel").css("left", BACK_TO_START_LEFT_POS + "px"); LEFT_OPACITY_ITEM_INDEX = original_items.length; RIGHT_OPACITY_ITEM_INDEX = LEFT_OPACITY_ITEM_INDEX + MINIMUM_ITEMS_SCROLLABLE; } makeEdgeItemsOpaque(); --LEFT_OPACITY_ITEM_INDEX; --RIGHT_OPACITY_ITEM_INDEX; makeEdgeItemsTransparent(); var carousel = jQuery("#carousel"); varnewLeft = carousel.position().left + ITEM_WIDTH; jQuery("#carousel").animate({ left: newLeft + "px" }, "slow");