最近在学《jQuery 基础教程》(第4版) ,Google 了一圈没找到完整的习题解答,所以放在这里作个参考。
Chapter 2 选择器 1.给位于嵌套列表第二个层次的所有 <li> 元素添加 special 类
1 $('li' ).children ().find ('li' ).addClass ('special' );
2.给位于表格第三列的所有单元格添加 year 类
1 $('tr' ).find ('td:eq(2)' ).addClass ('year' );
3.为表格中包含文本 Tragedy 的第一行添加 special 类
1 $('td:contains(\"Tragedy\")' ).first ().parent ().addClass ('special' );
4.(挑战 )选择包含链接(<a> 元素)的所有列表项(<li> 元素),为每个选中的列表项的同辈列表项元素添加 afterlink 类
1 $('a' ).parent ().nextAll ().addBack ().addClass ('afterlink' );
5.(挑战 )为与 .pdf 链接最接近的祖先元素 <ul> 添加 tragedy 类
1 $('a[href$=\"pdf\"]' ).closest ('ul' ).addClass ('tragedy' );
Chapter 3 事件 1.在 Charles Dickens 被单击时,应用 selected 样式
1 2 3 4 5 6 7 $('div.author' ).click (function ( ) { if ($(this ).hasClass ('selected' )) { $(this ).removeClass ('selected' ); } else { $(this ).addClass ('selected' ); } });
2.双击章节标题(h3)时,切换本章文字的可见性
1 2 3 $('h3.chapter-title' ).dblclick (function ( ) { $(this ).parent ().addClass ('hidden' ); });
3.当用户按下向右方向键时,切换到下一个 body 类,右方向键的键码是39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var bodyClasses = [ 'default' , 'narrow' , 'large' ]; $(document ).keyup (function (event ) { if (event.which === 39 ) { for (i = 0 ; i < 2 ; i++) { if ($('body' ).hasClass (bodyClasses[i])) { $('body' ).removeClass ().addClass (bodyClasses[i + 1 ]); break ; } } if (i == 2 ) { setBodyClass (bodyClasses[0 ]); } } });
上面这种写法比较“笨拙“。这里 有更灵巧的写法,妙用switch case语句。
4.(挑战 )使用 console.log() 函数记录在段落中移动的鼠标的坐标位置
1 2 3 $('p' ).mousemove (function (event ) { console .log (\"eventXY: (\" + event.pageX + \",\" + event.pageY + \")\"); });
5.(挑战 )使用 .mousedown() 和 .mouseup() 跟踪页面中的鼠标事件。如果鼠标按键在按下的地方被释放,则为所有段落添加 hidden 类。如果是在按下的地方之下被释放,删除所有段落的 hidden 类
1 2 3 4 5 6 7 8 9 10 11 12 13 var mouseDownX, mouseDownY;$(document ).mousedown (function (event ) { mouseDownX = event.pageX ; mouseDownY = event.pageY ; }); $(document ).mouseup (function (event ) { if (event.pageX === mouseDownX && event.pageY === mouseDownY) { $('p' ).addClass ('hidden' ); } else if (event.pageY > mouseDownY) { $('p' ).removeClass ('hidden' ); } });
Chapter 4 样式与动画 1.修改样式表,一开始先页面内容,当页面加载后,慢慢地淡入内容
1 $('#container' ).hide ().fadeIn ('slow' );
2.在鼠标悬停到段落上面时,给段落应用黄色背景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var oldBackgroundColor;$('div p' ).hover ( function ( ) { oldBackgroundColor = $(this ).css ('backgroundColor' ); $(this ).css ({ backgroundColor : 'yellow' }); }, function ( ) { $(this ).css ({ backgroundColor : oldBackgroundColor }); });
3.单击标题 <h2> 时将不透明度变为 25%,同时增加 20px 的左外边距,这两个效果完成后把讲话文本变成 50% 不透明度
1 2 3 4 5 6 7 8 9 10 11 12 $('h2' ).click (function ( ) { $(this ).animate ({ opacity : .25 , paddingLeft : '+=20px' }, 'slow' , function ( ) { $('div.speech' ).animate ({ opacity : .5 }, 'slow' ) }) });
4.按下方向键时,使样式转换器 #switcher向相应的方向平滑移动20像素。 注意:这里使用 .filter(':not(:animated)') 可以防止按键过快导致动画“堆积”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $(window ).keydown (function (event ) { var switcher = $('#switcher' ); switch (event.which ) { case 37 : switcher.css ('position' , 'relative' ).filter (':not(:animated)' ).animate ({ left : '-=20px' }, 'fast' ); break ; case 38 : switcher.css ('position' , 'relative' ).filter (':not(:animated)' ).animate ({ top : '-=20px' }, 'fast' ); break ; case 39 : switcher.css ('position' , 'relative' ).filter (':not(:animated)' ).animate ({ left : '+=20px' }, 'fast' ); break ; case 40 : switcher.css ('position' , 'relative' ).filter (':not(:animated)' ).animate ({ top : '+=20px' }, 'fast' ); break ; default : } });
Chapter 5 操作 DOM 1.修改添加 back to top 的代码,以便这些链接只从第四段后面才开始出现。
1 2 3 4 5 $('div.chapter p' ).each (function (index ) { if (index >= 3 ) { $(this ).after ($('<a href=\"#top\">back to top</a>' )); } });
2.在单击 back to top 链接时,为每个链接后面添加一个新段落,其中包含 you were here 字样
1 2 3 4 5 6 7 8 9 10 11 $('a[href*=\"#top\"]' ).click (function (event ) { var clickedLink = event.target ; $('.scrollLocationTip' ).remove (); $('<p class=\"scrollLocationTip\">you were here</p>' ).insertAfter (clickedLink); event.stopPropagation (); }); $('body' ).click (function ( ) { $('.scrollLocationTip' ).remove (); });
3.单击作者的名字时,把文本改为粗体(通过添加一个标签,而不是操作类或 CSS 属性) 4.(挑战 )在随后单击粗体作者名字时,之前添加的 <b> 元素(也就是在文本与正常文本之间切换)
1 2 3 4 5 6 7 8 9 10 $('#f-author' ).click (function ( ) { if ($(this ).children ('strong' ).length == 0 ) { $(this ).wrapInner ('<strong></strong>' ); } else { $(this ).children ('strong' ).contents ().unwrap ('<strong></strong>' ); } });
这两个练习还有另外一种写法 ,在两种状态之间“切换”可以使用 toggle() 方法来实现。
1 2 3 4 5 6 7 8 $('#f-author' ).toggle ( function ( ) { $(this ).wrapAll ('<b></b>' ); }, function ( ) { $(this ).unwrap () } );
5.(挑战 )为正文中的每个段落添加一个 inhabitants 类,但不能调用 addClass() 方法。确保不影响现有的类
1 2 3 4 5 6 7 8 9 $('.chapter p' ).each (function ( ) { if (!$(this ).hasClass ('inhabitants' )) { $(this ).attr ({ class : $(this ).attr ('class' ) + ' inhabitants' }); } });
Chapter 6 通过 Ajax 发送数据 1.页面加载后,把 exercises-content.html 的主体内容(body)提取到页面的内容区域
1 2 $('#dictionary' ).load ('exercises-content.html .letter' );
2.不要一次显示整个文档,为左侧的字母列表创建“提示条”,当用户鼠标放到字母上时从 exercises-content.html 中加载与该字母有关的内容
1 2 3 4 5 6 7 8 9 10 11 12 $('.letter' ).hover (function ( ) { $('#dictionary' ).load ('exercises-content.html #' + $(this ).attr ('id' )); }, function ( ) { $('#dictionary' ).html ('' ); });
3.为上面的页面加载添加错误处理功能,在页面的内容区显示错误消息。修改脚本,请求 does-not-exist.html 而不是 exercises-content.html,以测试错误处理功能。
1 2 3 4 5 6 7 8 9 10 11 $('.letter' ).hover (function ( ) { $('#dictionary' ).load ('does-not-exist.html #' + $(this ).attr ('id' ), function (response, status, xhr ) { if (status === 'error' ) { $('#dictionary' ).html ('错误:' + xhr.status ).append (xhr.responseText ); } else { $('#dictonary' ).html (xhr.responseText ); } }); }, function ( ) { $('#dictionary' ).html ('' ); });
4.页面加载后,向 GitHub 发出一个 JSONP 请求,取得某用户的代码库列表。把每个代码库的名称和 URL 插入到页面的内容区。例如 jQuery 项目代码库的 URL 是 https://api.github.com/users/jquery/repos
1 2 3 4 5 6 7 8 9 10 11 12 var repoURL = 'https://api.github.com/users/jquery/repos' ;$.getJSON (repoURL + '?callback=?' , function (response ) { var html = '' ; $.each (response.data , function (entryIndex, entry ) { html += '<div class=\"entry\">' ; html += '<div class=\"repoName term\">' + entry.name + '</div>' ; html += '<div class=\"repoURL part\">' + '<a href=\"' + entry.url + '\">' + entry.url + '</a>' + '</div>' ; html += '</div>' ; }); $('#dictionary' ).html (html); });
Chapter 7 使用插件 1.把幻灯片的切换周期延长到 1.5 秒,把动画的效果修改为下一张幻灯片淡入之前,前一张幻灯片淡出。
1 2 3 4 5 6 7 8 9 $books.cycle ({ timeout : 2000 , speed : 1500 , pause : true , fx : 'fade' , before : function ( ) { $('#slider' ).slider ('value' , $('#books li' ).index (this )); } });
2.设置名为 cyclePaused 的 cookie,将它的有效期设置为30天
1 2 3 $.cookie ('cyclePaused' , null , { expires : 7 });
3.限制书名区域,每次 resize 只允许以10像素为单位
1 2 3 4 $books.find ('.title' ).resizable ({ handles : 's' , grid : [10 , 10 ] });
4.修改 slider 的动画,让滑块平滑地移动到下一个位置。
1 2 3 4 5 6 7 8 $('<div id=\"slider\"></div>' ).slider ({ min : 0 , max : $('#books li' ).length - 1 , animate : true , slide : function (event, ui ) { $books.cycle (ui.value ); } }).appendTo ($controls);
5.幻灯片播放完最后一张后停止。停止播放时,也禁用相应的按钮和滑动条。
1 2 3 4 5 6 7 8 9 10 $books.cycle ({ timeout : 2000 , speed : 1500 , pause : true , fx : 'fade' , nowrap : true , before : function ( ) { $('#slider' ).slider ('value' , $('#books li' ).index (this )); } });
7.修改 mobile.html 中的 HTML 代码,让列表视图根据书名的第一个字母分隔开来。 可以在 html 中添加几个带有 data-role=\"list-divider\" 属性的标签:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div data-role =\ "content \"> <ul data-role =\ "listview \" data-inset =\ "true \" data-filter =\ "true \"> <li data-role =\ "list-divider \"> D</li > <li > <a href =\ "#drupal-7 \"> Drupal 7 Development by Example</a > </li > <li data-role =\ "list-divider \"> J</li > <li > <a href =\ "#jq-game \"> jQuery Game Development Essentials</a > </li > <li > <a href =\ "#jqmobile-cookbook \"> jQuery Mobile Cookbook</a > </li > <li > <a href =\ "#jquery-designers \"> jQuery for Designers</a > </li > <li > <a href =\ "#jquery-hotshot \"> jQuery Hotshot</a > </li > <li > <a href =\ "#jqui-cookbook \"> jQuery UI Cookbook</a > </li > <li data-role =\ "list-divider \"> M</li > <li > <a href =\ "#mobile-apps \"> Creating Mobile Apps with jQuery Mobile</a > </li > <li data-role =\ "list-divider \"> W</li > <li > <a href =\ "wp-mobile-apps.html \"> WordPress Mobile Applications with PhoneGap</a > </li > </ul > </div >
Chapter 8 开发插件 1.创建 .slideFadeIn() 和 .slideFadeOut() 的插件方法,把不透明度动画方法 .fadeIn() 和 .fadeOut() 以及高度动画方法 .slideDown() 和 .slideUp() 结合起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (function ($ ) { $.fn.slideFadeIn = function ( ) { return this .each (function ( ) { $(this ).slideDown ('slow' ).fadeTo ('slow' , 1.0 ); }); }; $.fn.slideFadeOut = function ( ) { return this .each (function ( ) { $(this ).fadeTo ('slow' , 0.5 ).slideUp ('slow' ); }); }; })(jQuery); $('#container h1' ).click (function ( ) { $('#inventory' ).slideFadeOut (); $('#inventory' ).slideFadeIn (); });
2.扩展 .shadow() 方法的可定制能力,让插件用户可以指定元素副本的 z 轴索引。为提示条控件添加一个 .isOpen() 子方法,在提示条正在显示的时候返回 true,而在其他时候返回 false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 (function ($ ) { $.fn.shadow = function (opts ) { var options = $.extend ($.fn.shadow .defaults , opts); return this .each (function ( ) { var $originalElement = $(this ); for (var i = 0 ; i < options.copies ; i++) { var offset = options.copyOffset (i); $originalElement .clone () .css ({ position : 'absolute' , left : $originalElement.offset ().left + offset.x , top : $originalElement.offset ().top + offset.y , margin : 0 , zIndex : options.zIndex , opacity : options.opacity }) .appendTo ('body' ); } }); } })(jQuery); $.fn.shadow .defaults = { copies : 5 , opacity : 0.1 , copyOffset : function (index ) { return { x : index, y : index }; }, zIndex : -1 }; (function ($ ) { $.widget ('ljq.tooltip' , { options : { offsetX : 10 , offsetY : 10 , content : function ( ) { return $(this ).data ('tooltip-text' ); } }, _create : function ( ) { this .isTooltipOpen = false ; this ._tooltipDiv = $('<div></div>' ) .addClass ('ljq-tooltip-text ' + 'ui-widget ui-state-highlight ui-corner-all' ) .hide ().appendTo ('body' ); this .element .addClass ('ljq-tooltip-trigger' ) .on ('mouseenter.ljq-tooltip' , $.proxy (this ._open , this )) .on ('mouseleave.ljq-tooltip' , $.proxy (this ._close , this )); }, destroy : function ( ) { this ._tooltipDiv .remove (); this .element .removeClass ('ljq-tooltip-trigger' ) .off ('.ljq-tooltip' ); $.Widget .prototype .destroy .apply (this , arguments ); }, isOpen : function ( ) { return this .isTooltipOpen ; }, _open : function ( ) { if (!this .options .disabled ) { var elementOffset = this .element .offset (); this ._tooltipDiv .css ({ position : 'absolute' , left : elementOffset.left + this .options .offsetX , top : elementOffset.top + this .element .height () + this .options .offsetY }).text (this .options .content .call (this .element [0 ])); this ._tooltipDiv .show (); this .isTooltipOpen = true ; this ._trigger ('open' ); } }, open : function ( ) { this ._open (); }, _close : function ( ) { this ._tooltipDiv .hide (); this ._trigger ('close' ); this .isTooltipOpen = false ; }, close : function ( ) { this ._close (); } }); })(jQuery); $('a' ).tooltip ().hover (function ( ) { console .log ('Is Tooltip Open? : ' + $(this ).tooltip ('isOpen' ).toString ()); });
3.添加代码监听 tooltipOpen 事件,并在控制台中记录一条消息
1 2 3 $('a' ).bind ('tooltipopen' , function ( ) { console .log ('tooltipopen event triggered' ); });
4.**(挑战)**自定义提示条部件的 content 选项,通过 AJAX 取得链接的 href 属性指向的页面的内容,将取得的内容作为提示条的文本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $('a' ).tooltip ({ content : function ( ) { var url = $(this ).attr ('href' ); var result = null ; $.ajax ({ url : url, type : 'get' , dataType : 'html' , async : false , success : function (data ) { result = data; } }); return result; } });
5.**(挑战)**为提示条部件提供一个新的 effect 选项,如果指定该选项,则用该名字指定的 jQuery UI 效果显示或隐藏提示条。
1 2 3 4 5 6 7 8 9 if (this .options .effect ) { this ._tooltipDiv .effect (this .options .effect , {distance : 10 , duration : 80 }); } $('a' ).tooltip ({effect : 'shake' });