My solutions to Learning jQuery 3rd Edition Chapter 7 exercises:
Exercises:
Some of the exercises are requires modifications of codes from the book. You can easily locate my modifications by looking for //--------------Added sections
1. Create new plugin methods called .slideFadeIn() and .slideFadeOut(), combining the opacity animations of .fadeIn() and .fadeOut() with the height animations of .slideDown() and .slideUp().
(function ($) {
$.fn.slideFadeIn = function() {
return this.each(function () {
//$(this).slideDown('slow').fadeIn('slow');
$(this).slideDown('slow').fadeTo('slow', 1.0);
});
};
$.fn.slideFadeOut = function() {
return this.each(function () {
//$(this).slideUp('slow').fadeOut('slow');
$(this).fadeTo('slow', 0.5).slideUp('slow');
});
};
})(jQuery);
//------Sample code for testing excercise 1
jQuery(document).ready(function ($) {
//Test for .slideFadeIn & .slideFadeOut
//Click the <h1>Inventory</h1> to see the effect of these new methods
$('#container h1').toggle(function() {
$('#inventory').slideFadeOut();
}, function () {
$('#inventory').slideFadeIn();
});
});
2. Extend the customizability of the .shadow() method so that the z-index of the cloned copies can be specified by the plugin user. Add a new sub-method called isOpen to the tooltip widget. This sub-method should return true if the tooltip is currently displayed and false otherwise.
/******************************************************************************
.shadow()
Create a shadow effect on any element by brute-force copying.
******************************************************************************/
(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,
//------------------------------------------------------Added
zIndex: options.zIndex,
//-------------------------------------------------------------
opacity: options.opacity
})
.appendTo('body');
}
});
};
$.fn.shadow.defaults = {
copies: 5,
opacity: 0.1,
copyOffset: function (index) {
return { x: index, y: index };
},
//------------------------------------------------------Added
zIndex: -1
//-----------------------------------------------------------
};
})(jQuery);
/******************************************************************************
.tooltip()
A simple jQuery UI tooltip widget.
******************************************************************************/
(function ($) {
$.widget('ljq.tooltip', {
options: {
offsetX: 10,
offsetY: 10,
content: function () {
return $(this).data('tooltip-text');
}
},
_create: function () {
//------------------------------------------------------Added
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')
.bind('mouseenter.ljq-tooltip', $.proxy(this._open, this))
.bind('mouseleave.ljq-tooltip', $.proxy(this._close, this));
},
destroy: function () {
this._tooltipDiv.remove();
this.element.removeClass('ljq-tooltip-trigger')
.unbind('.ljq-tooltip');
$.Widget.prototype.destroy.apply(this, arguments);
},
open: function () {
this._open();
},
close: function () {
this._close();
},
_open: function () {
//------------------------------------------------------Added
this.isTooltipOpen = true;
//-----------------------------------------------------------
if (!this.options.disabled) {
var elementOffset = this.element.offset();
this._tooltipDiv.css({
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._trigger('open');
}
},
_close: function () {
//------------------------------------------------------Added
this.isTooltipOpen = false;
//-----------------------------------------------------------
this._tooltipDiv.hide();
this._trigger('close');
},
//------------------------------------------------------Added
isOpen: function() {
return this.isTooltipOpen;
}
//-----------------------------------------------------------
});
})(jQuery);
//------Sample code for testing excercise 2
jQuery(document).ready(function ($) {
$.fn.shadow.defaults.copies = 10;
//$.fn.shadow.defaults.zIndex = 2; //if you uncomment this, Clicking <h1>Inventory</h1> will have no effect
$('h1').shadow({
copyOffset: function (index) {
return { x: -index, y: index };
}
});
//$('a').tooltip();
$('a').tooltip().hover(function () {
//alert($(this).tooltip('isOpen').toString());
console.log('Is tooltip open? -> ' + $(this).tooltip('isOpen').toString());
});
});
3. Add code that listens for the tooltipopen event that our widget fires, and logs a message to the console.
jQuery(document).ready(function ($) {
$('a').bind('tooltipopen', function () {
console.log('tooltip open event fires');
});
});
4. Challenge: Provide an alternative content option for the tooltip widget that fetches the content of the page and anchor's href points to via Ajax, and displays that content as the tooltip text.
jQuery(document).ready(function ($) {
$('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. Challenge: Provide a new effect option for the tooltip widget that, if specified, applies the named jQuery UI effect (such as explode) to the showing and hiding of the tooltip.
/******************************************************************************
.tooltip()
A simple jQuery UI tooltip widget.
******************************************************************************/
(function ($) {
$.widget('ljq.tooltip', {
options: {
offsetX: 10,
offsetY: 10,
content: function () {
return $(this).data('tooltip-text');
}
},
_create: function () {
//------------------------------------------------------Added
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')
.bind('mouseenter.ljq-tooltip', $.proxy(this._open, this))
.bind('mouseleave.ljq-tooltip', $.proxy(this._close, this));
},
destroy: function () {
this._tooltipDiv.remove();
this.element.removeClass('ljq-tooltip-trigger')
.unbind('.ljq-tooltip');
$.Widget.prototype.destroy.apply(this, arguments);
},
open: function () {
this._open();
},
close: function () {
this._close();
},
_open: function () {
//------------------------------------------------------Added
this.isTooltipOpen = true;
//-----------------------------------------------------------
if (!this.options.disabled) {
var elementOffset = this.element.offset();
this._tooltipDiv.css({
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._trigger('open');
//------------------------------------------------------Added
if(this.options.effect) {
this._tooltipDiv.effect(this.options.effect, {distance: 10, duration: 80});
}
//-----------------------------------------------------------
}
},
_close: function () {
//------------------------------------------------------Added
this.isTooltipOpen = false;
//-----------------------------------------------------------
this._tooltipDiv.hide();
this._trigger('close');
},
//------------------------------------------------------Added
isOpen: function () {
return this.isTooltipOpen;
}
//-----------------------------------------------------------
});
})(jQuery);
//------Sample code for testing excercise 5
jQuery(document).ready(function ($) {
$('a').tooltip({effect: 'shake'});
});
Free Lessons for Chruch Pianists:
Free lessons, tips and downloads for church pianists
DVD Courses (Reharmonization, Play by Ear!, Arranging, Accompanying, Theory for Church Pianists, etc.):
Over 30 hours of DVD instruction for church pianists