So you want to make a slideshow on your blog. First you'll need content. Your content can come from anywhere. JSON, XML, and HTML are supported. So get that setup and ready to go. Once you have that, put jQuery, jquery.knot.js, and knot.base.css on your page. Add the initialization block and you've got a slideshow. Want to add features? Just change the settings in the init block. Don't like the way it looks? Add some css to your page. Hide stuff you don't like. Change the colors etc. It really is that simple.
- Add the js to your page. http://o.aolcdn.com/os/aol/knot/v2/jquery.knot.min.js
- Add the base css to your page. http://o.aolcdn.com/os/aol/knot/css/knot.base.css
- Add configuration and initialization javascript.
This is the core plugin for used for initializing data acquisition and mapping. It is also used to initialize user interfaces by default.
Let's start off with a simple example.
####The HTML (abridged)
<ul class="photo-gallery">
<li class="photo" data-type="photo" data-media-id="5422878">
<h4>2014 Audi R8 V10 Plus rear 3/4 view</h4>
<a href="/photos/2014-audi-r8-v10-plus-first-drive/5422878/" data-photo-src="http://www.blogcdn.com/www.autoblog.com/media/2012/11/04-2014-audi-r8-v10-plus-fd.jpg">2014 Audi R8 V10 Plus</a>
</li>
<li class="photo" data-type="photo" data-media-id="5422879">
<h4>2014 Audi R8 V10 Plus side view</h4>
<a href="/photos/2014-audi-r8-v10-plus-first-drive/5422879/" data-photo-src="http://www.blogcdn.com/www.autoblog.com/media/2012/11/05-2014-audi-r8-v10-plus-fd.jpg">2014 Audi R8 V10 Plus</a>
</li>
</ul>
####The JavaScript
var $knot = $('#knot');
var knotSettings = {
data: '.photo-gallery',
contentMap: {
entryArray: {
path: 'li.photo'
},
'photo_src': {
path: 'a[data-photo-src]'
},
caption: {
path: 'a[text]'
},
title: {
path: 'h4[text]'
},
thumbnail: {
path: 'a[data-photo-src]'
},
type: {
path: '[data-type]'
}
}
};
$knot.knot(knotSettings);
Now, the code above will render a simple slider with the title and captions below.
####data (required)
The data
option defines what data to use to build the gallery. This object should include the array of entries that will become slides. data
can be set as a css selector string, a json object, or a url to a json or xml endpoint.
####contentMap (required)
The contentMap
option is an associative array that will define where to select the data to use to render the gallery.
####entryArray (required)
The entryArray
option is a selector or dot syntax string used to select, within the context of data
, an array of objects to use as each slide.
The rest of the options within the the contentMap
are arbitrary with a few exceptions. First I'll explain the exceptions. I'll go into the reasoning for arbitrary keys a bit later.
There are certian fields required for each type of slide that you wish to render. List of types:
Slide Type | Required Keys |
---|---|
photo | photo_src |
image | photo_src |
video | player |
audio | player |
quote | quoteSource , text |
tweet | tweet_link |
text | title , body |
html | html |
embed | embed |
ad | magicNumber |
Here is a list of available options and what they do.
Option Key | Value Type(s) | Possible Values | Behavior | Default | Notes |
---|---|---|---|---|---|
activeSlide | number | number | The gallery will change to this index when it renders | 0 | |
after | string, function | html string, function returning html string, null | This html string will be inserted into the dom after the target element | null | |
before | string, function | html string, function returning html string, null | This html string will be inserted into the dom before the target element | null | |
bottomExtraHtml | string, function | html string, function returning html string, null | This html string will be inserted into the bottom section of the fullscreen view | null | |
build | boolean | boolean | Tells the init plugin to render the ui | true | |
contentMap | object | object | Used to map data to properties for rendering | {} | required |
data | string, object | url, css selector, json object | Used to acquire the slideshow's data | '' | required |
dataType | string | xml, json, jsonp, html | Used to define the type of data to be acquired | jsonp | can dynamically detect html |
defaultType | string | see list of types above | Sets entries to this type when type is not available | photo | |
downloadEnabled | boolean | boolean | Covers the slide with an img element that can be used to download the slide's image | false | loads image only onContextMenu or press and hold events |
effect | string | translate, fade, none | Sets the type of transition that will occur between slides | translate | |
fullscreenAdMN | number | number, null | The magic number used to get the 300x250 in the fullscreen right rail | null | |
fullscreenHtml | string, function | html string, function returning html string, null | Overwrites the html used to render the fullscreen view | null | |
fullscreenLBMN | number | number, null | The magic number used to get the 728x90 for the upper area in the fullscreen view | null | |
fullscreenRefreshDivId | array | array of id strings, null | Sets which elements to target for ad refresh in fullscreen view | 'knotFullscreenAd-' + options.galleryId | |
fullscreenThumbs | boolean | boolean | Toggles thumbnails in the fullscreen view | false | |
fullscreenThumbnailControls | boolean | boolean | Inserts arrows to paginate fullscreen thumbnails | false | Is ignored unless fullscreenThumbnailStyle is set to carousel |
fullscreenThumbnailPosition | string | slider, null | Initiallizes thumbnails in either the right rail or below the slider | null | |
fullscreenThumbnailStyle | string | normal, carousel | Sets the display of the thumbs as either a grid or a carousel | normal | |
galleryId | number, string | number, string, null | Is used to create ad spot id's for ad refresh targeting | null | |
hideData | boolean | boolean | Tells the init to hide the data source if it is an html element | true | |
isInternational | boolean | boolean | Used for omnitureConfig page tracking | false | |
refreshCount | number | number | Sets the refresh rate for ads | 4 | |
refreshDivId | array | array of id strings, null | Sets which elements to target for ad refresh | null | |
rightRailHtml | string, function | html string, function returning html string, null | Overwrites the html used to render the right rail above the 300x250 ad fullscreen view | null | |
slideshowTitle | string | string, null | Used to render the slideshow's title in several places of the ui's | null | |
thumbHeight | number | number | Set the thumbnail height | 80 | |
thumbnails | boolean | boolean | Toggles the render of thumbnails in the default view | false | |
thumbnailControls | boolean | boolean | Inserts arrows to paginate thumbnails | false | Is ignored unless thumbnailStyle is set to carousel |
thumbnailsOnly | boolean | boolean | Prevents the slider from rendering and only renders the thumbnails | false | Does not prevent fullscreen from rendering |
thumbnailPosition | string | afterCaption, '', null | Sets the placement of the thumbnails to either before the caption and title or after | null | |
thumbnailStyle | string | normal, carousel | Sets the display of the thumbs as either a grid or a carousel | normal | |
thumbWidth | number | number | Set the thumbnail width | 80 | |
trackingId | string | string, null | Used to set omnitureConfig objects channel property | null | |
transitionSpeed | number | number | Time in milliseconds the transition between slides should take | 600 |
Here is a list of callbacks to which we can hook functions
Callback | Execution Point |
---|---|
onNextSlide | Next slide requested |
onPrevSlide | Previous slide requested |
onSlideChange | Slide change triggered |
onSlideChangeComplete | Slide changed |
onSlideLoad | Slide is loaded/preloaded |
onThumbClick | Thumbnail is clicked |
onEnterFullscreen | Fullscreen was entered |
onExitFullscreen | Fullscreen was exited |
onUiBuilt | Ui or Fullscreen Ui was inserted to DOM |
onKnotInit | Data aquired, mapped, and stored on target |
Now that we've gone over the basics of getting a gallery up and running, let's go over some more advanced features.
Each key that you set within the contentMap
, with some exceptions, has two options path
and override
.
entryArray
, and thumbnail
have the addition html
option.
####path (required but can be '') This is the dot syntax or css selector used to lookup values from the data object.
####override This allows a string or function that will be used to force the value to something else. For example, if your data doesn't specify a type for each slide but you know it will always be a photo, like an Instagram feed, you can force all slide to use a type of photo.
type: {
path: '',
override: 'photo'
}
Or say you want to use a number formatted as a dollar amount:
cost: {
path: '',
override: (function () {
var cost = 123122
return '$' + cost.toFixed(2);
}())
}
####html
This option must be a function that takes a single argument that is the data for that slide and must return a jQuery object. This is where some neat stuff happens. The data object that gets passed to this function contains the properties that you have arbitrarily set in the contentMap
option. Here you can define any slide appearance that you wish. For example, say we wanted to show a set of photos where we credit the photo with semi-transparent overlay with a link to the owner's website. We might build something like this:
contentMap: {
entryArray: {
path: 'li.photo',
html: function (entry) {
return $([
'<div style="position:relative">'
'<div style="background-image:url("', entry.photo_src, '");position:absolute;top:0;right:0;bottom:0;left:0;"></div>',
'<div style="background:rgba(0,0,0,.3);position:absolute;bottom:0;right:0">',
entry.credit, ': <a href="', entry.credit_url, '" target="_blank">', entry.user, '</a>',
'</div>',
'</div>'
].join(''));
}
},
'photo_src': {
path: 'a[data-photo-src]'
},
credit: {
path: '[data-credit]'
},
credit_user: {
path: '[data-username]'
},
credit_url: {
path: '[data-user-profile]'
},
caption: {
path: 'a[text]'
},
title: {
path: 'h4[text]'
},
type: {
path: '',
override: 'photo'
}
}
In this example we have set type to photo because we want to prefetch the image before triggering the loaded callback. By default slide types of image and photo are the only types that do prefecthing before transitioning to the slide. Just as before type photo requires the photo_src
definition.
Here I will go over the different ways to interact with the api's and data made available by the different plugins. I will also go over the ways you can set options and extend the plugins.
First, all methods that are available through the API are accessed in the same way after initialization. This is true for all plugins as well.
$('#knot').knot('methodName', [arguments]);
In the case of the other plugins you would use the coresponding plugin namespace.
$('#knot').knotUi('methodName', [arguments]);
$('#knot').knotFullscreen('methodName', [arguments]);
$('#knot').knotThumbs('methodName', [arguments]);
Next, you can access the data for any and all plugin instances with jQuery's $.fn.data()
function. Each instance stores itself as data on the target element.
$('#knot').data('knot');
$('#knot').data('knotUi');
$('#knot').data('knotFullscreen');
$('#knot').data('knotThumbs');
Now, almost everything that happens in the UIs are trigger by jQuery events via $.fn.trigger
with $.fn.delegate
and $.fn.bind
(didn't use $.fn.on
for backwards compat).
Here are some events that get trigger on the element on which the knot plugin was initialized.
From the core:
Event | Arguments |
---|---|
knotReady |
event, context |
knotDestroyed |
event |
From the UI:
Event | Arguments |
---|---|
knotUiBuilt |
event |
showNextSlide |
event |
showPrevSlide |
event |
slideChangeStart |
event, index, direction |
slideChange |
event, index, direction |
slideChangeComplete |
event, index |
From the fullscreen UI:
Event | Arguments |
---|---|
knotFullscreenDestroyed |
event |
knotFullscreenUiBuilt |
event |
enterFullscreen |
event |
enteredFullscreen |
event, index |
exitFullscreen |
event, index |
exitedFullscreen |
event, index |
knotResize |
event |
From the thumbnails:
Event | Arguments |
---|---|
knotThumbsDestroyed |
event |
thumbsAvailable |
event |
thumbMouseEnter |
event, original event, index |
thumbsCentered |
event |
You can bind
, delegate
or on
to any of these events on the element on which the plugin was initialized.
Options are typically set by the initialization block but can be set or changed after initilization using the option
method available for each plugin.
$('#knot').knotUi('option', {fullscreen: false});
To get the current value of an option use .data()
$('#knot').data('knot').options.fullscreen
"Extending" is kind of a broad term. What I mean by extending is adding plugins to the stack, adding methods to the plugins, adding renders to the renderer list, and simple inheretance of the prototypes for a plugin. You might think, "that sounds complicated.", and you'd be right. So I'll try to make it easy.
I recommend that you follow this pattern when adding plugins to the knot stack.
//the constructor
$.newPlugin = function (context, element) {
this.$element = $(element);
this._context(context);
this._init();
};
//default settings
$.newPlugin.settings = {
name: 'myPlugin'
};
//the prototype
$.newPlugin.prototype = {
_context: function (context) {
if (context.options) {
this.options = context.options;
}
this.context = context;
},
init: function () {
//some other methods
},
destroy: function () {
this.$element
.removeData('myPlugin')
.unbind('.myPlugin')
.undelegate('.myPlugin')
.empty();
}
}
//the plugin
$.fn.newPlugin = function (options,=) {
if (typeof options === 'string') {
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = $.data(this, 'newPlugin');
if (!instance) {
return;
}
if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
return;
}
instance[options].apply(instance, args, temp);
});
} else {
this.each(function () {
var instance = $.data(this, 'newPlugin');
if (instance) {
instance.destroy();
}
$.data(this, 'newPlugin', new $.newPlugin(options, this));
});
}
return this;
};
I've included in the plugins extend methods that allow you to add or overwrite methods for the plugin.
$('#knot').knot('extend', 'newMethod', function () {
var _this = this;
//this reffers to the plugin instance's prototype
//your new method
//i like to return this so that methods can be chained elsewhere in the prototype.
return this;
});
This is how you would add a new renderer type to the renderer plugin.
$.knotRender('add', 'phonebook', function ($slide, callback) {
$slide.html('<div class="your-renderer-html">' + $slide.data('index') + '</div>');
if (callback) {
callback($slide);
}
});
It's important to know that you MUST have a callback that passes $slide as the only argument. The $slide argument that the renderer receives is the jQuery collection that contains the slide's li that will transition into view when active.
So let's say you want to create a plugin that shares all of the same methods as another plugin except you want to overwrite a couple of methods and add a few without fucking up the original plugin. It's what the fullscreen plugin does to the ui plugin. Here's how you might do that.
//javascript constructor extender
var __extends = function (d, b) {
function A() {
this.constructor = d;
}
A.prototype = b.prototype;
d.prototype = new A();
};
//extends ui. classy.
$.newUiBasedPlugin = function (context, $el) {
$.knotUi.call(this, context, $el);
};
__extends($.newUiBasedPlugin, $.knotUi);
var methods = {
//your methods
};
$.each(methods, function (name, method) {
$.newUiBasedPlugin.prototype[name] = method;
});
//the plugin
$.fn.newUiBasedPlugin = function (options,=) {
if (typeof options === 'string') {
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = $.data(this, 'newUiBasedPlugin');
if (!instance) {
return;
}
if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
return;
}
instance[options].apply(instance, args, temp);
});
} else {
this.each(function () {
var instance = $.data(this, 'newUiBasedPlugin');
if (instance) {
instance.destroy();
}
$.data(this, 'newUiBasedPlugin', new $.newUiBasedPlugin(options, this));
});
}
return this;
};
This utility is used to fetch data from a defined source.
The source can be a url or a css selector.
If the source is a url, the plugin will asynchronously retrieve the data before it executes the callback.
If the source is a css selector the data returned will be the jQuery object created from that selector.
The type can be set to json
, jsonp
, xml
, or html
.
The type argument defaults to jsonp
and will automaticly detect jsonp
or html
.
The callback receives two arguments - the resulting data and the type.
Once the data has been returned the callback will execute.
$.knotData({
source: 'http://www.example.com/data.json',
type: 'json',
callback: function (data, type) {
//do something
}
});
This utility is used to return data described by a selector from an object.
The data
argument can be either a native JavaScript object or a jQuery object.
The map
argument is either a dot syntax string or a css selector string.
Dot syntax is used to select values from native objects.
CSS selectors are used to select values from jQuery ojects.
Examples:
Using dot syntax.
var lookedUp = $.knotLookup({foo: {bar: 1}}, 'foo.bar');
lookedUp
will return 1
.
When using dot syntax accessing array is accomplished by using the index of the array you want to search. object.array.0.value
Using html and css selectors.
<div id="#data-element">
<a href="http://www.example.com">Example</a>
</div>
var lookedUp = $.knotLookup('#data-element', 'ul li a[href]');
lookedUp
will return http://www.example.com
.
When using css selectors, if you want to return the attribute of an element simply select the attribute without passing a value. .list li a[href]
If you want to return the text or innerHtml use [text]
and [html]
respectively.
This utility is used transform the data for a slide into the final slide to be rendered.
$.knotRender('photo', {
'photo_src': 'http://www.example.com'
}, function ($slide) {
$slide.addClass('loaded');
});
Takes your xml and converts it to json. Primarily used for when the $.knotData function needs to get xml.