Last active
December 21, 2015 17:28
-
-
Save happyrobots/6340312 to your computer and use it in GitHub Desktop.
stuffy stuff thing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* guiders.js | |
* | |
* version 2.0.0 | |
* | |
* Released under the Apache License 2.0. | |
* www.apache.org/licenses/LICENSE-2.0.html | |
* | |
* Questions about Guiders? | |
* Email me (Jeff Pickhardt) at [email protected] | |
* | |
* Questions about Optimizely? Email one of the following: | |
* [email protected] or [email protected] | |
* | |
* Enjoy! | |
*/ | |
var guiders = (function($) { | |
var guiders = $.guiders = {}; | |
guiders.version = "2.0.0"; | |
guiders._defaultSettings = { | |
attachTo: null, // Selector of the element to attach to. | |
autoFocus: false, // Determines whether or not the browser scrolls to the element. | |
buttons: [{name: "Close"}], | |
buttonCustomHTML: "", | |
classString: null, | |
closeOnEscape: false, | |
description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", | |
highlight: null, | |
isHashable: true, | |
maxWidth: null, | |
offset: { | |
top: null, | |
left: null | |
}, | |
onClose: null, | |
onHide: null, | |
onShow: null, | |
overlay: false, | |
position: 0, // 1-12 follows an analog clock, 0 means centered. | |
shouldSkip: function() {}, // Optional handler allows you to skip a guider if returns true. | |
title: "Sample title goes here", | |
width: 400, | |
xButton: false // This places a closer "x" button in the top right of the guider. | |
}; | |
guiders._htmlSkeleton = [ | |
"<div class='guider'>", | |
" <div class='guiders_content'>", | |
" <h1 class='guiders_title'></h1>", | |
" <div class='guiders_close'></div>", | |
" <p class='guiders_description'></p>", | |
" <div class='guiders_buttons_container'>", | |
" </div>", | |
" </div>", | |
" <div class='guiders_arrow'>", | |
" </div>", | |
"</div>" | |
].join(""); | |
guiders._arrowSize = 42; // This is the arrow's width and height. | |
guiders._backButtonTitle = "Back"; | |
guiders._buttonAttributes = {"href": "javascript:void(0);"}; | |
guiders._buttonClassName = "guiders_button"; // Override this if you use a different class name for your buttons. | |
guiders._buttonClickEvent = "click touch"; // Using click touch allows this to trigger with iPad/iPhone taps, as well as browser clicks | |
guiders._buttonElement = "<a></a>"; // Override this if you want to use a different element for your buttons, like spans. | |
guiders._closeButtonTitle = "Close"; | |
guiders._currentGuiderID = null; | |
guiders._fixedOrAbsolute = "fixed"; | |
guiders._guiders = {}; | |
guiders._lastCreatedGuiderID = null; | |
guiders._nextButtonTitle = "Next"; | |
guiders._offsetNameMapping = { | |
"topLeft": 11, | |
"top": 12, | |
"topRight": 1, | |
"rightTop": 2, | |
"right": 3, | |
"rightBottom": 4, | |
"bottomRight": 5, | |
"bottom": 6, | |
"bottomLeft": 7, | |
"leftBottom": 8, | |
"left": 9, | |
"leftTop": 10 | |
}; | |
guiders._windowHeight = 0; | |
// Basic IE browser detection | |
var ieBrowserMatch = navigator.userAgent.match(/MSIE\s([\d.]+)/); | |
guiders._isIE = ieBrowserMatch && ieBrowserMatch.length > 1; | |
guiders._ieVersion = ieBrowserMatch && ieBrowserMatch.length > 1 ? Number(ieBrowserMatch[1]) : -1; | |
guiders._addButtons = function(myGuider) { | |
var guiderButtonsContainer = myGuider.elem.find(".guiders_buttons_container"); | |
if (myGuider.buttons === null || myGuider.buttons.length === 0) { | |
guiderButtonsContainer.remove(); | |
return; | |
} | |
for (var i = myGuider.buttons.length - 1; i >= 0; i--) { | |
var thisButton = myGuider.buttons[i]; | |
var thisButtonElem = $(guiders._buttonElement, | |
$.extend({"class" : guiders._buttonClassName, "html" : thisButton.name }, guiders._buttonAttributes, thisButton.html || {}) | |
); | |
if (typeof thisButton.classString !== "undefined" && thisButton.classString !== null) { | |
thisButtonElem.addClass(thisButton.classString); | |
} | |
guiderButtonsContainer.append(thisButtonElem); | |
var thisButtonName = thisButton.name.toLowerCase(); | |
if (thisButton.onclick) { | |
thisButtonElem.bind(guiders._buttonClickEvent, thisButton.onclick); | |
} else { | |
switch (thisButtonName) { | |
case guiders._closeButtonTitle.toLowerCase(): | |
thisButtonElem.bind(guiders._buttonClickEvent, function () { | |
guiders.hideAll(); | |
if (myGuider.onClose) { | |
myGuider.onClose(myGuider, false /* close by button */); | |
} | |
$("body").trigger("guidersClose"); | |
}); | |
break; | |
case guiders._nextButtonTitle.toLowerCase(): | |
thisButtonElem.bind(guiders._buttonClickEvent, function () { | |
!myGuider.elem.data("locked") && guiders.next(); | |
}); | |
break; | |
case guiders._backButtonTitle.toLowerCase(): | |
thisButtonElem.bind(guiders._buttonClickEvent, function () { | |
!myGuider.elem.data("locked") && guiders.prev(); | |
}); | |
break; | |
} | |
} | |
} | |
if (myGuider.buttonCustomHTML !== "") { | |
var myCustomHTML = $(myGuider.buttonCustomHTML); | |
myGuider.elem.find(".guiders_buttons_container").append(myCustomHTML); | |
} | |
if (myGuider.buttons.length === 0) { | |
guiderButtonsContainer.remove(); | |
} | |
}; | |
guiders._addXButton = function(myGuider) { | |
var xButtonContainer = myGuider.elem.find(".guiders_close"); | |
var xButton = $("<div></div>", { | |
"class" : "guiders_x_button", | |
"role" : "button" | |
}); | |
xButtonContainer.append(xButton); | |
xButton.click(function() { | |
guiders.hideAll(); | |
if (myGuider.onClose) { | |
myGuider.onClose(myGuider, true); | |
} | |
$("body").trigger("guidersClose"); | |
}); | |
}; | |
guiders._attach = function(myGuider) { | |
if (typeof myGuider !== 'object') { | |
return; | |
} | |
var attachTo = $(myGuider.attachTo); | |
var myHeight = myGuider.elem.innerHeight(); | |
var myWidth = myGuider.elem.innerWidth(); | |
if (myGuider.position === 0 || attachTo.length === 0) { | |
var fixedOrAbsolute = "fixed"; | |
if (guiders._isIE && guiders._ieVersion < 9) { | |
fixedOrAbsolute = "absolute"; | |
} | |
myGuider.elem.css("position", fixedOrAbsolute); | |
myGuider.elem.css("top", ($(window).height() - myHeight) / 3 + "px"); | |
myGuider.elem.css("left", ($(window).width() - myWidth) / 2 + "px"); | |
return; | |
} | |
// Otherwise, the guider is positioned relative to the attachTo element. | |
var base = attachTo.offset(); | |
var top = base.top; | |
var left = base.left; | |
// topMarginOfBody corrects positioning if body has a top margin set on it. | |
var topMarginOfBody = $("body").outerHeight(true) - $("body").outerHeight(false); | |
top -= topMarginOfBody; | |
// Now, take into account how the guider should be positioned relative to the attachTo element. | |
// e.g. top left, bottom center, etc. | |
if (guiders._offsetNameMapping[myGuider.position]) { | |
// As an alternative to the clock model, you can also use keywords to position the guider. | |
myGuider.position = guiders._offsetNameMapping[myGuider.position]; | |
} | |
var attachToHeight = attachTo.innerHeight(); | |
var attachToWidth = attachTo.innerWidth(); | |
var bufferOffset = 0.9 * guiders._arrowSize; | |
// offsetMap follows the form: [height, width] | |
var offsetMap = { | |
1: [-bufferOffset - myHeight, attachToWidth - myWidth], | |
2: [0, bufferOffset + attachToWidth], | |
3: [attachToHeight/2 - myHeight/2, bufferOffset + attachToWidth], | |
4: [attachToHeight - myHeight, bufferOffset + attachToWidth], | |
5: [bufferOffset + attachToHeight, attachToWidth - myWidth], | |
6: [bufferOffset + attachToHeight, attachToWidth/2 - myWidth/2], | |
7: [bufferOffset + attachToHeight, 0], | |
8: [attachToHeight - myHeight, -myWidth - bufferOffset], | |
9: [attachToHeight/2 - myHeight/2, -myWidth - bufferOffset], | |
10: [0, -myWidth - bufferOffset], | |
11: [-bufferOffset - myHeight, 0], | |
12: [-bufferOffset - myHeight, attachToWidth/2 - myWidth/2] | |
}; | |
var offset = offsetMap[myGuider.position]; | |
top += offset[0]; | |
left += offset[1]; | |
var positionType = "absolute"; | |
// If the element you are attaching to is position: fixed, then we will make the guider | |
// position: fixed as well. | |
if (attachTo.css("position") === "fixed" && guiders._fixedOrAbsolute === "fixed") { | |
positionType = "fixed"; | |
top -= $(window).scrollTop(); | |
left -= $(window).scrollLeft(); | |
} | |
// If you specify an additional offset parameter when you create the guider, it gets added here. | |
if (myGuider.offset.top !== null) { | |
top += myGuider.offset.top; | |
} | |
if (myGuider.offset.left !== null) { | |
left += myGuider.offset.left; | |
} | |
guiders._styleArrow(myGuider); | |
// Finally, set the style of the guider and return it! | |
myGuider.elem.css({ | |
"position": positionType, | |
"top": top, | |
"left": left | |
}); | |
return myGuider; | |
}; | |
guiders._dehighlightElement = function(selector) { | |
$(selector).removeClass('guiders_highlight'); | |
}; | |
guiders._hideOverlay = function() { | |
$("#guiders_overlay").fadeOut("fast"); | |
}; | |
guiders._highlightElement = function(selector) { | |
$(selector).addClass('guiders_highlight'); | |
}; | |
guiders._initializeOverlay = function() { | |
if ($("#guiders_overlay").length === 0) { | |
$("<div id='guiders_overlay'></div>").hide().appendTo("body"); | |
} | |
}; | |
guiders._showOverlay = function(myGuider) { | |
// This callback is needed to fix an IE opacity bug. | |
// See also: | |
// http://www.kevinleary.net/jquery-fadein-fadeout-problems-in-internet-explorer/ | |
$("#guiders_overlay").fadeIn("fast", function(){ | |
if (this.style.removeAttribute) { | |
this.style.removeAttribute("filter"); | |
} | |
}); | |
if (guiders._isIE) { | |
$("#guiders_overlay").css("position", "absolute"); | |
} | |
}; | |
guiders._styleArrow = function(myGuider) { | |
var position = myGuider.position || 0; | |
if (!position) { | |
return; | |
} | |
var myGuiderArrow = $(myGuider.elem.find(".guiders_arrow")); | |
var newClass = { | |
1: "guiders_arrow_down", | |
2: "guiders_arrow_left", | |
3: "guiders_arrow_left", | |
4: "guiders_arrow_left", | |
5: "guiders_arrow_up", | |
6: "guiders_arrow_up", | |
7: "guiders_arrow_up", | |
8: "guiders_arrow_right", | |
9: "guiders_arrow_right", | |
10: "guiders_arrow_right", | |
11: "guiders_arrow_down", | |
12: "guiders_arrow_down" | |
}; | |
myGuiderArrow.addClass(newClass[position]); | |
var myHeight = myGuider.elem.innerHeight(); | |
var myWidth = myGuider.elem.innerWidth(); | |
var arrowOffset = guiders._arrowSize / 2; | |
var positionMap = { | |
1: ["right", arrowOffset], | |
2: ["top", arrowOffset], | |
3: ["top", myHeight/2 - arrowOffset], | |
4: ["bottom", arrowOffset], | |
5: ["right", arrowOffset], | |
6: ["left", myWidth/2 - arrowOffset], | |
7: ["left", arrowOffset], | |
8: ["bottom", arrowOffset], | |
9: ["top", myHeight/2 - arrowOffset], | |
10: ["top", arrowOffset], | |
11: ["left", arrowOffset], | |
12: ["left", myWidth/2 - arrowOffset] | |
}; | |
var position = positionMap[myGuider.position]; | |
myGuiderArrow.css(position[0], position[1] + "px"); | |
}; | |
/** | |
* One way to show a guider to new users is to direct new users to a URL such as | |
* http://www.mysite.com/myapp#guider=welcome | |
* | |
* This can also be used to run guiders on multiple pages, by redirecting from | |
* one page to another, with the guider id in the hash tag. | |
* | |
* Alternatively, if you use a session variable or flash messages after sign up, | |
* you can add selectively add JavaScript to the page: "guiders.show('first');" | |
*/ | |
guiders._showIfHashed = function(myGuider) { | |
var GUIDER_HASH_TAG = "guider="; | |
var hashIndex = window.location.hash.indexOf(GUIDER_HASH_TAG); | |
if (hashIndex !== -1) { | |
var hashGuiderId = window.location.hash.substr(hashIndex + GUIDER_HASH_TAG.length); | |
if (myGuider.id.toLowerCase() === hashGuiderId.toLowerCase()) { | |
guiders.show(myGuider.id); | |
} | |
} | |
}; | |
guiders._updatePositionOnResize = function() { | |
// Change the bubble position after browser gets resized | |
var _resizing = undefined; | |
$(window).resize(function() { | |
if (typeof(_resizing) !== "undefined") { | |
clearTimeout(_resizing); // Prevents seizures | |
} | |
_resizing = setTimeout(function() { | |
_resizing = undefined; | |
if (typeof (guiders) !== "undefined") { | |
guiders.reposition(); | |
} | |
}, 20); | |
}); | |
}; | |
guiders._updatePositionOnResize(); | |
guiders._unwireEscape = function (myGuider) { | |
$(document).unbind("keydown"); | |
}; | |
guiders._wireEscape = function (myGuider) { | |
$(document).keydown(function(event) { | |
if (event.keyCode == 27 || event.which == 27) { | |
guiders.hideAll(); | |
if (myGuider.onClose) { | |
myGuider.onClose(myGuider, true /*close by X/Escape*/); | |
} | |
$("body").trigger("guidersClose"); | |
return false; | |
} | |
}); | |
}; | |
guiders.createGuider = function(passedSettings) { | |
if (passedSettings === null || passedSettings === undefined) { | |
passedSettings = {}; | |
} | |
// Extend those settings with passedSettings | |
myGuider = $.extend({}, guiders._defaultSettings, passedSettings); | |
myGuider.id = myGuider.id || "guider_random_" + String(Math.floor(Math.random() * 1000)); | |
var guiderElement = $("#" + myGuider.id); | |
if (!guiderElement.length) { | |
// If the guider already exists in the DOM, use that, as an alternate guider instantiation method. | |
// See the docs and $.fn.guider for more details. | |
// Otherwise, use the html skeleton. | |
guiderElement = $(guiders._htmlSkeleton); | |
} | |
myGuider.elem = guiderElement; | |
if (typeof myGuider.classString !== "undefined" && myGuider.classString !== null) { | |
myGuider.elem.addClass(myGuider.classString); | |
} | |
// You may pass a parameter to width/maxwidth as either a string or a number. | |
// If it's a number then it is assumed to be in px. | |
if (Number(myGuider.width) === myGuider.width) { | |
myGuider.width = String(myGuider.width) + "px"; | |
} | |
if (Number(myGuider.maxWidth) === myGuider.maxWidth) { | |
myGuider.maxWidth = String(myGuider.maxWidth) + "px"; | |
} | |
myGuider.elem.css("width", myGuider.width); | |
myGuider.elem.css("maxWidth", myGuider.maxWidth); | |
var guiderTitleContainer = guiderElement.find(".guiders_title"); | |
guiderTitleContainer.html(myGuider.title); | |
guiderElement.find(".guiders_description").html(myGuider.description); | |
guiders._addButtons(myGuider); | |
if (myGuider.xButton) { | |
guiders._addXButton(myGuider); | |
} | |
guiderElement.hide(); | |
guiderElement.appendTo("body"); | |
guiderElement.attr("id", myGuider.id); | |
// Ensure myGuider.attachTo is a jQuery element. | |
if (typeof myGuider.attachTo !== "undefined" && myGuider !== null) { | |
guiders._attach(myGuider); | |
} | |
guiders._initializeOverlay(); | |
guiders._guiders[myGuider.id] = myGuider; | |
if (guiders._lastCreatedGuiderID != null) { | |
myGuider.prev = guiders._lastCreatedGuiderID; | |
} | |
guiders._lastCreatedGuiderID = myGuider.id; | |
/** | |
* If the URL of the current window is of the form | |
* http://www.myurl.com/mypage.html#guider=id | |
* then show this guider. | |
*/ | |
if (myGuider.isHashable) { | |
guiders._showIfHashed(myGuider); | |
} | |
return guiders; | |
}; | |
guiders.get = function(id) { | |
if (typeof guiders._guiders[id] === "undefined") { | |
return null; | |
} | |
return guiders._guiders[id] || null; | |
}; | |
guiders.getCurrentGuider = function() { | |
return guiders._guiders[guiders._currentGuiderID] || null; | |
}; | |
guiders.hideAll = function(omitHidingOverlay, next) { | |
next = next || false; | |
$(".guider:visible").each(function(index, elem){ | |
var myGuider = guiders.get($(elem).attr('id')); | |
if (myGuider.onHide) { | |
myGuider.onHide(myGuider, next); | |
} | |
}); | |
$(".guider").fadeOut("fast"); | |
var currentGuider = guiders._guiders[guiders._currentGuiderID]; | |
if (currentGuider && currentGuider.highlight) { | |
guiders._dehighlightElement(currentGuider.highlight); | |
} | |
if (typeof omitHidingOverlay !== "undefined" && omitHidingOverlay === true) { | |
// do nothing for now | |
} else { | |
guiders._hideOverlay(); | |
} | |
return guiders; | |
}; | |
guiders.next = function() { | |
var currentGuider = guiders._guiders[guiders._currentGuiderID]; | |
if (typeof currentGuider === "undefined") { | |
return null; | |
} | |
currentGuider.elem.data("locked", true); | |
var nextGuiderId = currentGuider.next || null; | |
if (nextGuiderId !== null && nextGuiderId !== "") { | |
var nextGuider = guiders.get(nextGuiderId); | |
var omitHidingOverlay = nextGuider.overlay ? true : false; | |
guiders.hideAll(omitHidingOverlay, true); | |
if (currentGuider && currentGuider.highlight) { | |
guiders._dehighlightElement(currentGuider.highlight); | |
} | |
if (nextGuider.shouldSkip && nextGuider.shouldSkip()) { | |
guiders._currentGuiderID = nextGuider.id; | |
guiders.next(); | |
return guiders.getCurrentGuider(); | |
} | |
else { | |
guiders.show(nextGuiderId); | |
return guiders.getCurrentGuider(); | |
} | |
} | |
}; | |
guiders.prev = function () { | |
var currentGuider = guiders._guiders[guiders._currentGuiderID]; | |
if (typeof currentGuider === "undefined") { | |
// not what we think it is | |
return null; | |
} | |
if (currentGuider.prev === null) { | |
// no previous to look at | |
return null; | |
} | |
var prevGuider = guiders._guiders[currentGuider.prev]; | |
prevGuider.elem.data("locked", true); | |
// Note we use prevGuider.id as "prevGuider" is _already_ looking at the previous guider | |
var prevGuiderId = prevGuider.id || null; | |
if (prevGuiderId !== null && prevGuiderId !== "") { | |
var myGuider = guiders.get(prevGuiderId); | |
var omitHidingOverlay = myGuider.overlay ? true : false; | |
guiders.hideAll(omitHidingOverlay, true); | |
if (prevGuider && prevGuider.highlight) { | |
guiders._dehighlightElement(prevGuider.highlight); | |
} | |
guiders.show(prevGuiderId); | |
return myGuider; | |
} | |
}; | |
guiders.reposition = function() { | |
var currentGuider = guiders._guiders[guiders._currentGuiderID]; | |
guiders._attach(currentGuider); | |
}; | |
guiders.scrollToCurrent = function() { | |
var currentGuider = guiders._guiders[guiders._currentGuiderID]; | |
if (typeof currentGuider === "undefined") { | |
return; | |
} | |
var windowHeight = guiders._windowHeight; | |
var scrollHeight = $(window).scrollTop(); | |
var guiderOffset = currentGuider.elem.offset(); | |
var guiderElemHeight = currentGuider.elem.height(); | |
// Scroll to the guider's position. | |
var scrollToHeight = Math.round(Math.max(guiderOffset.top + (guiderElemHeight / 2) - (windowHeight / 2), 0)); | |
window.scrollTo(0, scrollToHeight); | |
}; | |
guiders.show = function(id) { | |
if (!id && guiders._lastCreatedGuiderID) { | |
id = guiders._lastCreatedGuiderID; | |
} | |
var myGuider = guiders.get(id); | |
if (myGuider.overlay) { | |
guiders._showOverlay(myGuider); | |
// if guider is attached to an element, make sure it's visible | |
if (myGuider.highlight && myGuider.attachTo) { | |
guiders._highlightElement(myGuider.attachTo); | |
} | |
} | |
if (myGuider.closeOnEscape) { | |
guiders._wireEscape(myGuider); | |
} else { | |
guiders._unwireEscape(myGuider); | |
} | |
// You can use an onShow function to take some action before the guider is shown. | |
if (myGuider.onShow) { | |
myGuider.onShow(myGuider); | |
} | |
guiders._attach(myGuider); | |
myGuider.elem.fadeIn("fast").data("locked", false); | |
guiders._currentGuiderID = id; | |
var windowHeight = guiders._windowHeight = $(window).height(); | |
var scrollHeight = $(window).scrollTop(); | |
var guiderOffset = myGuider.elem.offset(); | |
var guiderElemHeight = myGuider.elem.height(); | |
var isGuiderBelow = (scrollHeight + windowHeight < guiderOffset.top + guiderElemHeight); /* we will need to scroll down */ | |
var isGuiderAbove = (guiderOffset.top < scrollHeight); /* we will need to scroll up */ | |
if (myGuider.autoFocus && (isGuiderBelow || isGuiderAbove)) { | |
// Sometimes the browser won't scroll if the person just clicked, | |
// so let's do this in a setTimeout. | |
setTimeout(guiders.scrollToCurrent, 10); | |
} | |
$(myGuider.elem).trigger("guiders.show"); | |
return guiders; | |
}; | |
// Allow separate method of instantiating guiders, with $("#guider2").guider() | |
// You can pass parameters to the guiders with either data-attributes on the element, | |
// or as optional parameters in the options hash: $("#guider").guider(options) | |
$.fn.guider = function (passedOptions) { | |
passedOptions = passedOptions || {}; | |
var options = $.extend({}, passedOptions); | |
options.id = $(this).attr("id"); | |
var buttons = []; | |
$(this).find(".guiders_buttons_container").children().each(function () { | |
var buttonOptions = { | |
name: $(this).html(), | |
classString: $(this).attr("class") | |
}; | |
if ($(this).attr("data-onclick")) { | |
var functionName = $(this).attr("data-onclick"); | |
buttonOptions.onclick = function () { window[functionName](); }; | |
} | |
$(this).remove(); | |
buttons.push(buttonOptions); | |
}); | |
options.buttons = buttons; | |
title = $(this).find(".guiders_title").html() | |
if (title) { | |
options.title = title; | |
} | |
description = $(this).find(".guiders_description").html() | |
if (description) { | |
options.description = description; | |
} | |
for (var optionName in guiders._defaultSettings) { | |
if (!guiders._defaultSettings.hasOwnProperty(optionName)) { | |
continue; | |
} | |
var optionValue = $(this).attr("data-" + optionName); | |
if (optionValue === undefined || optionValue === null) { | |
continue; | |
} | |
if (optionValue == "true") { | |
optionValue = true; | |
} else if (optionValue == "false") { | |
optionValue = false; | |
} | |
options[optionName] = optionValue; | |
} | |
guiders.createGuider(options); | |
return this; | |
}; | |
return guiders; | |
}).call(this, jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},h=0,c=0,l=[];function g(e,d,g,i){var c={data:i||(d?d.data:{}),_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};e&&a.extend(c,e,{nodes:[],parent:d});if(g){c.tmpl=g;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++h;(l.length?f:b)[h]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h<m;h++){c=h;k=(h>0?this.clone(true):this).get();a.fn[d].apply(a(i[h]),k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,l,j){if(d[0]&&d[0].nodeType){var f=a.makeArray(arguments),g=d.length,i=0,h;while(i<g&&!(h=a.data(d[i++],"tmplItem")));if(g>1)f[0]=[a.makeArray(d)];if(h&&c)f[2]=function(b){a.tmpl.afterManip(this,b,j)};r.apply(this,f)}else r.apply(this,arguments);c=0;!e&&a.tmpl.complete(b);return this}});a.extend({tmpl:function(d,h,e,c){var j,k=!c;if(k){c=p;d=a.template[d]||a.template(null,d);f={}}else if(!d){d=c.tmpl;b[c.key]=c;c.nodes=[];c.wrapped&&n(c,c.wrapped);return a(i(c,null,c.tmpl(a,c)))}if(!d)return[];if(typeof h==="function")h=h.call(c||{});e&&e.wrapped&&n(e,e.wrapped);j=a.isArray(h)?a.map(h,function(a){return a?g(e,c,d,a):null}):[g(e,c,d,h)];return k?a(i(c,null,j)):j},tmplItem:function(b){var c;if(b instanceof a)b=b[0];while(b&&b.nodeType===1&&!(c=a.data(b,"tmplItem"))&&(b=b.parentNode));return c||p},template:function(c,b){if(b){if(typeof b==="string")b=o(b);else if(b instanceof a)b=b[0]||{};if(b.nodeType)b=a.data(b,"tmpl")||a.data(b,"tmpl",o(b.innerHTML));return typeof c==="string"?(a.template[c]=b):b}return c?typeof c!=="string"?a.template(null,c):a.template[c]||a.template(null,q.test(c)?c:a(c)):null},encode:function(a){return(""+a).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){_=_.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(_,$1,$2);_=[];",close:"call=$item.calls();_=call._.concat($item.wrap(call,_));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){_.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){_.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function i(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:i(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=j(c).concat(b);if(d)b=b.concat(j(d))});return b?b:j(c)}function j(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,_=[],$data=$item.data;with($data){_.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,j,d,b,c,e){var i=a.tmpl.tag[j],h,f,g;if(!i)throw"Template command not found: "+j;h=i._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=k(b);e=e?","+k(e)+")":c?")":"";f=c?b.indexOf(".")>-1?b+c:"("+b+").call($item"+e:b;g=c?f:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else g=f=h.$1||"null";d=k(d);return"');"+i[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(g).split("$1").join(f).split("$2").join(d?d.replace(/\s*([^\(]+)\s*(\((.*?)\))?/g,function(d,c,b,a){a=a?","+a+")":b?")":"";return a?"("+c+").call($item"+a:d}):h.$2||"")+"_.push('"})+"');}return _;")}function n(c,b){c._wrap=i(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function k(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,i;for(e=0,p=o.length;e<p;e++){if((k=o[e]).nodeType!==1)continue;j=k.getElementsByTagName("*");for(i=j.length-1;i>=0;i--)m(j[i]);m(k)}function m(j){var p,i=j,k,e,m;if(m=j.getAttribute(d)){while(i.parentNode&&(i=i.parentNode).nodeType===1&&!(p=i.getAttribute(d)));if(p!==m){i=i.parentNode?i.nodeType===11?0:i.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[i]||f[i],null,true);e.key=++h;b[h]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;i=a.data(j.parentNode,"tmplItem");i=i?i.key:0}if(e){k=e;while(k&&k.key!=i){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent,null,true)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
body { | |
font-family: Helvetica, Arial, sans-serif; | |
} | |
.warrant-match-info { | |
color: #777; | |
} | |
.warrant-label { | |
color: #999; | |
text-align: right; | |
} | |
.warrant { | |
margin-bottom: 1em; | |
} | |
.content { | |
width: 320px; | |
margin: 0 auto; | |
} | |
.warrant-heading { | |
text-align: center; | |
margin-bottom: 1em; | |
} | |
.hidden { | |
display: none; | |
} | |
.col, .col-left, .col-right { | |
display: inline-block; | |
vertical-align: top; | |
margin-bottom: 0.4em; | |
} | |
.col-left { | |
width: 32%; | |
} | |
.col-right { | |
width: 65%; | |
} | |
.warrant-inline-info { | |
display: none; | |
} | |
.guider { | |
background: #333; | |
color: #fff; | |
/* hack! */ | |
bottom: 0 !important; | |
top: auto !important; | |
} | |
.guiders_content { | |
margin: 1em; | |
} | |
.guider a { | |
color: #fed; | |
} | |
.guiders_buttons_container { | |
text-align: right; | |
} | |
.guiders_highlight { | |
background: #def; | |
font-weight: bold; | |
padding: 0.4em 0; | |
margin: 0.4em 0; | |
position: relative; | |
z-index: 900003 !important; /* Should be larger than anything else on your page. */ | |
} | |
</style> | |
</head> | |
<body> | |
<div class="content"> | |
<h2>We Recommend...<br/>This Call Warrant!</h2> | |
<p class="warrant-match-info"></p> | |
<p class="warrant-match-info hidden"> | |
Hmm is that really your choice? Since you think the DBS stock price will decrease a little in a short term, we suggest you to buy this put warrant. | |
</p> | |
<div class="warrants"> | |
<!-- put warrant --> | |
<!-- | |
<div class="warrant warrant-put"> | |
<div class="warrant-heading"> | |
<div class="warrant-logo"> | |
<img srg="logo.png" alt="Warrant Logo" /> | |
</div> | |
<div class="warrant-name"> | |
DBS something something | |
</div> | |
<div class="warrant-code"> | |
DX8W | |
</div> | |
</div> | |
<div class="warrant-price"> | |
<span class="warrant-label">Price:</span> US$ 0.8 | |
</div> | |
<div class="warrant-type"> | |
<div><span class="warrant-label">Type:</span> Put</div> | |
<div>This put warrant gives you right to buy DBS share at a strike price ($12.0), on or before an expiry date (10 Jun 2013)</div> | |
</div> | |
<div class="warrant-strike-price"> | |
<div><span class="warrant-label">Strike Price</span> US$ 12.0</div> | |
<div>This is the price at which this warrant's underlying stock can be sold. Although the stock price changes, with this warrant you can sell with the strike price</div> | |
</div> | |
<div class="warrant-expiry-date"> | |
<div><span class="warrant-label">Expiry Date:</span> 10 Jun 2013</div> | |
<div>This is the deadline for using this warrant. If you don't use this warrant by that time (by selling this warrant or exercising), TradeHero will auto-sell the warrant for you.</div> | |
</div> | |
</div>--> | |
</div> | |
<form class="warrant-wizard-buy"> | |
<input type="hidden" name="securityJSON" value="" /> | |
<input type="submit" value="Buy This Warrant Now" /> | |
</form> | |
</div> | |
<script type="text/tmpl" id="warrant-match-info-template"> | |
${randomCommentary} | |
Since you feel that ${warrant.name} will ${priceDirectionVerb} in a ${timeframeText} term, we suggest that you buy this ${warrant.warrantTypeDesc} warrant. | |
</script> | |
<script type="text/tmpl" id="warrant-template"> | |
<div class="warrant"> | |
<div class="warrant-heading"> | |
<div class="warrant-logo"> | |
<img src="${imageBlobUrl}" alt="${name}" /> | |
</div> | |
<div class="warrant-name"> | |
${name} | |
</div> | |
</div> | |
<div class="warrant-type"> | |
<div class="warrant-label col-left"> | |
Type: | |
</div> | |
<span class="warrant-inline-info" data-highlight-selector=".warrant-type"> | |
This ${warrantTypeDesc} warrant gives you the right to buy DBS share at a strike price (${currencyDisplay} ${strikePrice}), on or before an expiry date (${expiryDateString}). | |
</span> | |
<div class="col-right"> | |
${warrantTypeDescTitleized} | |
</div> | |
</div> | |
<div class="warrant-symbol"> | |
<div class="warrant-label col-left"> | |
Symbol: | |
</div> | |
<div class="col-right">${symbol}</div> | |
</div> | |
<div class="warrant-price"> | |
<div class="warrant-label col-left"> | |
Price: | |
</div> | |
<div class="col-right">${currencyDisplay} ${lastPrice}</div> | |
</div> | |
<div class="warrant-strike-price"> | |
<div class="warrant-label col-left"> | |
Strike Price: | |
</div> | |
<span class="warrant-inline-info" data-highlight-selector=".warrant-strike-price"> | |
This is the price at which this warrant's underlying stock can be bought. Although the stock price changes, with this warrant you can buy with this price. | |
</span> | |
<div class="col-right"> | |
${currencyDisplay} ${strikePrice} | |
</div> | |
</div> | |
<div class="warrant-expiry-date"> | |
<div class="warrant-label col-left"> | |
Expiry Date: | |
</div> | |
<span class="warrant-inline-info" data-highlight-selector=".warrant-expiry-date"> | |
This is the deadline for using this warrant. If you don't use this warrant by that time (by selling this warrant or exercising), TradeHero will auto-sell the warrant for you. | |
</span> | |
<div class="col-right"> | |
${expiryDateString} | |
</div> | |
</div> | |
</div> | |
</script> | |
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> | |
<script src="jquery.tmpl.min.js"></script> | |
<script src="guiders.js"></script> | |
<script type="text/javascript"> | |
(function() { | |
$.template('warrantMatchInfoTemplate', $('#warrant-match-info-template').html()); | |
$.template('warrantTemplate', $('#warrant-template').html()); | |
var warrant = { | |
name: "DBS 123 123", | |
warrantTypeDesc: "call", | |
warrantTypeDescTitleized: "Call", | |
currencyDisplay: "SG$", | |
imageBlobUrl: "http://placehold.it/120x80", | |
symbol: "FTSE", | |
lastPrice: 1.0029.toFixed(2), | |
strikePrice: 10.4378.toFixed(2), | |
expiryDateString: "10 Jun 2014" | |
}, matchInfo = { | |
warrant: warrant, | |
priceDirectionVerb: "increase", | |
randomCommentary: "Nice choice!", | |
timeframeText: "short" | |
}; | |
$.tmpl('warrantMatchInfoTemplate', matchInfo).appendTo('.warrant-match-info'); | |
$.tmpl('warrantTemplate', warrant).appendTo('.warrants'); | |
var $allWarrantInfo = $('.warrant-inline-info'), warrantInfoLastIndex = $allWarrantInfo.length - 1; | |
$allWarrantInfo.each(function(index, value) { | |
var $t = $(this), guidersOpts = { | |
description: $t.html(), | |
id: "guider-" + index, | |
title: "", | |
highlight: $t.data('highlight-selector'), | |
width: "auto", | |
offset: { left: 0, bottom: 0 }, | |
onShow: function(el) { | |
$(el.highlight).addClass('guiders_highlight'); | |
}, | |
onHide: function(el) { | |
$(el.highlight).removeClass('guiders_highlight'); | |
} | |
}; | |
if (index < warrantInfoLastIndex) { | |
guidersOpts.next = "guider-" + (index+1); | |
guidersOpts.buttons = [{name: "Next"}]; | |
} | |
var g = guiders.createGuider(guidersOpts); | |
if (index == 0) { | |
g.show(); | |
} | |
}); | |
})(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment