From 47106be99c1afe45bcef738e4ae9c5f8887d65d5 Mon Sep 17 00:00:00 2001
From: Henry <akhenry@gmail.com>
Date: Sun, 10 Apr 2016 17:14:34 -0700
Subject: [PATCH] Initial tour

---
 demo/bundle.js                                |   13 +-
 demo/lib/hopscotch/hopscotch.min.js           |   17 +
 demo/lib/shepherd/shepherd.min.js             |    1 +
 demo/lib/tether/tether.js                     | 1443 +++++++++++++++++
 demo/res/img/sprite-green.png                 |  Bin 0 -> 5405 bytes
 demo/res/img/sprite-orange.png                |  Bin 0 -> 5374 bytes
 demo/src/DemoInitializer.js                   |   80 +-
 demo/src/conductor/ConductorPolicy.js         |    8 +-
 .../src/conductor/DemoConductorRepresenter.js |    7 +-
 9 files changed, 1561 insertions(+), 8 deletions(-)
 create mode 100755 demo/lib/hopscotch/hopscotch.min.js
 create mode 100755 demo/lib/shepherd/shepherd.min.js
 create mode 100755 demo/lib/tether/tether.js
 create mode 100755 demo/res/img/sprite-green.png
 create mode 100755 demo/res/img/sprite-orange.png

diff --git a/demo/bundle.js b/demo/bundle.js
index 911fe84b46..22f7a4a110 100644
--- a/demo/bundle.js
+++ b/demo/bundle.js
@@ -45,7 +45,7 @@ define([
             "representers": [
                 {
                     "implementation": DemoConductorRepresenter,
-                    "depends": ["$q", "$compile", "conductorService", "views[]", "throttle"]
+                    "depends": ["$q", "$compile", "conductorService", "views[]", "throttle", "navigationService"]
                 }
             ],
             "components": [
@@ -71,6 +71,7 @@ define([
                 {
                     "implementation": DemoInitializer,
                     "depends": [
+                        "$timeout",
                         "representers[]"
                     ]
                 }
@@ -104,6 +105,16 @@ define([
                         ]
                     }
                 }
+            ],
+            "stylesheets": [
+                {
+                    "stylesheetUrl": "css/hopscotch.css",
+                    priority: "fallback"
+
+                },
+                {
+                    "stylesheetUrl": "css/tour.css"
+                }
             ]
         }
     });
diff --git a/demo/lib/hopscotch/hopscotch.min.js b/demo/lib/hopscotch/hopscotch.min.js
new file mode 100755
index 0000000000..40cb26cffb
--- /dev/null
+++ b/demo/lib/hopscotch/hopscotch.min.js
@@ -0,0 +1,17 @@
+/**! hopscotch - v0.2.5
+*
+* Copyright 2015 LinkedIn Corp. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+!function(a,b){"use strict";if("function"==typeof define&&define.amd)define([],b);else if("object"==typeof exports)module.exports=b();else{var c="hopscotch";if(a[c])return;a[c]=b()}}(this,function(){var Hopscotch,HopscotchBubble,HopscotchCalloutManager,HopscotchI18N,customI18N,customRenderer,customEscape,utils,callbacks,helpers,winLoadHandler,defaultOpts,winHopscotch,templateToUse="bubble_default",Sizzle=window.Sizzle||null,undefinedStr="undefined",waitingToStart=!1,hasJquery=typeof jQuery!==undefinedStr,hasSessionStorage=!1,isStorageWritable=!1,document=window.document,validIdRegEx=/^[a-zA-Z]+[a-zA-Z0-9_-]*$/,rtlMatches={left:"right",right:"left"};try{typeof window.sessionStorage!==undefinedStr&&(hasSessionStorage=!0,sessionStorage.setItem("hopscotch.test.storage","ok"),sessionStorage.removeItem("hopscotch.test.storage"),isStorageWritable=!0)}catch(err){}return defaultOpts={smoothScroll:!0,scrollDuration:1e3,scrollTopMargin:200,showCloseButton:!0,showPrevButton:!1,showNextButton:!0,bubbleWidth:280,bubblePadding:15,arrowWidth:20,skipIfNoElement:!0,isRtl:!1,cookieName:"hopscotch.tour.state"},Array.isArray||(Array.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)}),winLoadHandler=function(){waitingToStart&&winHopscotch.startTour()},utils={addClass:function(a,b){var c,d,e,f;if(a.className){for(d=b.split(/\s+/),c=" "+a.className+" ",e=0,f=d.length;f>e;++e)c.indexOf(" "+d[e]+" ")<0&&(c+=d[e]+" ");a.className=c.replace(/^\s+|\s+$/g,"")}else a.className=b},removeClass:function(a,b){var c,d,e,f;for(d=b.split(/\s+/),c=" "+a.className+" ",e=0,f=d.length;f>e;++e)c=c.replace(" "+d[e]+" "," ");a.className=c.replace(/^\s+|\s+$/g,"")},hasClass:function(a,b){var c;return a.className?(c=" "+a.className+" ",-1!==c.indexOf(" "+b+" ")):!1},getPixelValue:function(a){var b=typeof a;return"number"===b?a:"string"===b?parseInt(a,10):0},valOrDefault:function(a,b){return typeof a!==undefinedStr?a:b},invokeCallbackArrayHelper:function(a){var b;return Array.isArray(a)&&(b=helpers[a[0]],"function"==typeof b)?b.apply(this,a.slice(1)):void 0},invokeCallbackArray:function(a){var b,c;if(Array.isArray(a)){if("string"==typeof a[0])return utils.invokeCallbackArrayHelper(a);for(b=0,c=a.length;c>b;++b)utils.invokeCallback(a[b])}},invokeCallback:function(a){return"function"==typeof a?a():"string"==typeof a&&helpers[a]?helpers[a]():utils.invokeCallbackArray(a)},invokeEventCallbacks:function(a,b){var c,d,e=callbacks[a];if(b)return this.invokeCallback(b);for(c=0,d=e.length;d>c;++c)this.invokeCallback(e[c].cb)},getScrollTop:function(){var a;return a=typeof window.pageYOffset!==undefinedStr?window.pageYOffset:document.documentElement.scrollTop},getScrollLeft:function(){var a;return a=typeof window.pageXOffset!==undefinedStr?window.pageXOffset:document.documentElement.scrollLeft},getWindowHeight:function(){return window.innerHeight||document.documentElement.clientHeight},addEvtListener:function(a,b,c){return a?a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c):void 0},removeEvtListener:function(a,b,c){return a?a.removeEventListener?a.removeEventListener(b,c,!1):a.detachEvent("on"+b,c):void 0},documentIsReady:function(){return"complete"===document.readyState},evtPreventDefault:function(a){a.preventDefault?a.preventDefault():event&&(event.returnValue=!1)},extend:function(a,b){var c;for(c in b)b.hasOwnProperty(c)&&(a[c]=b[c])},getStepTargetHelper:function(a){var b=document.getElementById(a);if(b)return b;if(hasJquery)return b=jQuery(a),b.length?b[0]:null;if(Sizzle)return b=new Sizzle(a),b.length?b[0]:null;if(document.querySelector)try{return document.querySelector(a)}catch(c){}return/^#[a-zA-Z][\w-_:.]*$/.test(a)?document.getElementById(a.substring(1)):null},getStepTarget:function(a){var b;if(!a||!a.target)return null;if("string"==typeof a.target)return utils.getStepTargetHelper(a.target);if(Array.isArray(a.target)){var c,d;for(c=0,d=a.target.length;d>c;c++)if("string"==typeof a.target[c]&&(b=utils.getStepTargetHelper(a.target[c])))return b;return null}return a.target},getI18NString:function(a){return customI18N[a]||HopscotchI18N[a]},setState:function(a,b,c){var d,e="";if(hasSessionStorage&&isStorageWritable)try{sessionStorage.setItem(a,b)}catch(f){isStorageWritable=!1,this.setState(a,b,c)}else hasSessionStorage&&sessionStorage.removeItem(a),c&&(d=new Date,d.setTime(d.getTime()+24*c*60*60*1e3),e="; expires="+d.toGMTString()),document.cookie=a+"="+b+e+"; path=/"},getState:function(a){var b,c,d,e=a+"=",f=document.cookie.split(";");if(hasSessionStorage&&(d=sessionStorage.getItem(a)))return d;for(b=0;b<f.length;b++){for(c=f[b];" "===c.charAt(0);)c=c.substring(1,c.length);if(0===c.indexOf(e)){d=c.substring(e.length,c.length);break}}return d},clearState:function(a){hasSessionStorage?sessionStorage.removeItem(a):this.setState(a,"",-1)},normalizePlacement:function(a){!a.placement&&a.orientation&&(a.placement=a.orientation)},flipPlacement:function(a){if(a.isRtl&&!a._isFlipped){var b,c,d=["orientation","placement"];a.xOffset&&(a.xOffset=-1*this.getPixelValue(a.xOffset));for(c in d)b=d[c],a.hasOwnProperty(b)&&rtlMatches.hasOwnProperty(a[b])&&(a[b]=rtlMatches[a[b]]);a._isFlipped=!0}}},utils.addEvtListener(window,"load",winLoadHandler),callbacks={next:[],prev:[],start:[],end:[],show:[],error:[],close:[]},helpers={},HopscotchI18N={stepNums:null,nextBtn:"Next",prevBtn:"Back",doneBtn:"Done",skipBtn:"Skip",closeTooltip:"Close"},customI18N={},HopscotchBubble=function(a){this.init(a)},HopscotchBubble.prototype={isShowing:!1,currStep:void 0,setPosition:function(a){var b,c,d,e,f,g,h,i=utils.getStepTarget(a),j=this.element,k=this.arrowEl,l=a.isRtl?"right":"left";if(utils.flipPlacement(a),utils.normalizePlacement(a),c=j.offsetWidth,b=j.offsetHeight,utils.removeClass(j,"fade-in-down fade-in-up fade-in-left fade-in-right"),d=i.getBoundingClientRect(),h=a.isRtl?d.right-c:d.left,"top"===a.placement)e=d.top-b-this.opt.arrowWidth,f=h;else if("bottom"===a.placement)e=d.bottom+this.opt.arrowWidth,f=h;else if("left"===a.placement)e=d.top,f=d.left-c-this.opt.arrowWidth;else{if("right"!==a.placement)throw new Error("Bubble placement failed because step.placement is invalid or undefined!");e=d.top,f=d.right+this.opt.arrowWidth}g="center"!==a.arrowOffset?utils.getPixelValue(a.arrowOffset):a.arrowOffset,g?"top"===a.placement||"bottom"===a.placement?(k.style.top="","center"===g?k.style[l]=Math.floor(c/2-k.offsetWidth/2)+"px":k.style[l]=g+"px"):("left"===a.placement||"right"===a.placement)&&(k.style[l]="","center"===g?k.style.top=Math.floor(b/2-k.offsetHeight/2)+"px":k.style.top=g+"px"):(k.style.top="",k.style[l]=""),"center"===a.xOffset?f=d.left+i.offsetWidth/2-c/2:f+=utils.getPixelValue(a.xOffset),"center"===a.yOffset?e=d.top+i.offsetHeight/2-b/2:e+=utils.getPixelValue(a.yOffset),a.fixedElement||(e+=utils.getScrollTop(),f+=utils.getScrollLeft()),j.style.position=a.fixedElement?"fixed":"absolute",j.style.top=e+"px",j.style.left=f+"px"},render:function(a,b,c){var d,e,f,g,h,j,k,l,m,n=this.element;if(a?this.currStep=a:this.currStep&&(a=this.currStep),this.opt.isTourBubble?(g=winHopscotch.getCurrTour(),g&&(e=g.customData,d=g.customRenderer,a.isRtl=a.hasOwnProperty("isRtl")?a.isRtl:g.hasOwnProperty("isRtl")?g.isRtl:this.opt.isRtl,f=g.unsafe,Array.isArray(g.steps)&&(h=g.steps.length,j=this._getStepI18nNum(this._getStepNum(h-1)),l=this._getStepNum(b)===this._getStepNum(h-1)))):(e=a.customData,d=a.customRenderer,f=a.unsafe,a.isRtl=a.hasOwnProperty("isRtl")?a.isRtl:this.opt.isRtl),k=utils.getI18NString(l?"doneBtn":a.showSkip?"skipBtn":"nextBtn"),utils.flipPlacement(a),utils.normalizePlacement(a),this.placement=a.placement,m={i18n:{prevBtn:utils.getI18NString("prevBtn"),nextBtn:k,closeTooltip:utils.getI18NString("closeTooltip"),stepNum:this._getStepI18nNum(this._getStepNum(b)),numSteps:j},buttons:{showPrev:utils.valOrDefault(a.showPrevButton,this.opt.showPrevButton)&&this._getStepNum(b)>0,showNext:utils.valOrDefault(a.showNextButton,this.opt.showNextButton),showCTA:utils.valOrDefault(a.showCTAButton&&a.ctaLabel,!1),ctaLabel:a.ctaLabel,showClose:utils.valOrDefault(this.opt.showCloseButton,!0)},step:{num:b,isLast:utils.valOrDefault(l,!1),title:a.title||"",content:a.content||"",isRtl:a.isRtl,placement:a.placement,padding:utils.valOrDefault(a.padding,this.opt.bubblePadding),width:utils.getPixelValue(a.width)||this.opt.bubbleWidth,customData:a.customData||{}},tour:{isTour:this.opt.isTourBubble,numSteps:h,unsafe:utils.valOrDefault(f,!1),customData:e||{}}},"function"==typeof d)n.innerHTML=d(m);else if("string"==typeof d){if(!winHopscotch.templates||"function"!=typeof winHopscotch.templates[d])throw new Error('Bubble rendering failed - template "'+d+'" is not a function.');n.innerHTML=winHopscotch.templates[d](m)}else if(customRenderer)n.innerHTML=customRenderer(m);else{if(!winHopscotch.templates||"function"!=typeof winHopscotch.templates[templateToUse])throw new Error('Bubble rendering failed - template "'+templateToUse+'" is not a function.');n.innerHTML=winHopscotch.templates[templateToUse](m)}for(children=n.children,numChildren=children.length,i=0;i<numChildren;i++)node=children[i],utils.hasClass(node,"hopscotch-arrow")&&(this.arrowEl=node);return n.style.zIndex="number"==typeof a.zindex?a.zindex:"",this._setArrow(a.placement),this.hide(!1),this.setPosition(a),c&&c(!a.fixedElement),this},_getStepNum:function(a){var b,c,d=0,e=winHopscotch.getSkippedStepsIndexes(),f=e.length;for(c=0;f>c;c++)b=e[c],a>b&&d++;return a-d},_getStepI18nNum:function(a){var b=utils.getI18NString("stepNums");return b&&a<b.length?a=b[a]:a+=1,a},_setArrow:function(a){utils.removeClass(this.arrowEl,"down up right left"),"top"===a?utils.addClass(this.arrowEl,"down"):"bottom"===a?utils.addClass(this.arrowEl,"up"):"left"===a?utils.addClass(this.arrowEl,"right"):"right"===a&&utils.addClass(this.arrowEl,"left")},_getArrowDirection:function(){return"top"===this.placement?"down":"bottom"===this.placement?"up":"left"===this.placement?"right":"right"===this.placement?"left":void 0},show:function(){var a=this,b="fade-in-"+this._getArrowDirection(),c=1e3;return utils.removeClass(this.element,"hide"),utils.addClass(this.element,b),setTimeout(function(){utils.removeClass(a.element,"invisible")},50),setTimeout(function(){utils.removeClass(a.element,b)},c),this.isShowing=!0,this},hide:function(a){var b=this.element;return a=utils.valOrDefault(a,!0),b.style.top="",b.style.left="",a?(utils.addClass(b,"hide"),utils.removeClass(b,"invisible")):(utils.removeClass(b,"hide"),utils.addClass(b,"invisible")),utils.removeClass(b,"animate fade-in-up fade-in-down fade-in-right fade-in-left"),this.isShowing=!1,this},destroy:function(){var a=this.element;a&&a.parentNode.removeChild(a),utils.removeEvtListener(a,"click",this.clickCb)},_handleBubbleClick:function(a){function b(c){return c===a.currentTarget?null:utils.hasClass(c,"hopscotch-cta")?"cta":utils.hasClass(c,"hopscotch-next")?"next":utils.hasClass(c,"hopscotch-prev")?"prev":utils.hasClass(c,"hopscotch-close")?"close":b(c.parentElement)}var c;a=a||window.event;var d=a.target||a.srcElement;if(c=b(d),"cta"===c)this.opt.isTourBubble||winHopscotch.getCalloutManager().removeCallout(this.currStep.id),this.currStep.onCTA&&utils.invokeCallback(this.currStep.onCTA);else if("next"===c)winHopscotch.nextStep(!0);else if("prev"===c)winHopscotch.prevStep(!0);else if("close"===c){if(this.opt.isTourBubble){var e=winHopscotch.getCurrStepNum(),f=winHopscotch.getCurrTour(),g=e===f.steps.length-1;utils.invokeEventCallbacks("close"),winHopscotch.endTour(!0,g)}else this.opt.onClose&&utils.invokeCallback(this.opt.onClose),this.opt.id&&!this.opt.isTourBubble?winHopscotch.getCalloutManager().removeCallout(this.opt.id):this.destroy();utils.evtPreventDefault(a)}},init:function(a){var b,c,d,e,f=document.createElement("div"),g=this,h=!1;this.element=f,e={showPrevButton:defaultOpts.showPrevButton,showNextButton:defaultOpts.showNextButton,bubbleWidth:defaultOpts.bubbleWidth,bubblePadding:defaultOpts.bubblePadding,arrowWidth:defaultOpts.arrowWidth,isRtl:defaultOpts.isRtl,showNumber:!0,isTourBubble:!0},a=typeof a===undefinedStr?{}:a,utils.extend(e,a),this.opt=e,f.className="hopscotch-bubble animated",e.isTourBubble?(d=winHopscotch.getCurrTour(),d&&utils.addClass(f,"tour-"+d.id)):utils.addClass(f,"hopscotch-callout no-number"),b=function(){!h&&g.isShowing&&(h=!0,setTimeout(function(){g.setPosition(g.currStep),h=!1},100))},utils.addEvtListener(window,"resize",b),this.clickCb=function(a){g._handleBubbleClick(a)},utils.addEvtListener(f,"click",this.clickCb),this.hide(),utils.documentIsReady()?document.body.appendChild(f):(document.addEventListener?(c=function(){document.removeEventListener("DOMContentLoaded",c),window.removeEventListener("load",c),document.body.appendChild(f)},document.addEventListener("DOMContentLoaded",c,!1)):(c=function(){"complete"===document.readyState&&(document.detachEvent("onreadystatechange",c),window.detachEvent("onload",c),document.body.appendChild(f))},document.attachEvent("onreadystatechange",c)),utils.addEvtListener(window,"load",c))}},HopscotchCalloutManager=function(){var a={},b={};this.createCallout=function(c){var d;if(!c.id)throw new Error("Must specify a callout id.");if(!validIdRegEx.test(c.id))throw new Error("Callout ID is using an invalid format. Use alphanumeric, underscores, and/or hyphens only. First character must be a letter.");if(a[c.id])throw new Error("Callout by that id already exists. Please choose a unique id.");if(!utils.getStepTarget(c))throw new Error("Must specify existing target element via 'target' option.");return c.showNextButton=c.showPrevButton=!1,c.isTourBubble=!1,d=new HopscotchBubble(c),a[c.id]=d,b[c.id]=c,d.render(c,null,function(){d.show(),c.onShow&&utils.invokeCallback(c.onShow)}),d},this.getCallout=function(b){return a[b]},this.removeAllCallouts=function(){var b;for(b in a)a.hasOwnProperty(b)&&this.removeCallout(b)},this.removeCallout=function(c){var d=a[c];a[c]=null,b[c]=null,d&&d.destroy()},this.refreshCalloutPositions=function(){var c,d,e;for(c in a)a.hasOwnProperty(c)&&b.hasOwnProperty(c)&&(d=a[c],e=b[c],d&&e&&d.setPosition(e))}},Hopscotch=function(a){var b,c,d,e,f,g,h,i,j=this,k={},l=[],m=function(a){return b&&b.element&&b.element.parentNode||(b=new HopscotchBubble(d)),a&&utils.extend(b.opt,{bubblePadding:o("bubblePadding"),bubbleWidth:o("bubbleWidth"),showNextButton:o("showNextButton"),showPrevButton:o("showPrevButton"),showCloseButton:o("showCloseButton"),arrowWidth:o("arrowWidth"),isRtl:o("isRtl")}),b},n=function(){b&&(b.destroy(),b=null)},o=function(a){return"undefined"==typeof d?defaultOpts[a]:utils.valOrDefault(d[a],defaultOpts[a])},p=function(){var a;return a=!e||0>f||f>=e.steps.length?null:e.steps[f]},q=function(){j.nextStep()},r=function(a){var b,c,d,e,f,g,h=m(),i=h.element,j=utils.getPixelValue(i.style.top),k=j+utils.getPixelValue(i.offsetHeight),l=utils.getStepTarget(p()),n=l.getBoundingClientRect(),q=n.top+utils.getScrollTop(),r=n.bottom+utils.getScrollTop(),s=q>j?j:q,t=k>r?k:r,u=utils.getScrollTop(),v=u+utils.getWindowHeight(),w=s-o("scrollTopMargin");s>=u&&(s<=u+o("scrollTopMargin")||v>=t)?a&&a():o("smoothScroll")?typeof YAHOO!==undefinedStr&&typeof YAHOO.env!==undefinedStr&&typeof YAHOO.env.ua!==undefinedStr&&typeof YAHOO.util!==undefinedStr&&typeof YAHOO.util.Scroll!==undefinedStr?(b=YAHOO.env.ua.webkit?document.body:document.documentElement,d=YAHOO.util.Easing?YAHOO.util.Easing.easeOut:void 0,c=new YAHOO.util.Scroll(b,{scroll:{to:[0,w]}},o("scrollDuration")/1e3,d),c.onComplete.subscribe(a),c.animate()):hasJquery?jQuery("body, html").animate({scrollTop:w},o("scrollDuration"),a):(0>w&&(w=0),e=u>s?-1:1,f=Math.abs(u-w)/(o("scrollDuration")/10),(g=function(){var b=utils.getScrollTop(),c=b+e*f;return e>0&&c>=w||0>e&&w>=c?(c=w,a&&a(),void window.scrollTo(0,c)):(window.scrollTo(0,c),utils.getScrollTop()===b?void(a&&a()):void setTimeout(g,10))})()):(window.scrollTo(0,w),a&&a())},s=function(a,b){var c,d,g;f+a>=0&&f+a<e.steps.length?(f+=a,d=p(),g=function(){c=utils.getStepTarget(d),c?(k[f]&&delete k[f],b(f)):(k[f]=!0,utils.invokeEventCallbacks("error"),s(a,b))},d.delay?setTimeout(g,d.delay):g()):b(-1)},t=function(a,b){var c,d,g,h,i=m(),j=this;if(i.hide(),a=utils.valOrDefault(a,!0),c=p(),c.nextOnTargetClick&&utils.removeEvtListener(utils.getStepTarget(c),"click",q),d=c,g=b>0?d.multipage:f>0&&e.steps[f-1].multipage,h=function(c){var e;if(-1===c)return this.endTour(!0);if(a&&(e=b>0?utils.invokeEventCallbacks("next",d.onNext):utils.invokeEventCallbacks("prev",d.onPrev)),c===f){if(g)return void x();e=utils.valOrDefault(e,!0),e?this.showStep(c):this.endTour(!1)}},!g&&o("skipIfNoElement"))s(b,function(a){h.call(j,a)});else if(f+b>=0&&f+b<e.steps.length){if(f+=b,c=p(),!utils.getStepTarget(c)&&!g)return utils.invokeEventCallbacks("error"),this.endTour(!0,!1);h.call(this,f)}else if(f+b===e.steps.length)return this.endTour();return this},u=function(a){var b,c,d,e={};for(b in a)a.hasOwnProperty(b)&&"id"!==b&&"steps"!==b&&(e[b]=a[b]);return i.call(this,e,!0),c=utils.getState(o("cookieName")),c&&(d=c.split(":"),g=d[0],h=d[1],d.length>2&&(l=d[2].split(",")),h=parseInt(h,10)),this},v=function(a,b,c){var d,e;if(f=a||0,k=b||{},d=p(),e=utils.getStepTarget(d))return void c(f);if(!e){if(utils.invokeEventCallbacks("error"),k[f]=!0,o("skipIfNoElement"))return void s(1,c);f=-1,c(f)}},w=function(a){function b(){d.show(),utils.invokeEventCallbacks("show",c.onShow)}var c=e.steps[a],d=m(),g=utils.getStepTarget(c);f!==a&&p().nextOnTargetClick&&utils.removeEvtListener(utils.getStepTarget(p()),"click",q),f=a,d.hide(!1),d.render(c,a,function(a){a?r(b):b(),c.nextOnTargetClick&&utils.addEvtListener(g,"click",q)}),x()},x=function(){var a=e.id+":"+f,b=winHopscotch.getSkippedStepsIndexes();b&&b.length>0&&(a+=":"+b.join(",")),utils.setState(o("cookieName"),a,1)},y=function(a){a&&this.configure(a)};this.getCalloutManager=function(){return typeof c===undefinedStr&&(c=new HopscotchCalloutManager),c},this.startTour=function(a,b){var c,d,f={},i=this;if(!e){if(!a)throw new Error("Tour data is required for startTour.");if(!a.id||!validIdRegEx.test(a.id))throw new Error("Tour ID is using an invalid format. Use alphanumeric, underscores, and/or hyphens only. First character must be a letter.");e=a,u.call(this,a)}if(typeof b!==undefinedStr){if(b>=e.steps.length)throw new Error("Specified step number out of bounds.");d=b}if(!utils.documentIsReady())return waitingToStart=!0,this;if("undefined"==typeof d&&e.id===g&&typeof h!==undefinedStr){if(d=h,l.length>0)for(var j=0,k=l.length;k>j;j++)f[l[j]]=!0}else d||(d=0);return v(d,f,function(a){var b=-1!==a&&utils.getStepTarget(e.steps[a]);return b?(utils.invokeEventCallbacks("start"),c=m(),c.hide(!1),i.isActive=!0,void(utils.getStepTarget(p())?i.showStep(a):(utils.invokeEventCallbacks("error"),o("skipIfNoElement")&&i.nextStep(!1)))):void i.endTour(!1,!1)}),this},this.showStep=function(a){var b=e.steps[a];if(utils.getStepTarget(b))return b.delay?setTimeout(function(){w(a)},b.delay):w(a),this},this.prevStep=function(a){return t.call(this,a,-1),this},this.nextStep=function(a){return t.call(this,a,1),this},this.endTour=function(a,b){var c,d=m();return a=utils.valOrDefault(a,!0),b=utils.valOrDefault(b,!0),e&&(c=p(),c&&c.nextOnTargetClick&&utils.removeEvtListener(utils.getStepTarget(c),"click",q)),f=0,h=void 0,d.hide(),a&&utils.clearState(o("cookieName")),this.isActive&&(this.isActive=!1,e&&b&&utils.invokeEventCallbacks("end")),this.removeCallbacks(null,!0),this.resetDefaultOptions(),n(),e=null,this},this.getCurrTour=function(){return e},this.getCurrTarget=function(){return utils.getStepTarget(p())},this.getCurrStepNum=function(){return f},this.getSkippedStepsIndexes=function(){var a,b=[];for(a in k)b.push(a);return b},this.refreshBubblePosition=function(){var a=p();return a&&m().setPosition(a),this.getCalloutManager().refreshCalloutPositions(),this},this.listen=function(a,b,c){return a&&callbacks[a].push({cb:b,fromTour:c}),this},this.unlisten=function(a,b){var c,d,e=callbacks[a];for(c=0,d=e.length;d>c;++c)e[c]===b&&e.splice(c,1);return this},this.removeCallbacks=function(a,b){var c,d,e,f;for(f in callbacks)if(!a||a===f)if(b)for(c=callbacks[f],d=0,e=c.length;e>d;++d)c[d].fromTour&&(c.splice(d--,1),--e);else callbacks[f]=[];return this},this.registerHelper=function(a,b){"string"==typeof a&&"function"==typeof b&&(helpers[a]=b)},this.unregisterHelper=function(a){helpers[a]=null},this.invokeHelper=function(a){var b,c,d=[];for(b=1,c=arguments.length;c>b;++b)d.push(arguments[b]);helpers[a]&&helpers[a].call(null,d)},this.setCookieName=function(a){return d.cookieName=a,this},this.resetDefaultOptions=function(){return d={},this},this.resetDefaultI18N=function(){return customI18N={},this},this.getState=function(){return utils.getState(o("cookieName"))},i=function(a,b){var c,e,f,g,h=["next","prev","start","end","show","error","close"];for(d||this.resetDefaultOptions(),utils.extend(d,a),a&&utils.extend(customI18N,a.i18n),f=0,g=h.length;g>f;++f)e="on"+h[f].charAt(0).toUpperCase()+h[f].substring(1),a[e]&&this.listen(h[f],a[e],b);return c=m(!0),this},this.configure=function(a){return i.call(this,a,!1)},this.setRenderer=function(a){var b=typeof a;return"string"===b?(templateToUse=a,customRenderer=void 0):"function"===b&&(customRenderer=a),this},this.setEscaper=function(a){return"function"==typeof a&&(customEscape=a),this},y.call(this,a)},winHopscotch=new Hopscotch,function(){var _={};_.escape=function(a){return customEscape?customEscape(a):null==a?"":(""+a).replace(new RegExp("[&<>\"']","g"),function(a){return"&"==a?"&amp;":"<"==a?"&lt;":">"==a?"&gt;":'"'==a?"&quot;":"'"==a?"&#x27;":void 0})},this.templates=this.templates||{},this.templates.bubble_default=function(obj){function optEscape(a,b){return b?_.escape(a):a}obj||(obj={});var __t,__p="";_.escape,Array.prototype.join;with(obj)__p+='\n<div class="hopscotch-bubble-container" style="width: '+(null==(__t=step.width)?"":__t)+"px; padding: "+(null==(__t=step.padding)?"":__t)+'px;">\n  ',tour.isTour&&(__p+='<span class="hopscotch-bubble-number">'+(null==(__t=i18n.stepNum)?"":__t)+"</span>"),__p+='\n  <div class="hopscotch-bubble-content">\n    ',""!==step.title&&(__p+='<h3 class="hopscotch-title">'+(null==(__t=optEscape(step.title,tour.unsafe))?"":__t)+"</h3>"),__p+="\n    ",""!==step.content&&(__p+='<div class="hopscotch-content">'+(null==(__t=optEscape(step.content,tour.unsafe))?"":__t)+"</div>"),__p+='\n  </div>\n  <div class="hopscotch-actions">\n    ',buttons.showPrev&&(__p+='<button class="hopscotch-nav-button prev hopscotch-prev">'+(null==(__t=i18n.prevBtn)?"":__t)+"</button>"),__p+="\n    ",buttons.showCTA&&(__p+='<button class="hopscotch-nav-button next hopscotch-cta">'+(null==(__t=buttons.ctaLabel)?"":__t)+"</button>"),__p+="\n    ",buttons.showNext&&(__p+='<button class="hopscotch-nav-button next hopscotch-next">'+(null==(__t=i18n.nextBtn)?"":__t)+"</button>"),__p+="\n  </div>\n  ",buttons.showClose&&(__p+='<button class="hopscotch-bubble-close hopscotch-close">'+(null==(__t=i18n.closeTooltip)?"":__t)+"</button>"),__p+='\n</div>\n<div class="hopscotch-bubble-arrow-container hopscotch-arrow">\n  <div class="hopscotch-bubble-arrow-border"></div>\n  <div class="hopscotch-bubble-arrow"></div>\n</div>';return __p}}.call(winHopscotch),winHopscotch});
\ No newline at end of file
diff --git a/demo/lib/shepherd/shepherd.min.js b/demo/lib/shepherd/shepherd.min.js
new file mode 100755
index 0000000000..3b446ec61c
--- /dev/null
+++ b/demo/lib/shepherd/shepherd.min.js
@@ -0,0 +1 @@
+!function(n,i){"function"==typeof define&&define.amd?define(["tether"],i):"object"==typeof exports?module.exports=i(require("tether")):n.Shepherd=i(n.Tether)}(this,function(Tether){"use strict";function n(n,i){if(!(n instanceof i))throw new TypeError("Cannot call a class as a function")}function i(n,i){if("function"!=typeof i&&null!==i)throw new TypeError("Super expression must either be null or a function, not "+typeof i);n.prototype=Object.create(i&&i.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),i&&(Object.setPrototypeOf?Object.setPrototypeOf(n,i):n.__proto__=i)}function s(n){return"undefined"==typeof n}function o(n){return n&&n.constructor===Array}function c(n){return n&&n.constructor===Object}function a(n){return"object"==typeof n}function u(n){var i=document.createElement("div");return i.innerHTML=n,i.children[0]}function l(n,i){var o=void 0;return s(n.matches)?s(n.matchesSelector)?s(n.msMatchesSelector)?s(n.webkitMatchesSelector)?s(n.mozMatchesSelector)?s(n.oMatchesSelector)||(o=n.oMatchesSelector):o=n.mozMatchesSelector:o=n.webkitMatchesSelector:o=n.msMatchesSelector:o=n.matchesSelector:o=n.matches,o.call(n,i)}function p(n){if(a(n))return n.hasOwnProperty("element")&&n.hasOwnProperty("on")?n:null;var i=C.exec(n);if(!i)return null;var s=i[2];return"["===s[0]&&(s=s.substring(1,s.length-1)),{element:i[1],on:s}}function d(n,i){if(null===n||s(n))return n;if(a(n))return n;for(var o=n.split(" "),c={},u=i.length-1,l=o.length-1;l>=0;l--){if(0===u){c[i[u]]=o.slice(0,l+1).join(" ");break}c[i[u]]=o[l],u--}return c}var f=function(){function n(n,i){for(var s=0;s<i.length;s++){var o=i[s];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(n,o.key,o)}}return function(i,s,o){return s&&n(i.prototype,s),o&&n(i,o),i}}(),v=function(n,i,s){for(var o=!0;o;){var c=n,a=i,u=s;o=!1,null===c&&(c=Function.prototype);var l=Object.getOwnPropertyDescriptor(c,a);if(void 0!==l){if("value"in l)return l.value;var p=l.get;if(void 0===p)return;return p.call(u)}var d=Object.getPrototypeOf(c);if(null===d)return;n=d,i=a,s=u,o=!0,l=d=void 0}},m=Tether.Utils,y=m.Evented,g=m.addClass,b=m.extend,w=m.hasClass,k=m.removeClass,S=m.uniqueId,O=new y,x={top:"bottom center",left:"middle right",right:"middle left",bottom:"top center",center:"middle center"},C=/^(.+) (top|left|right|bottom|center|\[[a-z ]+\])$/,E=function(a){function m(i,s){return n(this,m),v(Object.getPrototypeOf(m.prototype),"constructor",this).call(this,i,s),this.tour=i,this.bindMethods(),this.setOptions(s),this}return i(m,a),f(m,[{key:"bindMethods",value:function(){var n=this,i=["_show","show","hide","isOpen","cancel","complete","scrollTo","destroy","render"];i.map(function(i){n[i]=n[i].bind(n)})}},{key:"setOptions",value:function(){var n=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.options=n,this.destroy(),this.id=this.options.id||this.id||"step-"+S();var i=this.options.when;if(i)for(var a in i)if({}.hasOwnProperty.call(i,a)){var u=i[a];this.on(a,u,this)}var l=JSON.stringify(this.options.buttons),p=s(l)||"true"===l,d="{}"===l||"[]"===l||"null"===l||"false"===l,f=!p&&o(this.options.buttons),v=!p&&c(this.options.buttons);p?this.options.buttons=[{text:"Next",action:this.tour.next,classes:"btn"}]:!d&&v?this.options.buttons=[this.options.buttons]:(d||!f)&&(this.options.buttons=!1)}},{key:"getTour",value:function(){return this.tour}},{key:"bindAdvance",value:function(){var n=this,i=d(this.options.advanceOn,["selector","event"]),o=i.event,c=i.selector,a=function(e){n.isOpen()&&(s(c)?n.el&&e.target===n.el&&n.tour.next():l(e.target,c)&&n.tour.next())};document.body.addEventListener(o,a),this.on("destroy",function(){return document.body.removeEventListener(o,a)})}},{key:"getAttachTo",value:function(){var n=p(this.options.attachTo)||{},i=b({},n);return"string"==typeof n.element&&(i.element=document.querySelector(n.element),i.element||console.error("The element for this Shepherd step was not found "+n.element)),i}},{key:"setupTether",value:function(){if(s(Tether))throw new Error("Using the attachment feature of Shepherd requires the Tether library");var n=this.getAttachTo(),i=x[n.on||"right"]||n.on;s(n.element)&&(n.element="viewport",i="middle center");var o={classPrefix:"shepherd",element:this.el,constraints:[{to:"window",pin:!0,attachment:"together"}],target:n.element,offset:n.offset||"0 0",attachment:i};this.tether&&this.tether.destroy(),this.tether=new Tether(b(o,this.options.tetherOptions))}},{key:"show",value:function(){var n=this;if(!s(this.options.beforeShowPromise)){var i=this.options.beforeShowPromise();if(!s(i))return i.then(function(){return n._show()})}this._show()}},{key:"_show",value:function(){var n=this;this.trigger("before-show"),this.el||this.render(),g(this.el,"shepherd-open"),document.body.setAttribute("data-shepherd-step",this.id),this.setupTether(),this.options.scrollTo&&setTimeout(function(){n.scrollTo()}),this.trigger("show")}},{key:"hide",value:function(){this.trigger("before-hide"),k(this.el,"shepherd-open"),document.body.removeAttribute("data-shepherd-step"),this.tether&&this.tether.destroy(),this.tether=null,this.trigger("hide")}},{key:"isOpen",value:function(){return this.el&&w(this.el,"shepherd-open")}},{key:"cancel",value:function(){this.tour.cancel(),this.trigger("cancel")}},{key:"complete",value:function(){this.tour.complete(),this.trigger("complete")}},{key:"scrollTo",value:function(){var n=this.getAttachTo(),i=n.element;s(this.options.scrollToHandler)?s(i)||i.scrollIntoView():this.options.scrollToHandler(i)}},{key:"destroy",value:function(){!s(this.el)&&this.el.parentNode&&(this.el.parentNode.removeChild(this.el),delete this.el),this.tether&&this.tether.destroy(),this.tether=null,this.trigger("destroy")}},{key:"render",value:function(){var n=this;s(this.el)||this.destroy(),this.el=u("<div class='shepherd-step "+(this.options.classes||"")+"' data-id='"+this.id+"' "+(this.options.idAttribute?'id="'+this.options.idAttribute+'"':"")+"></div>");var i=document.createElement("div");i.className="shepherd-content",this.el.appendChild(i);var o=document.createElement("header");if(i.appendChild(o),this.options.title&&(o.innerHTML+="<h3 class='shepherd-title'>"+this.options.title+"</h3>",this.el.className+=" shepherd-has-title"),this.options.showCancelLink){var c=u("<a href class='shepherd-cancel-link'>✕</a>");o.appendChild(c),this.el.className+=" shepherd-has-cancel-link",this.bindCancelLink(c)}s(this.options.text)||!function(){var s=u("<div class='shepherd-text'></div>"),o=n.options.text;"function"==typeof o&&(o=o.call(n,s)),o instanceof HTMLElement?s.appendChild(o):("string"==typeof o&&(o=[o]),o.map(function(n){s.innerHTML+="<p>"+n+"</p>"})),i.appendChild(s)}(),this.options.buttons&&!function(){var s=document.createElement("footer"),o=u("<ul class='shepherd-buttons'></ul>");n.options.buttons.map(function(i){var s=u("<li><a class='shepherd-button "+(i.classes||"")+"'>"+i.text+"</a>");o.appendChild(s),n.bindButtonEvents(i,s.querySelector("a"))}),s.appendChild(o),i.appendChild(s)}(),document.body.appendChild(this.el),this.setupTether(),this.options.advanceOn&&this.bindAdvance()}},{key:"bindCancelLink",value:function(n){var i=this;n.addEventListener("click",function(e){e.preventDefault(),i.cancel()})}},{key:"bindButtonEvents",value:function(n,i){var o=this;n.events=n.events||{},s(n.action)||(n.events.click=n.action);for(var c in n.events)if({}.hasOwnProperty.call(n.events,c)){var a=n.events[c];"string"==typeof a&&!function(){var n=a;a=function(){return o.tour.show(n)}}(),i.addEventListener(c,a)}this.on("destroy",function(){for(var s in n.events)if({}.hasOwnProperty.call(n.events,s)){var o=n.events[s];i.removeEventListener(s,o)}})}}]),m}(y),M=function(o){function c(){var i=this,s=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];n(this,c),v(Object.getPrototypeOf(c.prototype),"constructor",this).call(this,s),this.bindMethods(),this.options=s,this.steps=this.options.steps||[];var o=["complete","cancel","hide","start","show","active","inactive"];return o.map(function(n){!function(e){i.on(e,function(n){n=n||{},n.tour=i,O.trigger(e,n)})}(n)}),this}return i(c,o),f(c,[{key:"bindMethods",value:function(){var n=this,i=["next","back","cancel","complete","hide"];i.map(function(i){n[i]=n[i].bind(n)})}},{key:"addStep",value:function(n,i){return s(i)&&(i=n),i instanceof E?i.tour=this:(("string"==typeof n||"number"==typeof n)&&(i.id=n.toString()),i=b({},this.options.defaults,i),i=new E(this,i)),this.steps.push(i),this}},{key:"removeStep",value:function(n){for(var i=this.getCurrentStep(),s=0;s<this.steps.length;++s){var o=this.steps[s];if(o.id===n){o.hide(),o.destroy(),this.steps.splice(s,1);break}}i&&i.id===n&&(this.currentStep=void 0,this.steps.length?this.show(0):this.hide())}},{key:"getById",value:function(n){for(var i=0;i<this.steps.length;++i){var s=this.steps[i];if(s.id===n)return s}}},{key:"getCurrentStep",value:function(){return this.currentStep}},{key:"next",value:function(){var n=this.steps.indexOf(this.currentStep);n===this.steps.length-1?(this.hide(n),this.trigger("complete"),this.done()):this.show(n+1,!0)}},{key:"back",value:function(){var n=this.steps.indexOf(this.currentStep);this.show(n-1,!1)}},{key:"cancel",value:function(){this.currentStep&&this.currentStep.hide(),this.trigger("cancel"),this.done()}},{key:"complete",value:function(){this.currentStep&&this.currentStep.hide(),this.trigger("complete"),this.done()}},{key:"hide",value:function(){this.currentStep&&this.currentStep.hide(),this.trigger("hide"),this.done()}},{key:"done",value:function(){O.activeTour=null,k(document.body,"shepherd-active"),this.trigger("inactive",{tour:this})}},{key:"show",value:function(){var n=arguments.length<=0||void 0===arguments[0]?0:arguments[0],i=arguments.length<=1||void 0===arguments[1]?!0:arguments[1];this.currentStep?this.currentStep.hide():(g(document.body,"shepherd-active"),this.trigger("active",{tour:this})),O.activeTour=this;var o=void 0;if(o="string"==typeof n?this.getById(n):this.steps[n])if(s(o.options.showOn)||o.options.showOn())this.trigger("show",{step:o,previous:this.currentStep}),this.currentStep&&this.currentStep.hide(),this.currentStep=o,o.show();else{var c=this.steps.indexOf(o),a=i?c+1:c-1;this.show(a,i)}}},{key:"start",value:function(){this.trigger("start"),this.currentStep=null,this.next()}}]),c}(y);return b(O,{Tour:M,Step:E,Evented:y}),O});
\ No newline at end of file
diff --git a/demo/lib/tether/tether.js b/demo/lib/tether/tether.js
new file mode 100755
index 0000000000..d5d026151a
--- /dev/null
+++ b/demo/lib/tether/tether.js
@@ -0,0 +1,1443 @@
+/*! tether 0.6.5 */
+
+
+(function(root, factory) {
+  if (typeof define === 'function' && define.amd) {
+    define(factory);
+  } else if (typeof exports === 'object') {
+    module.exports = factory(require,exports,module);
+  } else {
+    root.Tether = factory();
+  }
+}(this, function(require,exports,module) {
+
+(function() {
+  var Evented, addClass, defer, deferred, extend, flush, getBounds, getOffsetParent, getOrigin, getScrollBarSize, getScrollParent, hasClass, node, removeClass, uniqueId, updateClasses, zeroPosCache,
+    __hasProp = {}.hasOwnProperty,
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+    __slice = [].slice;
+
+  if (this.Tether == null) {
+    this.Tether = {
+      modules: []
+    };
+  }
+
+  getScrollParent = function(el) {
+    var parent, position, scrollParent, style, _ref;
+    position = getComputedStyle(el).position;
+    if (position === 'fixed') {
+      return el;
+    }
+    scrollParent = void 0;
+    parent = el;
+    while (parent = parent.parentNode) {
+      try {
+        style = getComputedStyle(parent);
+      } catch (_error) {}
+      if (style == null) {
+        return parent;
+      }
+      if (/(auto|scroll)/.test(style['overflow'] + style['overflow-y'] + style['overflow-x'])) {
+        if (position !== 'absolute' || ((_ref = style['position']) === 'relative' || _ref === 'absolute' || _ref === 'fixed')) {
+          return parent;
+        }
+      }
+    }
+    return document.body;
+  };
+
+  uniqueId = (function() {
+    var id;
+    id = 0;
+    return function() {
+      return id++;
+    };
+  })();
+
+  zeroPosCache = {};
+
+  getOrigin = function(doc) {
+    var id, k, node, v, _ref;
+    node = doc._tetherZeroElement;
+    if (node == null) {
+      node = doc.createElement('div');
+      node.setAttribute('data-tether-id', uniqueId());
+      extend(node.style, {
+        top: 0,
+        left: 0,
+        position: 'absolute'
+      });
+      doc.body.appendChild(node);
+      doc._tetherZeroElement = node;
+    }
+    id = node.getAttribute('data-tether-id');
+    if (zeroPosCache[id] == null) {
+      zeroPosCache[id] = {};
+      _ref = node.getBoundingClientRect();
+      for (k in _ref) {
+        v = _ref[k];
+        zeroPosCache[id][k] = v;
+      }
+      defer(function() {
+        return zeroPosCache[id] = void 0;
+      });
+    }
+    return zeroPosCache[id];
+  };
+
+  node = null;
+
+  getBounds = function(el) {
+    var box, doc, docEl, k, origin, v, _ref;
+    if (el === document) {
+      doc = document;
+      el = document.documentElement;
+    } else {
+      doc = el.ownerDocument;
+    }
+    docEl = doc.documentElement;
+    box = {};
+    _ref = el.getBoundingClientRect();
+    for (k in _ref) {
+      v = _ref[k];
+      box[k] = v;
+    }
+    origin = getOrigin(doc);
+    box.top -= origin.top;
+    box.left -= origin.left;
+    if (box.width == null) {
+      box.width = document.body.scrollWidth - box.left - box.right;
+    }
+    if (box.height == null) {
+      box.height = document.body.scrollHeight - box.top - box.bottom;
+    }
+    box.top = box.top - docEl.clientTop;
+    box.left = box.left - docEl.clientLeft;
+    box.right = doc.body.clientWidth - box.width - box.left;
+    box.bottom = doc.body.clientHeight - box.height - box.top;
+    return box;
+  };
+
+  getOffsetParent = function(el) {
+    return el.offsetParent || document.documentElement;
+  };
+
+  getScrollBarSize = function() {
+    var inner, outer, width, widthContained, widthScroll;
+    inner = document.createElement('div');
+    inner.style.width = '100%';
+    inner.style.height = '200px';
+    outer = document.createElement('div');
+    extend(outer.style, {
+      position: 'absolute',
+      top: 0,
+      left: 0,
+      pointerEvents: 'none',
+      visibility: 'hidden',
+      width: '200px',
+      height: '150px',
+      overflow: 'hidden'
+    });
+    outer.appendChild(inner);
+    document.body.appendChild(outer);
+    widthContained = inner.offsetWidth;
+    outer.style.overflow = 'scroll';
+    widthScroll = inner.offsetWidth;
+    if (widthContained === widthScroll) {
+      widthScroll = outer.clientWidth;
+    }
+    document.body.removeChild(outer);
+    width = widthContained - widthScroll;
+    return {
+      width: width,
+      height: width
+    };
+  };
+
+  extend = function(out) {
+    var args, key, obj, val, _i, _len, _ref;
+    if (out == null) {
+      out = {};
+    }
+    args = [];
+    Array.prototype.push.apply(args, arguments);
+    _ref = args.slice(1);
+    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+      obj = _ref[_i];
+      if (obj) {
+        for (key in obj) {
+          if (!__hasProp.call(obj, key)) continue;
+          val = obj[key];
+          out[key] = val;
+        }
+      }
+    }
+    return out;
+  };
+
+  removeClass = function(el, name) {
+    var cls, _i, _len, _ref, _results;
+    if (el.classList != null) {
+      _ref = name.split(' ');
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        cls = _ref[_i];
+        if (cls.trim()) {
+          _results.push(el.classList.remove(cls));
+        }
+      }
+      return _results;
+    } else {
+      return el.className = el.className.replace(new RegExp("(^| )" + (name.split(' ').join('|')) + "( |$)", 'gi'), ' ');
+    }
+  };
+
+  addClass = function(el, name) {
+    var cls, _i, _len, _ref, _results;
+    if (el.classList != null) {
+      _ref = name.split(' ');
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        cls = _ref[_i];
+        if (cls.trim()) {
+          _results.push(el.classList.add(cls));
+        }
+      }
+      return _results;
+    } else {
+      removeClass(el, name);
+      return el.className += " " + name;
+    }
+  };
+
+  hasClass = function(el, name) {
+    if (el.classList != null) {
+      return el.classList.contains(name);
+    } else {
+      return new RegExp("(^| )" + name + "( |$)", 'gi').test(el.className);
+    }
+  };
+
+  updateClasses = function(el, add, all) {
+    var cls, _i, _j, _len, _len1, _results;
+    for (_i = 0, _len = all.length; _i < _len; _i++) {
+      cls = all[_i];
+      if (__indexOf.call(add, cls) < 0) {
+        if (hasClass(el, cls)) {
+          removeClass(el, cls);
+        }
+      }
+    }
+    _results = [];
+    for (_j = 0, _len1 = add.length; _j < _len1; _j++) {
+      cls = add[_j];
+      if (!hasClass(el, cls)) {
+        _results.push(addClass(el, cls));
+      } else {
+        _results.push(void 0);
+      }
+    }
+    return _results;
+  };
+
+  deferred = [];
+
+  defer = function(fn) {
+    return deferred.push(fn);
+  };
+
+  flush = function() {
+    var fn, _results;
+    _results = [];
+    while (fn = deferred.pop()) {
+      _results.push(fn());
+    }
+    return _results;
+  };
+
+  Evented = (function() {
+    function Evented() {}
+
+    Evented.prototype.on = function(event, handler, ctx, once) {
+      var _base;
+      if (once == null) {
+        once = false;
+      }
+      if (this.bindings == null) {
+        this.bindings = {};
+      }
+      if ((_base = this.bindings)[event] == null) {
+        _base[event] = [];
+      }
+      return this.bindings[event].push({
+        handler: handler,
+        ctx: ctx,
+        once: once
+      });
+    };
+
+    Evented.prototype.once = function(event, handler, ctx) {
+      return this.on(event, handler, ctx, true);
+    };
+
+    Evented.prototype.off = function(event, handler) {
+      var i, _ref, _results;
+      if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) {
+        return;
+      }
+      if (handler == null) {
+        return delete this.bindings[event];
+      } else {
+        i = 0;
+        _results = [];
+        while (i < this.bindings[event].length) {
+          if (this.bindings[event][i].handler === handler) {
+            _results.push(this.bindings[event].splice(i, 1));
+          } else {
+            _results.push(i++);
+          }
+        }
+        return _results;
+      }
+    };
+
+    Evented.prototype.trigger = function() {
+      var args, ctx, event, handler, i, once, _ref, _ref1, _results;
+      event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+      if ((_ref = this.bindings) != null ? _ref[event] : void 0) {
+        i = 0;
+        _results = [];
+        while (i < this.bindings[event].length) {
+          _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once;
+          handler.apply(ctx != null ? ctx : this, args);
+          if (once) {
+            _results.push(this.bindings[event].splice(i, 1));
+          } else {
+            _results.push(i++);
+          }
+        }
+        return _results;
+      }
+    };
+
+    return Evented;
+
+  })();
+
+  this.Tether.Utils = {
+    getScrollParent: getScrollParent,
+    getBounds: getBounds,
+    getOffsetParent: getOffsetParent,
+    extend: extend,
+    addClass: addClass,
+    removeClass: removeClass,
+    hasClass: hasClass,
+    updateClasses: updateClasses,
+    defer: defer,
+    flush: flush,
+    uniqueId: uniqueId,
+    Evented: Evented,
+    getScrollBarSize: getScrollBarSize
+  };
+
+}).call(this);
+
+(function() {
+  var MIRROR_LR, MIRROR_TB, OFFSET_MAP, Tether, addClass, addOffset, attachmentToOffset, autoToFixedAttachment, defer, extend, flush, getBounds, getOffsetParent, getOuterSize, getScrollBarSize, getScrollParent, getSize, now, offsetToPx, parseAttachment, parseOffset, position, removeClass, tethers, transformKey, updateClasses, within, _Tether, _ref,
+    __slice = [].slice,
+    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+
+  if (this.Tether == null) {
+    throw new Error("You must include the utils.js file before tether.js");
+  }
+
+  Tether = this.Tether;
+
+  _ref = Tether.Utils, getScrollParent = _ref.getScrollParent, getSize = _ref.getSize, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getOffsetParent = _ref.getOffsetParent, extend = _ref.extend, addClass = _ref.addClass, removeClass = _ref.removeClass, updateClasses = _ref.updateClasses, defer = _ref.defer, flush = _ref.flush, getScrollBarSize = _ref.getScrollBarSize;
+
+  within = function(a, b, diff) {
+    if (diff == null) {
+      diff = 1;
+    }
+    return (a + diff >= b && b >= a - diff);
+  };
+
+  transformKey = (function() {
+    var el, key, _i, _len, _ref1;
+    el = document.createElement('div');
+    _ref1 = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
+    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+      key = _ref1[_i];
+      if (el.style[key] !== void 0) {
+        return key;
+      }
+    }
+  })();
+
+  tethers = [];
+
+  position = function() {
+    var tether, _i, _len;
+    for (_i = 0, _len = tethers.length; _i < _len; _i++) {
+      tether = tethers[_i];
+      tether.position(false);
+    }
+    return flush();
+  };
+
+  now = function() {
+    var _ref1;
+    return (_ref1 = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref1 : +(new Date);
+  };
+
+  (function() {
+    var event, lastCall, lastDuration, pendingTimeout, tick, _i, _len, _ref1, _results;
+    lastCall = null;
+    lastDuration = null;
+    pendingTimeout = null;
+    tick = function() {
+      if ((lastDuration != null) && lastDuration > 16) {
+        lastDuration = Math.min(lastDuration - 16, 250);
+        pendingTimeout = setTimeout(tick, 250);
+        return;
+      }
+      if ((lastCall != null) && (now() - lastCall) < 10) {
+        return;
+      }
+      if (pendingTimeout != null) {
+        clearTimeout(pendingTimeout);
+        pendingTimeout = null;
+      }
+      lastCall = now();
+      position();
+      return lastDuration = now() - lastCall;
+    };
+    _ref1 = ['resize', 'scroll', 'touchmove'];
+    _results = [];
+    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+      event = _ref1[_i];
+      _results.push(window.addEventListener(event, tick));
+    }
+    return _results;
+  })();
+
+  MIRROR_LR = {
+    center: 'center',
+    left: 'right',
+    right: 'left'
+  };
+
+  MIRROR_TB = {
+    middle: 'middle',
+    top: 'bottom',
+    bottom: 'top'
+  };
+
+  OFFSET_MAP = {
+    top: 0,
+    left: 0,
+    middle: '50%',
+    center: '50%',
+    bottom: '100%',
+    right: '100%'
+  };
+
+  autoToFixedAttachment = function(attachment, relativeToAttachment) {
+    var left, top;
+    left = attachment.left, top = attachment.top;
+    if (left === 'auto') {
+      left = MIRROR_LR[relativeToAttachment.left];
+    }
+    if (top === 'auto') {
+      top = MIRROR_TB[relativeToAttachment.top];
+    }
+    return {
+      left: left,
+      top: top
+    };
+  };
+
+  attachmentToOffset = function(attachment) {
+    var _ref1, _ref2;
+    return {
+      left: (_ref1 = OFFSET_MAP[attachment.left]) != null ? _ref1 : attachment.left,
+      top: (_ref2 = OFFSET_MAP[attachment.top]) != null ? _ref2 : attachment.top
+    };
+  };
+
+  addOffset = function() {
+    var left, offsets, out, top, _i, _len, _ref1;
+    offsets = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+    out = {
+      top: 0,
+      left: 0
+    };
+    for (_i = 0, _len = offsets.length; _i < _len; _i++) {
+      _ref1 = offsets[_i], top = _ref1.top, left = _ref1.left;
+      if (typeof top === 'string') {
+        top = parseFloat(top, 10);
+      }
+      if (typeof left === 'string') {
+        left = parseFloat(left, 10);
+      }
+      out.top += top;
+      out.left += left;
+    }
+    return out;
+  };
+
+  offsetToPx = function(offset, size) {
+    if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
+      offset.left = parseFloat(offset.left, 10) / 100 * size.width;
+    }
+    if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
+      offset.top = parseFloat(offset.top, 10) / 100 * size.height;
+    }
+    return offset;
+  };
+
+  parseAttachment = parseOffset = function(value) {
+    var left, top, _ref1;
+    _ref1 = value.split(' '), top = _ref1[0], left = _ref1[1];
+    return {
+      top: top,
+      left: left
+    };
+  };
+
+  _Tether = (function() {
+    _Tether.modules = [];
+
+    function _Tether(options) {
+      this.position = __bind(this.position, this);
+      var module, _i, _len, _ref1, _ref2;
+      tethers.push(this);
+      this.history = [];
+      this.setOptions(options, false);
+      _ref1 = Tether.modules;
+      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+        module = _ref1[_i];
+        if ((_ref2 = module.initialize) != null) {
+          _ref2.call(this);
+        }
+      }
+      this.position();
+    }
+
+    _Tether.prototype.getClass = function(key) {
+      var _ref1, _ref2;
+      if ((_ref1 = this.options.classes) != null ? _ref1[key] : void 0) {
+        return this.options.classes[key];
+      } else if (((_ref2 = this.options.classes) != null ? _ref2[key] : void 0) !== false) {
+        if (this.options.classPrefix) {
+          return "" + this.options.classPrefix + "-" + key;
+        } else {
+          return key;
+        }
+      } else {
+        return '';
+      }
+    };
+
+    _Tether.prototype.setOptions = function(options, position) {
+      var defaults, key, _i, _len, _ref1, _ref2;
+      this.options = options;
+      if (position == null) {
+        position = true;
+      }
+      defaults = {
+        offset: '0 0',
+        targetOffset: '0 0',
+        targetAttachment: 'auto auto',
+        classPrefix: 'tether'
+      };
+      this.options = extend(defaults, this.options);
+      _ref1 = this.options, this.element = _ref1.element, this.target = _ref1.target, this.targetModifier = _ref1.targetModifier;
+      if (this.target === 'viewport') {
+        this.target = document.body;
+        this.targetModifier = 'visible';
+      } else if (this.target === 'scroll-handle') {
+        this.target = document.body;
+        this.targetModifier = 'scroll-handle';
+      }
+      _ref2 = ['element', 'target'];
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        key = _ref2[_i];
+        if (this[key] == null) {
+          throw new Error("Tether Error: Both element and target must be defined");
+        }
+        if (this[key].jquery != null) {
+          this[key] = this[key][0];
+        } else if (typeof this[key] === 'string') {
+          this[key] = document.querySelector(this[key]);
+        }
+      }
+      addClass(this.element, this.getClass('element'));
+      addClass(this.target, this.getClass('target'));
+      if (!this.options.attachment) {
+        throw new Error("Tether Error: You must provide an attachment");
+      }
+      this.targetAttachment = parseAttachment(this.options.targetAttachment);
+      this.attachment = parseAttachment(this.options.attachment);
+      this.offset = parseOffset(this.options.offset);
+      this.targetOffset = parseOffset(this.options.targetOffset);
+      if (this.scrollParent != null) {
+        this.disable();
+      }
+      if (this.targetModifier === 'scroll-handle') {
+        this.scrollParent = this.target;
+      } else {
+        this.scrollParent = getScrollParent(this.target);
+      }
+      if (this.options.enabled !== false) {
+        return this.enable(position);
+      }
+    };
+
+    _Tether.prototype.getTargetBounds = function() {
+      var bounds, fitAdj, hasBottomScroll, height, out, scrollBottom, scrollPercentage, style, target;
+      if (this.targetModifier != null) {
+        switch (this.targetModifier) {
+          case 'visible':
+            if (this.target === document.body) {
+              return {
+                top: pageYOffset,
+                left: pageXOffset,
+                height: innerHeight,
+                width: innerWidth
+              };
+            } else {
+              bounds = getBounds(this.target);
+              out = {
+                height: bounds.height,
+                width: bounds.width,
+                top: bounds.top,
+                left: bounds.left
+              };
+              out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top));
+              out.height = Math.min(out.height, bounds.height - ((bounds.top + bounds.height) - (pageYOffset + innerHeight)));
+              out.height = Math.min(innerHeight, out.height);
+              out.height -= 2;
+              out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left));
+              out.width = Math.min(out.width, bounds.width - ((bounds.left + bounds.width) - (pageXOffset + innerWidth)));
+              out.width = Math.min(innerWidth, out.width);
+              out.width -= 2;
+              if (out.top < pageYOffset) {
+                out.top = pageYOffset;
+              }
+              if (out.left < pageXOffset) {
+                out.left = pageXOffset;
+              }
+              return out;
+            }
+            break;
+          case 'scroll-handle':
+            target = this.target;
+            if (target === document.body) {
+              target = document.documentElement;
+              bounds = {
+                left: pageXOffset,
+                top: pageYOffset,
+                height: innerHeight,
+                width: innerWidth
+              };
+            } else {
+              bounds = getBounds(target);
+            }
+            style = getComputedStyle(target);
+            hasBottomScroll = target.scrollWidth > target.clientWidth || 'scroll' === [style.overflow, style.overflowX] || this.target !== document.body;
+            scrollBottom = 0;
+            if (hasBottomScroll) {
+              scrollBottom = 15;
+            }
+            height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom;
+            out = {
+              width: 15,
+              height: height * 0.975 * (height / target.scrollHeight),
+              left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
+            };
+            fitAdj = 0;
+            if (height < 408 && this.target === document.body) {
+              fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58;
+            }
+            if (this.target !== document.body) {
+              out.height = Math.max(out.height, 24);
+            }
+            scrollPercentage = this.target.scrollTop / (target.scrollHeight - height);
+            out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth);
+            if (this.target === document.body) {
+              out.height = Math.max(out.height, 24);
+            }
+            return out;
+        }
+      } else {
+        return getBounds(this.target);
+      }
+    };
+
+    _Tether.prototype.clearCache = function() {
+      return this._cache = {};
+    };
+
+    _Tether.prototype.cache = function(k, getter) {
+      if (this._cache == null) {
+        this._cache = {};
+      }
+      if (this._cache[k] == null) {
+        this._cache[k] = getter.call(this);
+      }
+      return this._cache[k];
+    };
+
+    _Tether.prototype.enable = function(position) {
+      if (position == null) {
+        position = true;
+      }
+      addClass(this.target, this.getClass('enabled'));
+      addClass(this.element, this.getClass('enabled'));
+      this.enabled = true;
+      if (this.scrollParent !== document) {
+        this.scrollParent.addEventListener('scroll', this.position);
+      }
+      if (position) {
+        return this.position();
+      }
+    };
+
+    _Tether.prototype.disable = function() {
+      removeClass(this.target, this.getClass('enabled'));
+      removeClass(this.element, this.getClass('enabled'));
+      this.enabled = false;
+      if (this.scrollParent != null) {
+        return this.scrollParent.removeEventListener('scroll', this.position);
+      }
+    };
+
+    _Tether.prototype.destroy = function() {
+      var i, tether, _i, _len, _results;
+      this.disable();
+      _results = [];
+      for (i = _i = 0, _len = tethers.length; _i < _len; i = ++_i) {
+        tether = tethers[i];
+        if (tether === this) {
+          tethers.splice(i, 1);
+          break;
+        } else {
+          _results.push(void 0);
+        }
+      }
+      return _results;
+    };
+
+    _Tether.prototype.updateAttachClasses = function(elementAttach, targetAttach) {
+      var add, all, side, sides, _i, _j, _len, _len1, _ref1,
+        _this = this;
+      if (elementAttach == null) {
+        elementAttach = this.attachment;
+      }
+      if (targetAttach == null) {
+        targetAttach = this.targetAttachment;
+      }
+      sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
+      if ((_ref1 = this._addAttachClasses) != null ? _ref1.length : void 0) {
+        this._addAttachClasses.splice(0, this._addAttachClasses.length);
+      }
+      add = this._addAttachClasses != null ? this._addAttachClasses : this._addAttachClasses = [];
+      if (elementAttach.top) {
+        add.push("" + (this.getClass('element-attached')) + "-" + elementAttach.top);
+      }
+      if (elementAttach.left) {
+        add.push("" + (this.getClass('element-attached')) + "-" + elementAttach.left);
+      }
+      if (targetAttach.top) {
+        add.push("" + (this.getClass('target-attached')) + "-" + targetAttach.top);
+      }
+      if (targetAttach.left) {
+        add.push("" + (this.getClass('target-attached')) + "-" + targetAttach.left);
+      }
+      all = [];
+      for (_i = 0, _len = sides.length; _i < _len; _i++) {
+        side = sides[_i];
+        all.push("" + (this.getClass('element-attached')) + "-" + side);
+      }
+      for (_j = 0, _len1 = sides.length; _j < _len1; _j++) {
+        side = sides[_j];
+        all.push("" + (this.getClass('target-attached')) + "-" + side);
+      }
+      return defer(function() {
+        if (_this._addAttachClasses == null) {
+          return;
+        }
+        updateClasses(_this.element, _this._addAttachClasses, all);
+        updateClasses(_this.target, _this._addAttachClasses, all);
+        return _this._addAttachClasses = void 0;
+      });
+    };
+
+    _Tether.prototype.position = function(flushChanges) {
+      var elementPos, elementStyle, height, left, manualOffset, manualTargetOffset, module, next, offset, offsetBorder, offsetParent, offsetParentSize, offsetParentStyle, offsetPosition, ret, scrollLeft, scrollTop, scrollbarSize, side, targetAttachment, targetOffset, targetPos, targetSize, top, width, _i, _j, _len, _len1, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6,
+        _this = this;
+      if (flushChanges == null) {
+        flushChanges = true;
+      }
+      if (!this.enabled) {
+        return;
+      }
+      this.clearCache();
+      targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment);
+      this.updateAttachClasses(this.attachment, targetAttachment);
+      elementPos = this.cache('element-bounds', function() {
+        return getBounds(_this.element);
+      });
+      width = elementPos.width, height = elementPos.height;
+      if (width === 0 && height === 0 && (this.lastSize != null)) {
+        _ref1 = this.lastSize, width = _ref1.width, height = _ref1.height;
+      } else {
+        this.lastSize = {
+          width: width,
+          height: height
+        };
+      }
+      targetSize = targetPos = this.cache('target-bounds', function() {
+        return _this.getTargetBounds();
+      });
+      offset = offsetToPx(attachmentToOffset(this.attachment), {
+        width: width,
+        height: height
+      });
+      targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize);
+      manualOffset = offsetToPx(this.offset, {
+        width: width,
+        height: height
+      });
+      manualTargetOffset = offsetToPx(this.targetOffset, targetSize);
+      offset = addOffset(offset, manualOffset);
+      targetOffset = addOffset(targetOffset, manualTargetOffset);
+      left = targetPos.left + targetOffset.left - offset.left;
+      top = targetPos.top + targetOffset.top - offset.top;
+      _ref2 = Tether.modules;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        module = _ref2[_i];
+        ret = module.position.call(this, {
+          left: left,
+          top: top,
+          targetAttachment: targetAttachment,
+          targetPos: targetPos,
+          attachment: this.attachment,
+          elementPos: elementPos,
+          offset: offset,
+          targetOffset: targetOffset,
+          manualOffset: manualOffset,
+          manualTargetOffset: manualTargetOffset,
+          scrollbarSize: scrollbarSize
+        });
+        if ((ret == null) || typeof ret !== 'object') {
+          continue;
+        } else if (ret === false) {
+          return false;
+        } else {
+          top = ret.top, left = ret.left;
+        }
+      }
+      next = {
+        page: {
+          top: top,
+          left: left
+        },
+        viewport: {
+          top: top - pageYOffset,
+          bottom: pageYOffset - top - height + innerHeight,
+          left: left - pageXOffset,
+          right: pageXOffset - left - width + innerWidth
+        }
+      };
+      if (document.body.scrollWidth > window.innerWidth) {
+        scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+        next.viewport.bottom -= scrollbarSize.height;
+      }
+      if (document.body.scrollHeight > window.innerHeight) {
+        scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+        next.viewport.right -= scrollbarSize.width;
+      }
+      if (((_ref3 = document.body.style.position) !== '' && _ref3 !== 'static') || ((_ref4 = document.body.parentElement.style.position) !== '' && _ref4 !== 'static')) {
+        next.page.bottom = document.body.scrollHeight - top - height;
+        next.page.right = document.body.scrollWidth - left - width;
+      }
+      if (((_ref5 = this.options.optimizations) != null ? _ref5.moveElement : void 0) !== false && (this.targetModifier == null)) {
+        offsetParent = this.cache('target-offsetparent', function() {
+          return getOffsetParent(_this.target);
+        });
+        offsetPosition = this.cache('target-offsetparent-bounds', function() {
+          return getBounds(offsetParent);
+        });
+        offsetParentStyle = getComputedStyle(offsetParent);
+        elementStyle = getComputedStyle(this.element);
+        offsetParentSize = offsetPosition;
+        offsetBorder = {};
+        _ref6 = ['Top', 'Left', 'Bottom', 'Right'];
+        for (_j = 0, _len1 = _ref6.length; _j < _len1; _j++) {
+          side = _ref6[_j];
+          offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle["border" + side + "Width"]);
+        }
+        offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right;
+        offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom;
+        if (next.page.top >= (offsetPosition.top + offsetBorder.top) && next.page.bottom >= offsetPosition.bottom) {
+          if (next.page.left >= (offsetPosition.left + offsetBorder.left) && next.page.right >= offsetPosition.right) {
+            scrollTop = offsetParent.scrollTop;
+            scrollLeft = offsetParent.scrollLeft;
+            next.offset = {
+              top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top,
+              left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
+            };
+          }
+        }
+      }
+      this.move(next);
+      this.history.unshift(next);
+      if (this.history.length > 3) {
+        this.history.pop();
+      }
+      if (flushChanges) {
+        flush();
+      }
+      return true;
+    };
+
+    _Tether.prototype.move = function(position) {
+      var css, elVal, found, key, moved, offsetParent, point, same, transcribe, type, val, write, writeCSS, _i, _len, _ref1, _ref2,
+        _this = this;
+      if (this.element.parentNode == null) {
+        return;
+      }
+      same = {};
+      for (type in position) {
+        same[type] = {};
+        for (key in position[type]) {
+          found = false;
+          _ref1 = this.history;
+          for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+            point = _ref1[_i];
+            if (!within((_ref2 = point[type]) != null ? _ref2[key] : void 0, position[type][key])) {
+              found = true;
+              break;
+            }
+          }
+          if (!found) {
+            same[type][key] = true;
+          }
+        }
+      }
+      css = {
+        top: '',
+        left: '',
+        right: '',
+        bottom: ''
+      };
+      transcribe = function(same, pos) {
+        var xPos, yPos, _ref3;
+        if (((_ref3 = _this.options.optimizations) != null ? _ref3.gpu : void 0) !== false) {
+          if (same.top) {
+            css.top = 0;
+            yPos = pos.top;
+          } else {
+            css.bottom = 0;
+            yPos = -pos.bottom;
+          }
+          if (same.left) {
+            css.left = 0;
+            xPos = pos.left;
+          } else {
+            css.right = 0;
+            xPos = -pos.right;
+          }
+          css[transformKey] = "translateX(" + (Math.round(xPos)) + "px) translateY(" + (Math.round(yPos)) + "px)";
+          if (transformKey !== 'msTransform') {
+            return css[transformKey] += " translateZ(0)";
+          }
+        } else {
+          if (same.top) {
+            css.top = "" + pos.top + "px";
+          } else {
+            css.bottom = "" + pos.bottom + "px";
+          }
+          if (same.left) {
+            return css.left = "" + pos.left + "px";
+          } else {
+            return css.right = "" + pos.right + "px";
+          }
+        }
+      };
+      moved = false;
+      if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) {
+        css.position = 'absolute';
+        transcribe(same.page, position.page);
+      } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
+        css.position = 'fixed';
+        transcribe(same.viewport, position.viewport);
+      } else if ((same.offset != null) && same.offset.top && same.offset.left) {
+        css.position = 'absolute';
+        offsetParent = this.cache('target-offsetparent', function() {
+          return getOffsetParent(_this.target);
+        });
+        if (getOffsetParent(this.element) !== offsetParent) {
+          defer(function() {
+            _this.element.parentNode.removeChild(_this.element);
+            return offsetParent.appendChild(_this.element);
+          });
+        }
+        transcribe(same.offset, position.offset);
+        moved = true;
+      } else {
+        css.position = 'absolute';
+        transcribe({
+          top: true,
+          left: true
+        }, position.page);
+      }
+      if (!moved && this.element.parentNode.tagName !== 'BODY') {
+        this.element.parentNode.removeChild(this.element);
+        document.body.appendChild(this.element);
+      }
+      writeCSS = {};
+      write = false;
+      for (key in css) {
+        val = css[key];
+        elVal = this.element.style[key];
+        if (elVal !== '' && val !== '' && (key === 'top' || key === 'left' || key === 'bottom' || key === 'right')) {
+          elVal = parseFloat(elVal);
+          val = parseFloat(val);
+        }
+        if (elVal !== val) {
+          write = true;
+          writeCSS[key] = css[key];
+        }
+      }
+      if (write) {
+        return defer(function() {
+          return extend(_this.element.style, writeCSS);
+        });
+      }
+    };
+
+    return _Tether;
+
+  })();
+
+  Tether.position = position;
+
+  this.Tether = extend(_Tether, Tether);
+
+}).call(this);
+
+(function() {
+  var BOUNDS_FORMAT, MIRROR_ATTACH, defer, extend, getBoundingRect, getBounds, getOuterSize, getSize, updateClasses, _ref,
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  _ref = this.Tether.Utils, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getSize = _ref.getSize, extend = _ref.extend, updateClasses = _ref.updateClasses, defer = _ref.defer;
+
+  MIRROR_ATTACH = {
+    left: 'right',
+    right: 'left',
+    top: 'bottom',
+    bottom: 'top',
+    middle: 'middle'
+  };
+
+  BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
+
+  getBoundingRect = function(tether, to) {
+    var i, pos, side, size, style, _i, _len;
+    if (to === 'scrollParent') {
+      to = tether.scrollParent;
+    } else if (to === 'window') {
+      to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset];
+    }
+    if (to === document) {
+      to = to.documentElement;
+    }
+    if (to.nodeType != null) {
+      pos = size = getBounds(to);
+      style = getComputedStyle(to);
+      to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top];
+      for (i = _i = 0, _len = BOUNDS_FORMAT.length; _i < _len; i = ++_i) {
+        side = BOUNDS_FORMAT[i];
+        side = side[0].toUpperCase() + side.substr(1);
+        if (side === 'Top' || side === 'Left') {
+          to[i] += parseFloat(style["border" + side + "Width"]);
+        } else {
+          to[i] -= parseFloat(style["border" + side + "Width"]);
+        }
+      }
+    }
+    return to;
+  };
+
+  this.Tether.modules.push({
+    position: function(_arg) {
+      var addClasses, allClasses, attachment, bounds, changeAttachX, changeAttachY, cls, constraint, eAttachment, height, left, oob, oobClass, p, pin, pinned, pinnedClass, removeClass, side, tAttachment, targetAttachment, targetHeight, targetSize, targetWidth, to, top, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8,
+        _this = this;
+      top = _arg.top, left = _arg.left, targetAttachment = _arg.targetAttachment;
+      if (!this.options.constraints) {
+        return true;
+      }
+      removeClass = function(prefix) {
+        var side, _i, _len, _results;
+        _this.removeClass(prefix);
+        _results = [];
+        for (_i = 0, _len = BOUNDS_FORMAT.length; _i < _len; _i++) {
+          side = BOUNDS_FORMAT[_i];
+          _results.push(_this.removeClass("" + prefix + "-" + side));
+        }
+        return _results;
+      };
+      _ref1 = this.cache('element-bounds', function() {
+        return getBounds(_this.element);
+      }), height = _ref1.height, width = _ref1.width;
+      if (width === 0 && height === 0 && (this.lastSize != null)) {
+        _ref2 = this.lastSize, width = _ref2.width, height = _ref2.height;
+      }
+      targetSize = this.cache('target-bounds', function() {
+        return _this.getTargetBounds();
+      });
+      targetHeight = targetSize.height;
+      targetWidth = targetSize.width;
+      tAttachment = {};
+      eAttachment = {};
+      allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')];
+      _ref3 = this.options.constraints;
+      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+        constraint = _ref3[_i];
+        if (constraint.outOfBoundsClass) {
+          allClasses.push(constraint.outOfBoundsClass);
+        }
+        if (constraint.pinnedClass) {
+          allClasses.push(constraint.pinnedClass);
+        }
+      }
+      for (_j = 0, _len1 = allClasses.length; _j < _len1; _j++) {
+        cls = allClasses[_j];
+        _ref4 = ['left', 'top', 'right', 'bottom'];
+        for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
+          side = _ref4[_k];
+          allClasses.push("" + cls + "-" + side);
+        }
+      }
+      addClasses = [];
+      tAttachment = extend({}, targetAttachment);
+      eAttachment = extend({}, this.attachment);
+      _ref5 = this.options.constraints;
+      for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {
+        constraint = _ref5[_l];
+        to = constraint.to, attachment = constraint.attachment, pin = constraint.pin;
+        if (attachment == null) {
+          attachment = '';
+        }
+        if (__indexOf.call(attachment, ' ') >= 0) {
+          _ref6 = attachment.split(' '), changeAttachY = _ref6[0], changeAttachX = _ref6[1];
+        } else {
+          changeAttachX = changeAttachY = attachment;
+        }
+        bounds = getBoundingRect(this, to);
+        if (changeAttachY === 'target' || changeAttachY === 'both') {
+          if (top < bounds[1] && tAttachment.top === 'top') {
+            top += targetHeight;
+            tAttachment.top = 'bottom';
+          }
+          if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+            top -= targetHeight;
+            tAttachment.top = 'top';
+          }
+        }
+        if (changeAttachY === 'together') {
+          if (top < bounds[1] && tAttachment.top === 'top') {
+            if (eAttachment.top === 'bottom') {
+              top += targetHeight;
+              tAttachment.top = 'bottom';
+              top += height;
+              eAttachment.top = 'top';
+            } else if (eAttachment.top === 'top') {
+              top += targetHeight;
+              tAttachment.top = 'bottom';
+              top -= height;
+              eAttachment.top = 'bottom';
+            }
+          }
+          if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+            if (eAttachment.top === 'top') {
+              top -= targetHeight;
+              tAttachment.top = 'top';
+              top -= height;
+              eAttachment.top = 'bottom';
+            } else if (eAttachment.top === 'bottom') {
+              top -= targetHeight;
+              tAttachment.top = 'top';
+              top += height;
+              eAttachment.top = 'top';
+            }
+          }
+          if (tAttachment.top === 'middle') {
+            if (top + height > bounds[3] && eAttachment.top === 'top') {
+              top -= height;
+              eAttachment.top = 'bottom';
+            } else if (top < bounds[1] && eAttachment.top === 'bottom') {
+              top += height;
+              eAttachment.top = 'top';
+            }
+          }
+        }
+        if (changeAttachX === 'target' || changeAttachX === 'both') {
+          if (left < bounds[0] && tAttachment.left === 'left') {
+            left += targetWidth;
+            tAttachment.left = 'right';
+          }
+          if (left + width > bounds[2] && tAttachment.left === 'right') {
+            left -= targetWidth;
+            tAttachment.left = 'left';
+          }
+        }
+        if (changeAttachX === 'together') {
+          if (left < bounds[0] && tAttachment.left === 'left') {
+            if (eAttachment.left === 'right') {
+              left += targetWidth;
+              tAttachment.left = 'right';
+              left += width;
+              eAttachment.left = 'left';
+            } else if (eAttachment.left === 'left') {
+              left += targetWidth;
+              tAttachment.left = 'right';
+              left -= width;
+              eAttachment.left = 'right';
+            }
+          } else if (left + width > bounds[2] && tAttachment.left === 'right') {
+            if (eAttachment.left === 'left') {
+              left -= targetWidth;
+              tAttachment.left = 'left';
+              left -= width;
+              eAttachment.left = 'right';
+            } else if (eAttachment.left === 'right') {
+              left -= targetWidth;
+              tAttachment.left = 'left';
+              left += width;
+              eAttachment.left = 'left';
+            }
+          } else if (tAttachment.left === 'center') {
+            if (left + width > bounds[2] && eAttachment.left === 'left') {
+              left -= width;
+              eAttachment.left = 'right';
+            } else if (left < bounds[0] && eAttachment.left === 'right') {
+              left += width;
+              eAttachment.left = 'left';
+            }
+          }
+        }
+        if (changeAttachY === 'element' || changeAttachY === 'both') {
+          if (top < bounds[1] && eAttachment.top === 'bottom') {
+            top += height;
+            eAttachment.top = 'top';
+          }
+          if (top + height > bounds[3] && eAttachment.top === 'top') {
+            top -= height;
+            eAttachment.top = 'bottom';
+          }
+        }
+        if (changeAttachX === 'element' || changeAttachX === 'both') {
+          if (left < bounds[0] && eAttachment.left === 'right') {
+            left += width;
+            eAttachment.left = 'left';
+          }
+          if (left + width > bounds[2] && eAttachment.left === 'left') {
+            left -= width;
+            eAttachment.left = 'right';
+          }
+        }
+        if (typeof pin === 'string') {
+          pin = (function() {
+            var _len4, _m, _ref7, _results;
+            _ref7 = pin.split(',');
+            _results = [];
+            for (_m = 0, _len4 = _ref7.length; _m < _len4; _m++) {
+              p = _ref7[_m];
+              _results.push(p.trim());
+            }
+            return _results;
+          })();
+        } else if (pin === true) {
+          pin = ['top', 'left', 'right', 'bottom'];
+        }
+        pin || (pin = []);
+        pinned = [];
+        oob = [];
+        if (top < bounds[1]) {
+          if (__indexOf.call(pin, 'top') >= 0) {
+            top = bounds[1];
+            pinned.push('top');
+          } else {
+            oob.push('top');
+          }
+        }
+        if (top + height > bounds[3]) {
+          if (__indexOf.call(pin, 'bottom') >= 0) {
+            top = bounds[3] - height;
+            pinned.push('bottom');
+          } else {
+            oob.push('bottom');
+          }
+        }
+        if (left < bounds[0]) {
+          if (__indexOf.call(pin, 'left') >= 0) {
+            left = bounds[0];
+            pinned.push('left');
+          } else {
+            oob.push('left');
+          }
+        }
+        if (left + width > bounds[2]) {
+          if (__indexOf.call(pin, 'right') >= 0) {
+            left = bounds[2] - width;
+            pinned.push('right');
+          } else {
+            oob.push('right');
+          }
+        }
+        if (pinned.length) {
+          pinnedClass = (_ref7 = this.options.pinnedClass) != null ? _ref7 : this.getClass('pinned');
+          addClasses.push(pinnedClass);
+          for (_m = 0, _len4 = pinned.length; _m < _len4; _m++) {
+            side = pinned[_m];
+            addClasses.push("" + pinnedClass + "-" + side);
+          }
+        }
+        if (oob.length) {
+          oobClass = (_ref8 = this.options.outOfBoundsClass) != null ? _ref8 : this.getClass('out-of-bounds');
+          addClasses.push(oobClass);
+          for (_n = 0, _len5 = oob.length; _n < _len5; _n++) {
+            side = oob[_n];
+            addClasses.push("" + oobClass + "-" + side);
+          }
+        }
+        if (__indexOf.call(pinned, 'left') >= 0 || __indexOf.call(pinned, 'right') >= 0) {
+          eAttachment.left = tAttachment.left = false;
+        }
+        if (__indexOf.call(pinned, 'top') >= 0 || __indexOf.call(pinned, 'bottom') >= 0) {
+          eAttachment.top = tAttachment.top = false;
+        }
+        if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== this.attachment.top || eAttachment.left !== this.attachment.left) {
+          this.updateAttachClasses(eAttachment, tAttachment);
+        }
+      }
+      defer(function() {
+        updateClasses(_this.target, addClasses, allClasses);
+        return updateClasses(_this.element, addClasses, allClasses);
+      });
+      return {
+        top: top,
+        left: left
+      };
+    }
+  });
+
+}).call(this);
+
+(function() {
+  var defer, getBounds, updateClasses, _ref;
+
+  _ref = this.Tether.Utils, getBounds = _ref.getBounds, updateClasses = _ref.updateClasses, defer = _ref.defer;
+
+  this.Tether.modules.push({
+    position: function(_arg) {
+      var abutted, addClasses, allClasses, bottom, height, left, right, side, sides, targetPos, top, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3, _ref4, _ref5,
+        _this = this;
+      top = _arg.top, left = _arg.left;
+      _ref1 = this.cache('element-bounds', function() {
+        return getBounds(_this.element);
+      }), height = _ref1.height, width = _ref1.width;
+      targetPos = this.getTargetBounds();
+      bottom = top + height;
+      right = left + width;
+      abutted = [];
+      if (top <= targetPos.bottom && bottom >= targetPos.top) {
+        _ref2 = ['left', 'right'];
+        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+          side = _ref2[_i];
+          if ((_ref3 = targetPos[side]) === left || _ref3 === right) {
+            abutted.push(side);
+          }
+        }
+      }
+      if (left <= targetPos.right && right >= targetPos.left) {
+        _ref4 = ['top', 'bottom'];
+        for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) {
+          side = _ref4[_j];
+          if ((_ref5 = targetPos[side]) === top || _ref5 === bottom) {
+            abutted.push(side);
+          }
+        }
+      }
+      allClasses = [];
+      addClasses = [];
+      sides = ['left', 'top', 'right', 'bottom'];
+      allClasses.push(this.getClass('abutted'));
+      for (_k = 0, _len2 = sides.length; _k < _len2; _k++) {
+        side = sides[_k];
+        allClasses.push("" + (this.getClass('abutted')) + "-" + side);
+      }
+      if (abutted.length) {
+        addClasses.push(this.getClass('abutted'));
+      }
+      for (_l = 0, _len3 = abutted.length; _l < _len3; _l++) {
+        side = abutted[_l];
+        addClasses.push("" + (this.getClass('abutted')) + "-" + side);
+      }
+      defer(function() {
+        updateClasses(_this.target, addClasses, allClasses);
+        return updateClasses(_this.element, addClasses, allClasses);
+      });
+      return true;
+    }
+  });
+
+}).call(this);
+
+(function() {
+  this.Tether.modules.push({
+    position: function(_arg) {
+      var left, result, shift, shiftLeft, shiftTop, top, _ref;
+      top = _arg.top, left = _arg.left;
+      if (!this.options.shift) {
+        return;
+      }
+      result = function(val) {
+        if (typeof val === 'function') {
+          return val.call(this, {
+            top: top,
+            left: left
+          });
+        } else {
+          return val;
+        }
+      };
+      shift = result(this.options.shift);
+      if (typeof shift === 'string') {
+        shift = shift.split(' ');
+        shift[1] || (shift[1] = shift[0]);
+        shiftTop = shift[0], shiftLeft = shift[1];
+        shiftTop = parseFloat(shiftTop, 10);
+        shiftLeft = parseFloat(shiftLeft, 10);
+      } else {
+        _ref = [shift.top, shift.left], shiftTop = _ref[0], shiftLeft = _ref[1];
+      }
+      top += shiftTop;
+      left += shiftLeft;
+      return {
+        top: top,
+        left: left
+      };
+    }
+  });
+
+}).call(this);
+
+return this.Tether;
+
+}));
diff --git a/demo/res/img/sprite-green.png b/demo/res/img/sprite-green.png
new file mode 100755
index 0000000000000000000000000000000000000000..89fc8f2343c554babe0753c42c0d59ec3059f15a
GIT binary patch
literal 5405
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
A`~Uy|

literal 0
HcmV?d00001

diff --git a/demo/res/img/sprite-orange.png b/demo/res/img/sprite-orange.png
new file mode 100755
index 0000000000000000000000000000000000000000..49cfa479dcdd26cfbb56670c0f6caf84e169a735
GIT binary patch
literal 5374
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

literal 0
HcmV?d00001

diff --git a/demo/src/DemoInitializer.js b/demo/src/DemoInitializer.js
index a53e4dc617..16ad0739d7 100644
--- a/demo/src/DemoInitializer.js
+++ b/demo/src/DemoInitializer.js
@@ -20,13 +20,40 @@
  * at runtime from the About dialog for additional information.
  *****************************************************************************/
 /*global define*/
+require.config({
+/*    paths: {
+        tether: "demo/lib/tether/tether",
+        shepherd: "demo/lib/shepherd/shepherd.min"
+    },
+    shim: {
+        tether: {
+            exports: "tether"
+        },
+        shepherd: {
+            deps: ["tether"],
+            exports: "shepherd"
+        }
+    }*/
+    paths: {
+        hopscotch: "demo/lib/hopscotch/hopscotch.min"
+    },
+    shim: {
+        tourist: {
+            exports: "hopscotch"
+        }
+    }
 
+});
 define(
-    ["../../platform/features/conductor/src/ConductorRepresenter"],
-    function (ConductorRepresenter){
+    [
+        "../../platform/features/conductor/src/ConductorRepresenter",
+        "hopscotch",
+        "zepto"
+    ],
+    function (ConductorRepresenter, hopscotch, $){
         "use strict";
 
-        function DemoInitializer(representers) {
+        function DemoInitializer($timeout, representers) {
 
             function indexOf(array, callback) {
                 return array.reduce(function(previous, element, index) {
@@ -48,6 +75,53 @@ define(
             }
 
             removeRepresenter(ConductorRepresenter);
+
+            $timeout(function() {
+                var tour = {
+                    id: "hello-hopscotch",
+                    steps: [
+                        {
+                            title: "The Object Tree",
+                            content: "The object tree contains telemetry and" +
+                            " view <strong>objects</strong>",
+                            target: document.querySelector("mct-tree ul.tree"),
+                            placement: "right"
+                        },
+                        {
+                            title: "Creating objects",
+                            content: "New objects can be created under" +
+                            " the <strong>My Items</strong> folder using the " +
+                            " <strong>Create</strong> button",
+                            target: document.querySelector(".create-btn"),
+                            placement: "bottom"
+                        },
+                        {
+                            title: "Composing objects",
+                            content: "Objects can be composed by dragging" +
+                            " them from the tree...",
+                            target: document.querySelector("mct-tree" +
+                                " ul.tree"),
+                            placement: "right"
+                        },
+                        {
+                            title: "Composing objects (cont.)",
+                            content: "...into the current view",
+                            target: document.querySelector(".object-holder-main"),
+                            placement: "top"
+                        },
+                        {
+                            title: "Create a layout",
+                            content: "Try composing a <strong> Display Layout </strong> by creating it from the create menu, and then dragging some objects into it.",
+                            target: document.querySelector(".create-btn"),
+                            placement: "right"
+                        }
+                    ]
+                };
+                hopscotch.endTour(true);
+                // Start the tour!
+                hopscotch.startTour(tour);
+
+            }, 3000);
         }
 
         return DemoInitializer;
diff --git a/demo/src/conductor/ConductorPolicy.js b/demo/src/conductor/ConductorPolicy.js
index 20b8de910b..c2b6e3f231 100644
--- a/demo/src/conductor/ConductorPolicy.js
+++ b/demo/src/conductor/ConductorPolicy.js
@@ -48,6 +48,12 @@ define(
             }, true);
         }
 
+        function or(array) {
+            return array.reduce(function (previous, next) {
+                return previous || next;
+            }, false);
+        }
+
         /**
          * @param {DomainObject} candidate
          * @returns {Promise} a promise resolved with true if the object
@@ -66,7 +72,7 @@ define(
                         if (composition.length === 0 ) {
                             return fastPromise(false);
                         } else {
-                            return self.$q.all(composition.map(self.allow.bind(self))).then(and);
+                            return self.$q.all(composition.map(self.allow.bind(self))).then(or);
                         }
                     });
                 } else {
diff --git a/demo/src/conductor/DemoConductorRepresenter.js b/demo/src/conductor/DemoConductorRepresenter.js
index 6515fab67e..1fdfab2b5d 100644
--- a/demo/src/conductor/DemoConductorRepresenter.js
+++ b/demo/src/conductor/DemoConductorRepresenter.js
@@ -36,6 +36,7 @@ define(
             conductorService,
             views,
             throttle,
+            navigationService,
             scope,
             element
         ) {
@@ -43,6 +44,7 @@ define(
             this.element = element;
             this.views = views;
             this.conductorPolicy = new ConductorPolicy($q);
+            this.navigationService = navigationService;
 
             ConductorRepresenter.call(this,
                 throttle,
@@ -57,7 +59,8 @@ define(
 
         DemoConductorRepresenter.prototype.represent = function (representation, representedObject) {
             var self = this;
-            if (this.views.indexOf(representation) !== -1) {
+            if (this.views.indexOf(representation) !== -1 && representedObject.getId() === this.navigationService.getNavigation().getId()) {
+
                 this.conductorPolicy.allow(representedObject).then(function (show) {
                     if (show && representation.type !== 'folder') {
                         ConductorRepresenter.prototype.represent.call(self, representation, representedObject);
@@ -66,7 +69,5 @@ define(
             }
         };
 
-        DemoConductorRepresenter.prototype.destroy = function destroy() {};
-
         return DemoConductorRepresenter;
     });