diff options
| -rw-r--r-- | docs/getting-started.md | 69 | ||||
| -rw-r--r-- | docs/guide/type.md | 107 | ||||
| -rw-r--r-- | docs/juxtapose.css | 347 | ||||
| -rw-r--r-- | docs/juxtapose.js | 760 | ||||
| -rw-r--r-- | docs/lightslider.min.css | 3 | ||||
| -rw-r--r-- | docs/lightslider.min.js | 4 | ||||
| -rw-r--r-- | mkdocs.yml | 4 |
7 files changed, 1130 insertions, 164 deletions
diff --git a/docs/getting-started.md b/docs/getting-started.md index 6b554e1e..f93f3c30 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -339,74 +339,11 @@ The table-based layout provides field-based sorting and multi-select. Clicking t The [`analysis.types.TemplateSimplifier`](#analysis.types.TemplateSimplifier) setting can be helpful when working with C++ symbols. -<div class="inline-slides"> - <ol id="inline-slides-text"> - <li id="currentline">Before Simplification</li> - <li>After Simplification</li> - </ol> - <div id="image-slider-container"> - <ul id="image-slider"> - <li> - <img src="img/before-template-simplification.png" alt="Before Simplification"/> - </li> - <li> - <img src="img/after-template-simplification.png" alt="After Simplification"/> - </li> - </ul> - </div> +<div class="juxtapose"> + <img src="img/before-template-simplification.png" data-label="Before Simplification"/> + <img src="img/after-template-simplification.png" data-label="After Simplification"/> </div> -_hover over the image to temporarily pause_ - -<script> -document.addEventListener("DOMContentLoaded", function(event) { - let pause = 3000; - let slider = $("#image-slider"); - let sliderContainer = $(slider.selector + "-container"); - window.slider = slider.lightSlider({ - item:1, - loop: false, - auto: true, - speed: 200, - pause: pause, - slideMargin: 0, - pauseOnHover: true, - autoWidth:false, - thumbMargin:0, - onBeforeSlide: function (el) { - Array.from($('ol#inline-slides-text')[0].children).forEach(function(item, index, arr) { - if (index == el.getCurrentSlideCount() - 1) - item.id = "currentline"; - else - item.id = ""; - }); - }, - onSliderLoad: function() { - let sliderHeight = slider.height(); - slider.find('img').each(function() { - $(this).parent().css("padding-top", (sliderHeight - this.naturalHeight)/2); - }); - slider.removeClass('hiddenc'); - }, - onAfterSlide: function(el) { - if (el.getCurrentSlideCount() == el.getTotalSlideCount()) { - setTimeout(() => {!el.is(':hover') && el.goToSlide(0)}, pause); - } - }, - onBeforeStart: function() { - let width = 0; - slider.find('img').each(function() { - width = Math.max(width, this.naturalWidth); - }); - sliderContainer.width(width); - }, - }); - Array.from($('ol#inline-slides-text')[0].children).forEach(function(item, index, arr) { - item.addEventListener('click', function() { window.slider.goToSlide(index)}); - }); -}); -</script> - #### Cross-Reference Filtering  diff --git a/docs/guide/type.md b/docs/guide/type.md index cacc6060..839970b8 100644 --- a/docs/guide/type.md +++ b/docs/guide/type.md @@ -30,94 +30,23 @@ The simplest way to directly manipulate types in disassembly is by viewing an ex New to [stable version 1.3.2015](https://binary.ninja/changelog/) is the "Smart Structures" feature. Rather than manually create a type in the type view and then apply it to disassembly, you can create structures directly from disassembly using the `s` hotkey. Consider the following example (created using [taped](binaryninja:http://captf.com/2011/gits/taped) from the 2011 Ghost in the Shellcode CTF if you'd like to play along at home): -<div class="inline-slides"> - <ol id="inline-slides-text"> - <li id="currentline">Assembly view of the start of <code>0x8048e20</code></li> - <li>MLIL view of the same basic block</li> - <li>MLIL view after selecting the return of <code>calloc</code> and pressing <code>s</code></li> - <li>MLIL view after selecting the offset and pressing <code>s</code> to turn it into a member access</li> - <li>MLIL view after selecting the remaining offsets and pressing <code>s</code> in turn</li> - <li>Viewing the structure automatically created after this workflow</li> - <li>Selecting the remaining bytes and turning them into an array using <code>1</code> to turn them all into uint_8 variables, and then <code>*</code> to turn them all into an array</li> - </ol> - <div id="image-slider-container"> - <ul id="image-slider"> - <li> - <img src="../img/taped-1.png" alt="Structure Workflow 1"/> - </li> - <li> - <img src="../img/taped-2.png" alt="Structure Workflow 2"/> - </li> - <li> - <img src="../img/taped-3.png" alt="Structure Workflow 3"/> - </li> - <li> - <img src="../img/taped-4.png" alt="Structure Workflow 4"/> - </li> - <li> - <img src="../img/taped-5.png" alt="Structure Workflow 5"/> - </li> - <li> - <img src="../img/taped-6.png" alt="Structure Workflow 6"/> - </li> - <li> - <img src="../img/taped-7.png" alt="Structure Workflow 7"/> - </li> - </ul> - </div> -</div> +| Step | Preview | +|------|--------| +| Assembly view of the start of <code>0x8048e20</code> | <img src="../img/taped-1.png" alt="Structure Workflow 1"/> | +| MLIL view of the same basic block | <img src="../img/taped-2.png" alt="Structure Workflow 2"/> | +| MLIL view after selecting the return of <code>calloc</code> and pressing <code>s</code> | <img src="../img/taped-3.png" alt="Structure Workflow 3"/> | +| MLIL view after selecting the offset and pressing <code>s</code> to turn it into a member access | <img src="../img/taped-4.png" alt="Structure Workflow 4"/> | +| MLIL view after selecting the remaining offsets and pressing <code>s</code> in turn | <img src="../img/taped-5.png" alt="Structure Workflow 5"/> | +| Viewing the structure automatically created after this workflow | <img src="../img/taped-6.png" alt="Structure Workflow 6"/> | +| Selecting the remaining bytes and turning them into an array using <code>1</code> to turn them all into uint_8 variables, and then <code>*</code> to turn them all into an array | <img src="../img/taped-7.png" alt="Structure Workflow 7"/> | -_hover over the image to temporarily pause_ - - -<script> -document.addEventListener("DOMContentLoaded", function(event) { - let pause = 3000; - let slider = $("#image-slider"); - let sliderContainer = $(slider.selector + "-container"); - window.slider = slider.lightSlider({ - item:1, - loop: false, - auto: true, - speed: 200, - pause: pause, - slideMargin: 0, - pauseOnHover: true, - autoWidth:false, - thumbMargin:0, - onBeforeSlide: function (el) { - Array.from($('ol#inline-slides-text')[0].children).forEach(function(item, index, arr) { - if (index == el.getCurrentSlideCount() - 1) - item.id = "currentline"; - else - item.id = ""; - }); - }, - onSliderLoad: function() { - let sliderHeight = slider.height(); - slider.find('img').each(function() { - $(this).parent().css("padding-top", (sliderHeight - this.naturalHeight)/2); - }); - slider.removeClass('hiddenc'); - }, - onAfterSlide: function(el) { - if (el.getCurrentSlideCount() == el.getTotalSlideCount()) { - setTimeout(() => {!el.is(':hover') && el.goToSlide(0)}, pause); - } - }, - onBeforeStart: function() { - let width = 0; - slider.find('img').each(function() { - width = Math.max(width, this.naturalWidth); - }); - sliderContainer.width(width); - }, - }); - Array.from($('ol#inline-slides-text')[0].children).forEach(function(item, index, arr) { - item.addEventListener('click', function() { window.slider.goToSlide(index)}); - }); -}); -</script> +<style> + #smart-structures-workflow + p + .wy-table-responsive td:first-child { + max-width: 500px; + word-break: break-word; + white-space: break-spaces; + } +</style> Note that the last step is entirely optional. Now that we've created a basic structure, and if we happen to do some reverse engineering on these binaries, we learn that this is actually a linked list and that the structures should look like: @@ -646,7 +575,7 @@ typelib.write_to_file('test.so.1.bntl') ### Other Type Library Questions -#### What's a named type vs. just a type? +#### What's a named type vs. just a type? Some variable definitions have type information, but don't produce a type name useful for future definitions, examples: @@ -798,7 +727,7 @@ Type class=Structure ``` Here is the representation of `type int ()(int, int)` named `MyFunctionType` from [typelib_create.py](https://github.com/Vector35/binaryninja-api/blob/dev/python/examples/typelib_create.py): -#### When do named objects get used? +#### When do named objects get used? When a binary is loaded and its external symbols is processed, the symbol names are searched against the named objects from type libraries. If there is a match, it obeys the type from the type library. Upon success, you'll see a message like: diff --git a/docs/juxtapose.css b/docs/juxtapose.css new file mode 100644 index 00000000..21367132 --- /dev/null +++ b/docs/juxtapose.css @@ -0,0 +1,347 @@ +/* juxtapose - v1.2.2 - 2020-09-03 + * Copyright (c) 2020 Alex Duner and Northwestern University Knight Lab + */ +div.juxtapose { + width: 100%; + font-family: Helvetica, Arial, sans-serif; +} + +div.jx-slider { + width: 100%; + height: 100%; + position: relative; + overflow: hidden; + cursor: pointer; + color: #f3f3f3; +} + + +div.jx-handle { + position: absolute; + height: 100%; + width: 40px; + cursor: col-resize; + z-index: 15; + margin-left: -20px; +} + +.vertical div.jx-handle { + height: 40px; + width: 100%; + cursor: row-resize; + margin-top: -20px; + margin-left: 0; +} + +div.jx-control { + height: 100%; + margin-right: auto; + margin-left: auto; + width: 3px; + background-color: currentColor; +} + +.vertical div.jx-control { + height: 3px; + width: 100%; + background-color: currentColor; + position: relative; + top: 50%; + transform: translateY(-50%); +} + +div.jx-controller { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + height: 60px; + width: 9px; + margin-left: -3px; + background-color: currentColor; +} + +.vertical div.jx-controller { + height: 9px; + width: 100px; + margin-left: auto; + margin-right: auto; + top: -3px; + position: relative; +} + +div.jx-arrow { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + width: 0; + height: 0; + transition: all .2s ease; +} + +.vertical div.jx-arrow { + position: absolute; + margin: 0 auto; + left: 0; + right: 0; + width: 0; + height: 0; + transition: all .2s ease; +} + + +div.jx-arrow.jx-left { + left: 2px; + border-style: solid; + border-width: 8px 8px 8px 0; + border-color: transparent currentColor transparent transparent; +} + +div.jx-arrow.jx-right { + right: 2px; + border-style: solid; + border-width: 8px 0 8px 8px; + border-color: transparent transparent transparent currentColor; +} + +.vertical div.jx-arrow.jx-left { + left: 0px; + top: 2px; + border-style: solid; + border-width: 0px 8px 8px 8px; + border-color: transparent transparent currentColor transparent; +} + +.vertical div.jx-arrow.jx-right { + right: 0px; + top: auto; + bottom: 2px; + border-style: solid; + border-width: 8px 8px 0 8px; + border-color: currentColor transparent transparent transparent; +} + +div.jx-handle:hover div.jx-arrow.jx-left, +div.jx-handle:active div.jx-arrow.jx-left { + left: -1px; +} + +div.jx-handle:hover div.jx-arrow.jx-right, +div.jx-handle:active div.jx-arrow.jx-right { + right: -1px; +} + +.vertical div.jx-handle:hover div.jx-arrow.jx-left, +.vertical div.jx-handle:active div.jx-arrow.jx-left { + left: 0px; + top: 0px; +} + +.vertical div.jx-handle:hover div.jx-arrow.jx-right, +.vertical div.jx-handle:active div.jx-arrow.jx-right { + right: 0px; + bottom: 0px; +} + + +div.jx-image { + position: absolute; + height: 100%; + display: inline-block; + top: 0; + overflow: hidden; + -webkit-backface-visibility: hidden; +} + +.vertical div.jx-image { + width: 100%; + left: 0; + top: auto; +} + +div.jx-image img { + height: 100%; + width: auto; + z-index: 5; + position: absolute; + margin-bottom: 0; + + max-height: none; + max-width: none; + max-height: initial; + max-width: initial; +} + +.vertical div.jx-image img { + height: auto; + width: 100%; +} + +div.jx-image.jx-left { + left: 0; + background-position: left; +} + +div.jx-image.jx-left img { + left: 0; +} + +div.jx-image.jx-right { + right: 0; + background-position: right; +} + +div.jx-image.jx-right img { + right: 0; + bottom: 0; +} + + +.veritcal div.jx-image.jx-left { + top: 0; + background-position: top; +} + +.veritcal div.jx-image.jx-left img { + top: 0; +} + +.vertical div.jx-image.jx-right { + bottom: 0; + background-position: bottom; +} + +.veritcal div.jx-image.jx-right img { + bottom: 0; +} + + +div.jx-image div.jx-label { + font-size: 1em; + padding: .25em .75em; + position: relative; + display: inline-block; + top: 0; + background-color: #000; /* IE 8 */ + background-color: rgba(0,0,0,.7); + color: white; + z-index: 10; + white-space: nowrap; + line-height: 18px; + vertical-align: middle; +} + +div.jx-image.jx-left div.jx-label { + float: left; + left: 0; +} + +div.jx-image.jx-right div.jx-label { + float: right; + right: 0; +} + +.vertical div.jx-image div.jx-label { + display: table; + position: absolute; +} + +.vertical div.jx-image.jx-right div.jx-label { + left: 0; + bottom: 0; + top: auto; +} + +div.jx-credit { + line-height: 1.1; + font-size: 0.75em; +} + +div.jx-credit em { + font-weight: bold; + font-style: normal; +} + + +/* Animation */ + +div.jx-image.transition { + transition: width .5s ease; +} + +div.jx-handle.transition { + transition: left .5s ease; +} + +.vertical div.jx-image.transition { + transition: height .5s ease; +} + +.vertical div.jx-handle.transition { + transition: top .5s ease; +} + +/* Knight Lab Credit */ +a.jx-knightlab { + background-color: #000; /* IE 8 */ + background-color: rgba(0,0,0,.25); + bottom: 0; + display: table; + height: 14px; + line-height: 14px; + padding: 1px 4px 1px 5px; + position: absolute; + right: 0; + text-decoration: none; + z-index: 10; +} + +a.jx-knightlab div.knightlab-logo { + display: inline-block; + vertical-align: middle; + height: 8px; + width: 8px; + background-color: #c34528; + transform: rotate(45deg); + -ms-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + top: -1.25px; + position: relative; + cursor: pointer; +} + +a.jx-knightlab:hover { + background-color: #000; /* IE 8 */ + background-color: rgba(0,0,0,.35); +} +a.jx-knightlab:hover div.knightlab-logo { + background-color: #ce4d28; +} + +a.jx-knightlab span.juxtapose-name { + display: table-cell; + margin: 0; + padding: 0; + font-family: Helvetica, Arial, sans-serif; + font-weight: 300; + color: white; + font-size: 10px; + padding-left: 0.375em; + vertical-align: middle; + line-height: normal; + text-shadow: none; +} + +/* keyboard accessibility */ +div.jx-controller:focus, +div.jx-image.jx-left div.jx-label:focus, +div.jx-image.jx-right div.jx-label:focus, +a.jx-knightlab:focus { + background: #eae34a; + color: #000; +} +a.jx-knightlab:focus span.juxtapose-name{ + color: #000; + border: none; +} diff --git a/docs/juxtapose.js b/docs/juxtapose.js new file mode 100644 index 00000000..240e8b26 --- /dev/null +++ b/docs/juxtapose.js @@ -0,0 +1,760 @@ +/* juxtapose - v1.2.2 - 2020-09-03 + * Copyright (c) 2020 Alex Duner and Northwestern University Knight Lab + */ +/* juxtapose - v1.1.2 - 2015-07-16 + * Copyright (c) 2015 Alex Duner and Northwestern University Knight Lab + */ + +(function(document, window) { + + var juxtapose = { + sliders: [], + OPTIMIZATION_ACCEPTED: 1, + OPTIMIZATION_WAS_CONSTRAINED: 2 + }; + + var flickr_key = "d90fc2d1f4acc584e08b8eaea5bf4d6c"; + var FLICKR_SIZE_PREFERENCES = ['Large', 'Medium']; + + function Graphic(properties, slider) { + var self = this; + this.image = new Image(); + + this.loaded = false; + this.image.onload = function() { + self.loaded = true; + slider._onLoaded(); + }; + + this.image.src = properties.src; + this.image.alt = properties.alt || ''; + this.label = properties.label || false; + this.credit = properties.credit || false; + } + + function FlickrGraphic(properties, slider) { + var self = this; + this.image = new Image(); + + this.loaded = false; + this.image.onload = function() { + self.loaded = true; + slider._onLoaded(); + }; + + this.flickrID = this.getFlickrID(properties.src); + this.callFlickrAPI(this.flickrID, self); + + this.label = properties.label || false; + this.credit = properties.credit || false; + } + + FlickrGraphic.prototype = { + getFlickrID: function(url) { + if (url.match(/flic.kr\/.+/i)) { + var encoded = url.split('/').slice(-1)[0]; + return base58Decode(encoded); + } + var idx = url.indexOf("flickr.com/photos/"); + var pos = idx + "flickr.com/photos/".length; + var photo_info = url.substr(pos); + if (photo_info.indexOf('/') == -1) return null; + if (photo_info.indexOf('/') === 0) photo_info = photo_info.substr(1); + id = photo_info.split("/")[1]; + return id; + }, + + callFlickrAPI: function(id, self) { + var url = 'https://api.flickr.com/services/rest/?method=flickr.photos.getSizes' + + '&api_key=' + flickr_key + + '&photo_id=' + id + '&format=json&nojsoncallback=1'; + + var request = new XMLHttpRequest(); + request.open('GET', url, true); + request.onload = function() { + if (request.status >= 200 && request.status < 400) { + data = JSON.parse(request.responseText); + var flickr_url = self.bestFlickrUrl(data.sizes.size); + self.setFlickrImage(flickr_url); + } else { + console.error("There was an error getting the picture from Flickr"); + } + }; + request.onerror = function() { + console.error("There was an error getting the picture from Flickr"); + }; + request.send(); + }, + + setFlickrImage: function(src) { + this.image.src = src; + }, + + bestFlickrUrl: function(ary) { + var dict = {}; + for (var i = 0; i < ary.length; i++) { + dict[ary[i].label] = ary[i].source; + } + for (var j = 0; j < FLICKR_SIZE_PREFERENCES.length; j++) { + if (FLICKR_SIZE_PREFERENCES[j] in dict) { + return dict[FLICKR_SIZE_PREFERENCES[j]]; + } + } + return ary[0].source; + } + }; + + function getNaturalDimensions(DOMelement) { + if (DOMelement.naturalWidth && DOMelement.naturalHeight) { + return { width: DOMelement.naturalWidth, height: DOMelement.naturalHeight }; + } + // https://www.jacklmoore.com/notes/naturalwidth-and-naturalheight-in-ie/ + var img = new Image(); + img.src = DOMelement.src; + return { width: img.width, height: img.height }; + } + + function getImageDimensions(img) { + var dimensions = { + width: getNaturalDimensions(img).width, + height: getNaturalDimensions(img).height, + aspect: function() { return (this.width / this.height); } + }; + return dimensions; + } + + function addClass(element, c) { + if (element.classList) { + element.classList.add(c); + } else { + element.className += " " + c; + } + } + + function removeClass(element, c) { + element.className = element.className.replace(/(\S+)\s*/g, function(w, match) { + if (match === c) { + return ''; + } + return w; + }).replace(/^\s+/, ''); + } + + function setText(element, text) { + if (document.body.textContent) { + element.textContent = text; + } else { + element.innerText = text; + } + } + + function getComputedWidthAndHeight(element) { + if (window.getComputedStyle) { + return { + width: parseInt(getComputedStyle(element).width, 10), + height: parseInt(getComputedStyle(element).height, 10) + }; + } else { + w = element.getBoundingClientRect().right - element.getBoundingClientRect().left; + h = element.getBoundingClientRect().bottom - element.getBoundingClientRect().top; + return { + width: parseInt(w, 10) || 0, + height: parseInt(h, 10) || 0 + }; + } + } + + function viewport() { + var e = window, + a = 'inner'; + if (!('innerWidth' in window)) { + a = 'client'; + e = document.documentElement || document.body; + } + return { width: e[a + 'Width'], height: e[a + 'Height'] } + } + + function getPageX(e) { + var pageX; + if (e.pageX) { + pageX = e.pageX; + } else if (e.touches) { + pageX = e.touches[0].pageX; + } else { + pageX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + } + return pageX; + } + + function getPageY(e) { + var pageY; + if (e.pageY) { + pageY = e.pageY; + } else if (e.touches) { + pageY = e.touches[0].pageY; + } else { + pageY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + return pageY; + } + + function checkFlickr(url) { + if (url.match(/flic.kr\/.+/i)) { + return true; + } + var idx = url.indexOf("flickr.com/photos/"); + if (idx == -1) { + return false; + } else { + return true; + } + } + + function base58Decode(encoded) { + var alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ', + base = alphabet.length; + if (typeof encoded !== 'string') { + throw '"base58Decode" only accepts strings.'; + } + var decoded = 0; + while (encoded) { + var alphabetPosition = alphabet.indexOf(encoded[0]); + if (alphabetPosition < 0) { + throw '"base58Decode" can\'t find "' + encoded[0] + '" in the alphabet: "' + alphabet + '"'; + } + var powerOf = encoded.length - 1; + decoded += alphabetPosition * (Math.pow(base, powerOf)); + encoded = encoded.substring(1); + } + return decoded.toString(); + } + + function getLeftPercent(slider, input) { + if (typeof(input) === "string" || typeof(input) === "number") { + leftPercent = parseInt(input, 10); + } else { + var sliderRect = slider.getBoundingClientRect(); + var offset = { + top: sliderRect.top + document.body.scrollTop + document.documentElement.scrollTop, + left: sliderRect.left + document.body.scrollLeft + document.documentElement.scrollLeft + }; + var width = slider.offsetWidth; + var pageX = getPageX(input); + var relativeX = pageX - offset.left; + leftPercent = (relativeX / width) * 100; + } + return leftPercent; + } + + function getTopPercent(slider, input) { + if (typeof(input) === "string" || typeof(input) === "number") { + topPercent = parseInt(input, 10); + } else { + var sliderRect = slider.getBoundingClientRect(); + var offset = { + top: sliderRect.top + document.body.scrollTop + document.documentElement.scrollTop, + left: sliderRect.left + document.body.scrollLeft + document.documentElement.scrollLeft + }; + var width = slider.offsetHeight; + var pageY = getPageY(input); + var relativeY = pageY - offset.top; + topPercent = (relativeY / width) * 100; + } + return topPercent; + } + + // values of BOOLEAN_OPTIONS are ignored. just used for 'in' test on keys + var BOOLEAN_OPTIONS = { 'animate': true, 'showLabels': true, 'showCredits': true, 'makeResponsive': true }; + + function interpret_boolean(x) { + if (typeof(x) != 'string') { + return Boolean(x); + } + return !(x === 'false' || x === ''); + } + + function JXSlider(selector, images, options) { + + this.selector = selector; + + var i; + this.options = { // new options must have default values set here. + animate: true, + showLabels: true, + showCredits: true, + makeResponsive: true, + startingPosition: "50%", + mode: 'horizontal', + callback: null // pass a callback function if you like + }; + + for (i in this.options) { + if (i in options) { + if (i in BOOLEAN_OPTIONS) { + this.options[i] = interpret_boolean(options[i]); + } else { + this.options[i] = options[i]; + } + } + } + + if (images.length == 2) { + + if (checkFlickr(images[0].src)) { + this.imgBefore = new FlickrGraphic(images[0], this); + } else { + this.imgBefore = new Graphic(images[0], this); + } + + if (checkFlickr(images[1].src)) { + this.imgAfter = new FlickrGraphic(images[1], this); + } else { + this.imgAfter = new Graphic(images[1], this); + } + + } else { + console.warn("The images parameter takes two Image objects."); + } + + if (this.imgBefore.credit || this.imgAfter.credit) { + this.options.showCredits = true; + } else { + this.options.showCredits = false; + } + } + + JXSlider.prototype = { + + updateSlider: function(input, animate) { + var leftPercent, rightPercent; + + if (this.options.mode === "vertical") { + leftPercent = getTopPercent(this.slider, input); + } else { + leftPercent = getLeftPercent(this.slider, input); + } + + leftPercent = leftPercent.toFixed(2) + "%"; + leftPercentNum = parseFloat(leftPercent); + rightPercent = (100 - leftPercentNum) + "%"; + + if (leftPercentNum > 0 && leftPercentNum < 100) { + removeClass(this.handle, 'transition'); + removeClass(this.rightImage, 'transition'); + removeClass(this.leftImage, 'transition'); + + if (this.options.animate && animate) { + addClass(this.handle, 'transition'); + addClass(this.leftImage, 'transition'); + addClass(this.rightImage, 'transition'); + } + + if (this.options.mode === "vertical") { + this.handle.style.top = leftPercent; + this.leftImage.style.height = leftPercent; + this.rightImage.style.height = rightPercent; + } else { + this.handle.style.left = leftPercent; + this.leftImage.style.width = leftPercent; + this.rightImage.style.width = rightPercent; + } + this.sliderPosition = leftPercent; + } + }, + + getPosition: function() { + return this.sliderPosition; + }, + + displayLabel: function(element, labelText) { + label = document.createElement("div"); + label.className = 'jx-label'; + label.setAttribute('tabindex', 0); //put the controller in the natural tab order of the document + + setText(label, labelText); + element.appendChild(label); + }, + + displayCredits: function() { + credit = document.createElement("div"); + credit.className = "jx-credit"; + + text = "<em>Photo Credits:</em>"; + if (this.imgBefore.credit) { text += " <em>Before</em> " + this.imgBefore.credit; } + if (this.imgAfter.credit) { text += " <em>After</em> " + this.imgAfter.credit; } + + credit.innerHTML = text; + + this.wrapper.appendChild(credit); + }, + + setStartingPosition: function(s) { + this.options.startingPosition = s; + }, + + checkImages: function() { + if (getImageDimensions(this.imgBefore.image).aspect() == + getImageDimensions(this.imgAfter.image).aspect()) { + return true; + } else { + return false; + } + }, + + calculateDims: function(width, height) { + var ratio = getImageDimensions(this.imgBefore.image).aspect(); + if (width) { + height = width / ratio; + } else if (height) { + width = height * ratio; + } + return { + width: width, + height: height, + ratio: ratio + }; + }, + + responsivizeIframe: function(dims) { + //Check the slider dimensions against the iframe (window) dimensions + if (dims.height < window.innerHeight) { + //If the aspect ratio is greater than 1, imgs are landscape, so letterbox top and bottom + if (dims.ratio >= 1) { + this.wrapper.style.paddingTop = parseInt((window.innerHeight - dims.height) / 2) + "px"; + } + } else if (dims.height > window.innerHeight) { + /* If the image is too tall for the window, which happens at 100% width on large screens, + * force dimension recalculation based on height instead of width */ + dims = this.calculateDims(0, window.innerHeight); + this.wrapper.style.paddingLeft = parseInt((window.innerWidth - dims.width) / 2) + "px"; + } + if (this.options.showCredits) { + // accommodate the credits box within the iframe + dims.height -= 13; + } + return dims; + }, + + setWrapperDimensions: function() { + var wrapperWidth = getComputedWidthAndHeight(this.wrapper).width; + var wrapperHeight = getComputedWidthAndHeight(this.wrapper).height; + var dims = this.calculateDims(wrapperWidth, wrapperHeight); + // if window is in iframe, make sure images don't overflow boundaries + if (window.location !== window.parent.location && !this.options.makeResponsive) { + dims = this.responsivizeIframe(dims); + } + + this.wrapper.style.height = parseInt(dims.height) + "px"; + this.wrapper.style.width = parseInt(dims.width) + "px"; + }, + + optimizeWrapper: function(maxWidth) { + var result = juxtapose.OPTIMIZATION_ACCEPTED; + if ((this.imgBefore.image.naturalWidth >= maxWidth) && (this.imgAfter.image.naturalWidth >= maxWidth)) { + this.wrapper.style.width = maxWidth + "px"; + result = juxtapose.OPTIMIZATION_WAS_CONSTRAINED; + } else if (this.imgAfter.image.naturalWidth < maxWidth) { + this.wrapper.style.width = this.imgAfter.image.naturalWidth + "px"; + } else { + this.wrapper.style.width = this.imgBefore.image.naturalWidth + "px"; + } + this.setWrapperDimensions(); + return result; + }, + + _onLoaded: function() { + + if (this.imgBefore && this.imgBefore.loaded === true && + this.imgAfter && this.imgAfter.loaded === true) { + + this.wrapper = document.querySelector(this.selector); + addClass(this.wrapper, 'juxtapose'); + + this.wrapper.style.width = getNaturalDimensions(this.imgBefore.image).width; + this.setWrapperDimensions(); + + this.slider = document.createElement("div"); + this.slider.className = 'jx-slider'; + this.wrapper.appendChild(this.slider); + + if (this.options.mode != "horizontal") { + addClass(this.slider, this.options.mode); + } + + this.handle = document.createElement("div"); + this.handle.className = 'jx-handle'; + + this.rightImage = document.createElement("div"); + this.rightImage.className = 'jx-image jx-right'; + this.rightImage.appendChild(this.imgAfter.image); + + + this.leftImage = document.createElement("div"); + this.leftImage.className = 'jx-image jx-left'; + this.leftImage.appendChild(this.imgBefore.image); + + this.labCredit = document.createElement("a"); + this.labCredit.setAttribute('href', 'https://juxtapose.knightlab.com'); + this.labCredit.setAttribute('target', '_blank'); + this.labCredit.setAttribute('rel', 'noopener'); + this.labCredit.className = 'jx-knightlab'; + this.labLogo = document.createElement("div"); + this.labLogo.className = 'knightlab-logo'; + this.labCredit.appendChild(this.labLogo); + this.projectName = document.createElement("span"); + this.projectName.className = 'juxtapose-name'; + setText(this.projectName, 'JuxtaposeJS'); + this.labCredit.appendChild(this.projectName); + + this.slider.appendChild(this.handle); + this.slider.appendChild(this.leftImage); + this.slider.appendChild(this.rightImage); + this.slider.appendChild(this.labCredit); + + this.leftArrow = document.createElement("div"); + this.rightArrow = document.createElement("div"); + this.control = document.createElement("div"); + this.controller = document.createElement("div"); + + this.leftArrow.className = 'jx-arrow jx-left'; + this.rightArrow.className = 'jx-arrow jx-right'; + this.control.className = 'jx-control'; + this.controller.className = 'jx-controller'; + + this.controller.setAttribute('tabindex', 0); //put the controller in the natural tab order of the document + this.controller.setAttribute('role', 'slider'); + this.controller.setAttribute('aria-valuenow', 50); + this.controller.setAttribute('aria-valuemin', 0); + this.controller.setAttribute('aria-valuemax', 100); + + this.handle.appendChild(this.leftArrow); + this.handle.appendChild(this.control); + this.handle.appendChild(this.rightArrow); + this.control.appendChild(this.controller); + + this._init(); + } + }, + + _init: function() { + + if (this.checkImages() === false) { + console.warn(this, "Check that the two images have the same aspect ratio for the slider to work correctly."); + } + + this.updateSlider(this.options.startingPosition, false); + + if (this.options.showLabels === true) { + if (this.imgBefore.label) { this.displayLabel(this.leftImage, this.imgBefore.label); } + if (this.imgAfter.label) { this.displayLabel(this.rightImage, this.imgAfter.label); } + } + + if (this.options.showCredits === true) { + this.displayCredits(); + } + + var self = this; + window.addEventListener("resize", function() { + self.setWrapperDimensions(); + }); + + + // Set up Javascript Events + // On mousedown, call updateSlider then set animate to false + // (if animate is true, adds css transition when updating). + + this.slider.addEventListener("mousedown", function(e) { + e = e || window.event; + e.preventDefault(); + self.updateSlider(e, true); + animate = true; + + this.addEventListener("mousemove", function(e) { + e = e || window.event; + e.preventDefault(); + if (animate) { self.updateSlider(e, false); } + }); + + this.addEventListener('mouseup', function(e) { + e = e || window.event; + e.preventDefault(); + e.stopPropagation(); + this.removeEventListener('mouseup', arguments.callee); + animate = false; + }); + }); + + this.slider.addEventListener("touchstart", function(e) { + e = e || window.event; + e.preventDefault(); + e.stopPropagation(); + self.updateSlider(e, true); + + this.addEventListener("touchmove", function(e) { + e = e || window.event; + e.preventDefault(); + e.stopPropagation(); + self.updateSlider(event, false); + }); + + }); + + /* keyboard accessibility */ + + this.handle.addEventListener("keydown", function(e) { + e = e || window.event; + var key = e.which || e.keyCode; + var ariaValue = parseFloat(this.style.left); + + //move jx-controller left + if (key == 37) { + ariaValue = ariaValue - 1; + var leftStart = parseFloat(this.style.left) - 1; + self.updateSlider(leftStart, false); + self.controller.setAttribute('aria-valuenow', ariaValue); + } + + //move jx-controller right + if (key == 39) { + ariaValue = ariaValue + 1; + var rightStart = parseFloat(this.style.left) + 1; + self.updateSlider(rightStart, false); + self.controller.setAttribute('aria-valuenow', ariaValue); + } + }); + + //toggle right-hand image visibility + this.leftImage.addEventListener("keydown", function(event) { + var key = event.which || event.keyCode; + if ((key == 13) || (key == 32)) { + self.updateSlider("90%", true); + self.controller.setAttribute('aria-valuenow', 90); + } + }); + + //toggle left-hand image visibility + this.rightImage.addEventListener("keydown", function(event) { + var key = event.which || event.keyCode; + if ((key == 13) || (key == 32)) { + self.updateSlider("10%", true); + self.controller.setAttribute('aria-valuenow', 10); + } + }); + + juxtapose.sliders.push(this); + + if (this.options.callback && typeof(this.options.callback) == 'function') { + this.options.callback(this); + } + } + + }; + + /* + Given an element that is configured with the proper data elements, make a slider out of it. + Normally this will just be used by scanPage. + */ + juxtapose.makeSlider = function(element, idx) { + if (typeof idx == 'undefined') { + idx = juxtapose.sliders.length; // not super threadsafe... + } + + var w = element; + + var images = w.querySelectorAll('img'); + + var options = {}; + // don't set empty string into options, that's a false false. + if (w.getAttribute('data-animate')) { + options.animate = w.getAttribute('data-animate'); + } + if (w.getAttribute('data-showlabels')) { + options.showLabels = w.getAttribute('data-showlabels'); + } + if (w.getAttribute('data-showcredits')) { + options.showCredits = w.getAttribute('data-showcredits'); + } + if (w.getAttribute('data-startingposition')) { + options.startingPosition = w.getAttribute('data-startingposition'); + } + if (w.getAttribute('data-mode')) { + options.mode = w.getAttribute('data-mode'); + } + if (w.getAttribute('data-makeresponsive')) { + options.mode = w.getAttribute('data-makeresponsive'); + } + + specificClass = 'juxtapose-' + idx; + addClass(element, specificClass); + + selector = '.' + specificClass; + + if (w.innerHTML) { + w.innerHTML = ''; + } else { + w.innerText = ''; + } + + slider = new juxtapose.JXSlider( + selector, [{ + src: images[0].src, + label: images[0].getAttribute('data-label'), + credit: images[0].getAttribute('data-credit'), + alt: images[0].alt + }, + { + src: images[1].src, + label: images[1].getAttribute('data-label'), + credit: images[1].getAttribute('data-credit'), + alt: images[1].alt + } + ], + options + ); + }; + + //Enable HTML Implementation + juxtapose.scanPage = function() { + var elements = document.querySelectorAll('.juxtapose'); + for (var i = 0; i < elements.length; i++) { + juxtapose.makeSlider(elements[i], i); + } + }; + + juxtapose.JXSlider = JXSlider; + window.juxtapose = juxtapose; + + juxtapose.scanPage(); + +}(document, window)); + + +// addEventListener polyfill / jonathantneal +!window.addEventListener && (function(WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) { + WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function(type, listener) { + var target = this; + + registry.unshift([target, type, listener, function(event) { + event.currentTarget = target; + event.preventDefault = function() { event.returnValue = false }; + event.stopPropagation = function() { event.cancelBubble = true }; + event.target = event.srcElement || target; + + listener.call(target, event); + }]); + + this.attachEvent("on" + type, registry[0][3]); + }; + + WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function(type, listener) { + for (var index = 0, register; register = registry[index]; ++index) { + if (register[0] == this && register[1] == type && register[2] == listener) { + return this.detachEvent("on" + type, registry.splice(index, 1)[0][3]); + } + } + }; + + WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function(eventObject) { + return this.fireEvent("on" + eventObject.type, eventObject); + }; +})(Window.prototype, HTMLDocument.prototype, Element.prototype, "addEventListener", "removeEventListener", "dispatchEvent", []);
\ No newline at end of file diff --git a/docs/lightslider.min.css b/docs/lightslider.min.css deleted file mode 100644 index e5fec29c..00000000 --- a/docs/lightslider.min.css +++ /dev/null @@ -1,3 +0,0 @@ -/*! lightslider - v1.1.3 - 2015-04-14 -* https://github.com/sachinchoolur/lightslider -* Copyright (c) 2015 Sachin N; Licensed MIT */.lSSlideWrapper,.lSSlideWrapper .lSFade{position:relative}.lSSlideWrapper .lSSlide,.lSSlideWrapper.usingCss .lSFade>*{-webkit-transition-timing-function:inherit!important;transition-timing-function:inherit!important;-webkit-transition-duration:inherit!important;transition-duration:inherit!important}.lSSlideOuter,.lSSlideOuter .lSPager.lSGallery{-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-touch-callout:none;-webkit-user-select:none}.lSSlideOuter .lSPager.lSGallery:after,.lSSlideWrapper>.lightSlider:after{clear:both}.lSSlideOuter{overflow:hidden;user-select:none}.lightSlider:after,.lightSlider:before{content:" ";display:table}.lightSlider{overflow:hidden;margin:0}.lSSlideWrapper{max-width:100%;overflow:hidden}.lSSlideWrapper .lSSlide{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);-webkit-transition:all 1s;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform,height;transition-property:transform,height}.lSSlideWrapper .lSFade>*{position:absolute!important;top:0;left:0;z-index:9;margin-right:0;width:100%}.lSSlideWrapper.usingCss .lSFade>*{opacity:0;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-property:opacity;transition-property:opacity}.lSSlideWrapper .lSFade>.active{z-index:10}.lSSlideWrapper.usingCss .lSFade>.active{opacity:1}.lSSlideOuter .lSPager.lSpg{margin:10px 0 0;padding:0;text-align:center}.lSSlideOuter .lSPager.lSpg>li{cursor:pointer;display:inline-block;padding:0 5px}.lSSlideOuter .lSPager.lSpg>li a{background-color:#222;border-radius:30px;display:inline-block;height:8px;overflow:hidden;text-indent:-999em;width:8px;position:relative;z-index:99;-webkit-transition:all .5s linear 0s;transition:all .5s linear 0s}.lSSlideOuter .lSPager.lSpg>li.active a,.lSSlideOuter .lSPager.lSpg>li:hover a{background-color:#428bca}.lSSlideOuter .media{opacity:.8}.lSSlideOuter .media.active{opacity:1}.lSSlideOuter .lSPager.lSGallery{list-style:none;padding-left:0;margin:0;overflow:hidden;transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;user-select:none}.lSSlideOuter .lSPager.lSGallery li{overflow:hidden;-webkit-transition:border-radius .12s linear 0s .35s linear 0s;transition:border-radius .12s linear 0s .35s linear 0s}.lSSlideOuter .lSPager.lSGallery li.active,.lSSlideOuter .lSPager.lSGallery li:hover{border-radius:5px}.lSSlideOuter .lSPager.lSGallery img{display:block;height:auto;max-width:100%}.lSSlideOuter .lSPager.lSGallery:after,.lSSlideOuter .lSPager.lSGallery:before{content:" ";display:table}.lSAction>a{width:32px;display:block;top:50%;height:32px;background-image:url(../img/controls.png);cursor:pointer;position:absolute;z-index:99;margin-top:-16px;opacity:.5;-webkit-transition:opacity .35s linear 0s;transition:opacity .35s linear 0s}.lSAction>a:hover{opacity:1}.lSAction>.lSPrev{background-position:0 0;left:10px}.lSAction>.lSNext{background-position:-32px 0;right:10px}.lSAction>a.disabled{pointer-events:none}.cS-hidden{height:1px;opacity:0;filter:alpha(opacity=0);overflow:hidden}.lSSlideOuter.vertical{position:relative}.lSSlideOuter.vertical.noPager{padding-right:0!important}.lSSlideOuter.vertical .lSGallery{position:absolute!important;right:0;top:0}.lSSlideOuter.vertical .lightSlider>*{width:100%!important;max-width:none!important}.lSSlideOuter.vertical .lSAction>a{left:50%;margin-left:-14px;margin-top:0}.lSSlideOuter.vertical .lSAction>.lSNext{background-position:31px -31px;bottom:10px;top:auto}.lSSlideOuter.vertical .lSAction>.lSPrev{background-position:0 -31px;bottom:auto;top:10px}.lSSlideOuter.lSrtl{direction:rtl}.lSSlideOuter .lSPager,.lSSlideOuter .lightSlider{padding-left:0;list-style:none}.lSSlideOuter.lSrtl .lSPager,.lSSlideOuter.lSrtl .lightSlider{padding-right:0}.lSSlideOuter .lSGallery li,.lSSlideOuter .lightSlider>*{float:left}.lSSlideOuter.lSrtl .lSGallery li,.lSSlideOuter.lSrtl .lightSlider>*{float:right!important}@-webkit-keyframes rightEnd{0%,100%{left:0}50%{left:-15px}}@keyframes rightEnd{0%,100%{left:0}50%{left:-15px}}@-webkit-keyframes topEnd{0%,100%{top:0}50%{top:-15px}}@keyframes topEnd{0%,100%{top:0}50%{top:-15px}}@-webkit-keyframes leftEnd{0%,100%{left:0}50%{left:15px}}@keyframes leftEnd{0%,100%{left:0}50%{left:15px}}@-webkit-keyframes bottomEnd{0%,100%{bottom:0}50%{bottom:-15px}}@keyframes bottomEnd{0%,100%{bottom:0}50%{bottom:-15px}}.lSSlideOuter .rightEnd{-webkit-animation:rightEnd .3s;animation:rightEnd .3s;position:relative}.lSSlideOuter .leftEnd{-webkit-animation:leftEnd .3s;animation:leftEnd .3s;position:relative}.lSSlideOuter.vertical .rightEnd{-webkit-animation:topEnd .3s;animation:topEnd .3s;position:relative}.lSSlideOuter.vertical .leftEnd{-webkit-animation:bottomEnd .3s;animation:bottomEnd .3s;position:relative}.lSSlideOuter.lSrtl .rightEnd{-webkit-animation:leftEnd .3s;animation:leftEnd .3s;position:relative}.lSSlideOuter.lSrtl .leftEnd{-webkit-animation:rightEnd .3s;animation:rightEnd .3s;position:relative}.lightSlider.lsGrab>*{cursor:-webkit-grab;cursor:-moz-grab;cursor:-o-grab;cursor:-ms-grab;cursor:grab}.lightSlider.lsGrabbing>*{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:-o-grabbing;cursor:-ms-grabbing;cursor:grabbing}
\ No newline at end of file diff --git a/docs/lightslider.min.js b/docs/lightslider.min.js deleted file mode 100644 index ea16d58d..00000000 --- a/docs/lightslider.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! lightslider - v1.1.6 - 2016-10-25 -* https://github.com/sachinchoolur/lightslider -* Copyright (c) 2016 Sachin N; Licensed MIT */ -!function(a,b){"use strict";var c={item:3,autoWidth:!1,slideMove:1,slideMargin:10,addClass:"",mode:"slide",useCSS:!0,cssEasing:"ease",easing:"linear",speed:400,auto:!1,pauseOnHover:!1,loop:!1,slideEndAnimation:!0,pause:2e3,keyPress:!1,controls:!0,prevHtml:"",nextHtml:"",rtl:!1,adaptiveHeight:!1,vertical:!1,verticalHeight:500,vThumbWidth:100,thumbItem:10,pager:!0,gallery:!1,galleryMargin:5,thumbMargin:5,currentPagerPosition:"middle",enableTouch:!0,enableDrag:!0,freeMove:!0,swipeThreshold:40,responsive:[],onBeforeStart:function(a){},onSliderLoad:function(a){},onBeforeSlide:function(a,b){},onAfterSlide:function(a,b){},onBeforeNextSlide:function(a,b){},onBeforePrevSlide:function(a,b){}};a.fn.lightSlider=function(b){if(0===this.length)return this;if(this.length>1)return this.each(function(){a(this).lightSlider(b)}),this;var d={},e=a.extend(!0,{},c,b),f={},g=this;d.$el=this,"fade"===e.mode&&(e.vertical=!1);var h=g.children(),i=a(window).width(),j=null,k=null,l=0,m=0,n=!1,o=0,p="",q=0,r=e.vertical===!0?"height":"width",s=e.vertical===!0?"margin-bottom":"margin-right",t=0,u=0,v=0,w=0,x=null,y="ontouchstart"in document.documentElement,z={};return z.chbreakpoint=function(){if(i=a(window).width(),e.responsive.length){var b;if(e.autoWidth===!1&&(b=e.item),i<e.responsive[0].breakpoint)for(var c=0;c<e.responsive.length;c++)i<e.responsive[c].breakpoint&&(j=e.responsive[c].breakpoint,k=e.responsive[c]);if("undefined"!=typeof k&&null!==k)for(var d in k.settings)k.settings.hasOwnProperty(d)&&(("undefined"==typeof f[d]||null===f[d])&&(f[d]=e[d]),e[d]=k.settings[d]);if(!a.isEmptyObject(f)&&i>e.responsive[0].breakpoint)for(var g in f)f.hasOwnProperty(g)&&(e[g]=f[g]);e.autoWidth===!1&&t>0&&v>0&&b!==e.item&&(q=Math.round(t/((v+e.slideMargin)*e.slideMove)))}},z.calSW=function(){e.autoWidth===!1&&(v=(o-(e.item*e.slideMargin-e.slideMargin))/e.item)},z.calWidth=function(a){var b=a===!0?p.find(".lslide").length:h.length;if(e.autoWidth===!1)m=b*(v+e.slideMargin);else{m=0;for(var c=0;b>c;c++)m+=parseInt(h.eq(c).width())+e.slideMargin}return m},d={doCss:function(){var a=function(){for(var a=["transition","MozTransition","WebkitTransition","OTransition","msTransition","KhtmlTransition"],b=document.documentElement,c=0;c<a.length;c++)if(a[c]in b.style)return!0};return e.useCSS&&a()?!0:!1},keyPress:function(){e.keyPress&&a(document).on("keyup.lightslider",function(b){a(":focus").is("input, textarea")||(b.preventDefault?b.preventDefault():b.returnValue=!1,37===b.keyCode?g.goToPrevSlide():39===b.keyCode&&g.goToNextSlide())})},controls:function(){e.controls&&(g.after('<div class="lSAction"><a class="lSPrev">'+e.prevHtml+'</a><a class="lSNext">'+e.nextHtml+"</a></div>"),e.autoWidth?z.calWidth(!1)<o&&p.find(".lSAction").hide():l<=e.item&&p.find(".lSAction").hide(),p.find(".lSAction a").on("click",function(b){return b.preventDefault?b.preventDefault():b.returnValue=!1,"lSPrev"===a(this).attr("class")?g.goToPrevSlide():g.goToNextSlide(),!1}))},initialStyle:function(){var a=this;"fade"===e.mode&&(e.autoWidth=!1,e.slideEndAnimation=!1),e.auto&&(e.slideEndAnimation=!1),e.autoWidth&&(e.slideMove=1,e.item=1),e.loop&&(e.slideMove=1,e.freeMove=!1),e.onBeforeStart.call(this,g),z.chbreakpoint(),g.addClass("lightSlider").wrap('<div class="lSSlideOuter '+e.addClass+'"><div class="lSSlideWrapper"></div></div>'),p=g.parent(".lSSlideWrapper"),e.rtl===!0&&p.parent().addClass("lSrtl"),e.vertical?(p.parent().addClass("vertical"),o=e.verticalHeight,p.css("height",o+"px")):o=g.outerWidth(),h.addClass("lslide"),e.loop===!0&&"slide"===e.mode&&(z.calSW(),z.clone=function(){if(z.calWidth(!0)>o){for(var b=0,c=0,d=0;d<h.length&&(b+=parseInt(g.find(".lslide").eq(d).width())+e.slideMargin,c++,!(b>=o+e.slideMargin));d++);var f=e.autoWidth===!0?c:e.item;if(f<g.find(".clone.left").length)for(var i=0;i<g.find(".clone.left").length-f;i++)h.eq(i).remove();if(f<g.find(".clone.right").length)for(var j=h.length-1;j>h.length-1-g.find(".clone.right").length;j--)q--,h.eq(j).remove();for(var k=g.find(".clone.right").length;f>k;k++)g.find(".lslide").eq(k).clone().removeClass("lslide").addClass("clone right").appendTo(g),q++;for(var l=g.find(".lslide").length-g.find(".clone.left").length;l>g.find(".lslide").length-f;l--)g.find(".lslide").eq(l-1).clone().removeClass("lslide").addClass("clone left").prependTo(g);h=g.children()}else h.hasClass("clone")&&(g.find(".clone").remove(),a.move(g,0))},z.clone()),z.sSW=function(){l=h.length,e.rtl===!0&&e.vertical===!1&&(s="margin-left"),e.autoWidth===!1&&h.css(r,v+"px"),h.css(s,e.slideMargin+"px"),m=z.calWidth(!1),g.css(r,m+"px"),e.loop===!0&&"slide"===e.mode&&n===!1&&(q=g.find(".clone.left").length)},z.calL=function(){h=g.children(),l=h.length},this.doCss()&&p.addClass("usingCss"),z.calL(),"slide"===e.mode?(z.calSW(),z.sSW(),e.loop===!0&&(t=a.slideValue(),this.move(g,t)),e.vertical===!1&&this.setHeight(g,!1)):(this.setHeight(g,!0),g.addClass("lSFade"),this.doCss()||(h.fadeOut(0),h.eq(q).fadeIn(0))),e.loop===!0&&"slide"===e.mode?h.eq(q).addClass("active"):h.first().addClass("active")},pager:function(){var a=this;if(z.createPager=function(){w=(o-(e.thumbItem*e.thumbMargin-e.thumbMargin))/e.thumbItem;var b=p.find(".lslide"),c=p.find(".lslide").length,d=0,f="",h=0;for(d=0;c>d;d++){"slide"===e.mode&&(e.autoWidth?h+=(parseInt(b.eq(d).width())+e.slideMargin)*e.slideMove:h=d*(v+e.slideMargin)*e.slideMove);var i=b.eq(d*e.slideMove).attr("data-thumb");if(f+=e.gallery===!0?'<li style="width:100%;'+r+":"+w+"px;"+s+":"+e.thumbMargin+'px"><a href="#"><img src="'+i+'" /></a></li>':'<li><a href="#">'+(d+1)+"</a></li>","slide"===e.mode&&h>=m-o-e.slideMargin){d+=1;var j=2;e.autoWidth&&(f+='<li><a href="#">'+(d+1)+"</a></li>",j=1),j>d?(f=null,p.parent().addClass("noPager")):p.parent().removeClass("noPager");break}}var k=p.parent();k.find(".lSPager").html(f),e.gallery===!0&&(e.vertical===!0&&k.find(".lSPager").css("width",e.vThumbWidth+"px"),u=d*(e.thumbMargin+w)+.5,k.find(".lSPager").css({property:u+"px","transition-duration":e.speed+"ms"}),e.vertical===!0&&p.parent().css("padding-right",e.vThumbWidth+e.galleryMargin+"px"),k.find(".lSPager").css(r,u+"px"));var l=k.find(".lSPager").find("li");l.first().addClass("active"),l.on("click",function(){return e.loop===!0&&"slide"===e.mode?q+=l.index(this)-k.find(".lSPager").find("li.active").index():q=l.index(this),g.mode(!1),e.gallery===!0&&a.slideThumb(),!1})},e.pager){var b="lSpg";e.gallery&&(b="lSGallery"),p.after('<ul class="lSPager '+b+'"></ul>');var c=e.vertical?"margin-left":"margin-top";p.parent().find(".lSPager").css(c,e.galleryMargin+"px"),z.createPager()}setTimeout(function(){z.init()},0)},setHeight:function(a,b){var c=null,d=this;c=e.loop?a.children(".lslide ").first():a.children().first();var f=function(){var d=c.outerHeight(),e=0,f=d;b&&(d=0,e=100*f/o),a.css({height:d+"px","padding-bottom":e+"%"})};f(),c.find("img").length?c.find("img")[0].complete?(f(),x||d.auto()):c.find("img").on("load",function(){setTimeout(function(){f(),x||d.auto()},100)}):x||d.auto()},active:function(a,b){this.doCss()&&"fade"===e.mode&&p.addClass("on");var c=0;if(q*e.slideMove<l){a.removeClass("active"),this.doCss()||"fade"!==e.mode||b!==!1||a.fadeOut(e.speed),c=b===!0?q:q*e.slideMove;var d,f;b===!0&&(d=a.length,f=d-1,c+1>=d&&(c=f)),e.loop===!0&&"slide"===e.mode&&(c=b===!0?q-g.find(".clone.left").length:q*e.slideMove,b===!0&&(d=a.length,f=d-1,c+1===d?c=f:c+1>d&&(c=0))),this.doCss()||"fade"!==e.mode||b!==!1||a.eq(c).fadeIn(e.speed),a.eq(c).addClass("active")}else a.removeClass("active"),a.eq(a.length-1).addClass("active"),this.doCss()||"fade"!==e.mode||b!==!1||(a.fadeOut(e.speed),a.eq(c).fadeIn(e.speed))},move:function(a,b){e.rtl===!0&&(b=-b),this.doCss()?a.css(e.vertical===!0?{transform:"translate3d(0px, "+-b+"px, 0px)","-webkit-transform":"translate3d(0px, "+-b+"px, 0px)"}:{transform:"translate3d("+-b+"px, 0px, 0px)","-webkit-transform":"translate3d("+-b+"px, 0px, 0px)"}):e.vertical===!0?a.css("position","relative").animate({top:-b+"px"},e.speed,e.easing):a.css("position","relative").animate({left:-b+"px"},e.speed,e.easing);var c=p.parent().find(".lSPager").find("li");this.active(c,!0)},fade:function(){this.active(h,!1);var a=p.parent().find(".lSPager").find("li");this.active(a,!0)},slide:function(){var a=this;z.calSlide=function(){m>o&&(t=a.slideValue(),a.active(h,!1),t>m-o-e.slideMargin?t=m-o-e.slideMargin:0>t&&(t=0),a.move(g,t),e.loop===!0&&"slide"===e.mode&&(q>=l-g.find(".clone.left").length/e.slideMove&&a.resetSlide(g.find(".clone.left").length),0===q&&a.resetSlide(p.find(".lslide").length)))},z.calSlide()},resetSlide:function(a){var b=this;p.find(".lSAction a").addClass("disabled"),setTimeout(function(){q=a,p.css("transition-duration","0ms"),t=b.slideValue(),b.active(h,!1),d.move(g,t),setTimeout(function(){p.css("transition-duration",e.speed+"ms"),p.find(".lSAction a").removeClass("disabled")},50)},e.speed+100)},slideValue:function(){var a=0;if(e.autoWidth===!1)a=q*(v+e.slideMargin)*e.slideMove;else{a=0;for(var b=0;q>b;b++)a+=parseInt(h.eq(b).width())+e.slideMargin}return a},slideThumb:function(){var a;switch(e.currentPagerPosition){case"left":a=0;break;case"middle":a=o/2-w/2;break;case"right":a=o-w}var b=q-g.find(".clone.left").length,c=p.parent().find(".lSPager");"slide"===e.mode&&e.loop===!0&&(b>=c.children().length?b=0:0>b&&(b=c.children().length));var d=b*(w+e.thumbMargin)-a;d+o>u&&(d=u-o-e.thumbMargin),0>d&&(d=0),this.move(c,d)},auto:function(){e.auto&&(clearInterval(x),x=setInterval(function(){g.goToNextSlide()},e.pause))},pauseOnHover:function(){var b=this;e.auto&&e.pauseOnHover&&(p.on("mouseenter",function(){a(this).addClass("ls-hover"),g.pause(),e.auto=!0}),p.on("mouseleave",function(){a(this).removeClass("ls-hover"),p.find(".lightSlider").hasClass("lsGrabbing")||b.auto()}))},touchMove:function(a,b){if(p.css("transition-duration","0ms"),"slide"===e.mode){var c=a-b,d=t-c;if(d>=m-o-e.slideMargin)if(e.freeMove===!1)d=m-o-e.slideMargin;else{var f=m-o-e.slideMargin;d=f+(d-f)/5}else 0>d&&(e.freeMove===!1?d=0:d/=5);this.move(g,d)}},touchEnd:function(a){if(p.css("transition-duration",e.speed+"ms"),"slide"===e.mode){var b=!1,c=!0;t-=a,t>m-o-e.slideMargin?(t=m-o-e.slideMargin,e.autoWidth===!1&&(b=!0)):0>t&&(t=0);var d=function(a){var c=0;if(b||a&&(c=1),e.autoWidth)for(var d=0,f=0;f<h.length&&(d+=parseInt(h.eq(f).width())+e.slideMargin,q=f+c,!(d>=t));f++);else{var g=t/((v+e.slideMargin)*e.slideMove);q=parseInt(g)+c,t>=m-o-e.slideMargin&&g%1!==0&&q++}};a>=e.swipeThreshold?(d(!1),c=!1):a<=-e.swipeThreshold&&(d(!0),c=!1),g.mode(c),this.slideThumb()}else a>=e.swipeThreshold?g.goToPrevSlide():a<=-e.swipeThreshold&&g.goToNextSlide()},enableDrag:function(){var b=this;if(!y){var c=0,d=0,f=!1;p.find(".lightSlider").addClass("lsGrab"),p.on("mousedown",function(b){return o>m&&0!==m?!1:void("lSPrev"!==a(b.target).attr("class")&&"lSNext"!==a(b.target).attr("class")&&(c=e.vertical===!0?b.pageY:b.pageX,f=!0,b.preventDefault?b.preventDefault():b.returnValue=!1,p.scrollLeft+=1,p.scrollLeft-=1,p.find(".lightSlider").removeClass("lsGrab").addClass("lsGrabbing"),clearInterval(x)))}),a(window).on("mousemove",function(a){f&&(d=e.vertical===!0?a.pageY:a.pageX,b.touchMove(d,c))}),a(window).on("mouseup",function(g){if(f){p.find(".lightSlider").removeClass("lsGrabbing").addClass("lsGrab"),f=!1,d=e.vertical===!0?g.pageY:g.pageX;var h=d-c;Math.abs(h)>=e.swipeThreshold&&a(window).on("click.ls",function(b){b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopImmediatePropagation(),b.stopPropagation(),a(window).off("click.ls")}),b.touchEnd(h)}})}},enableTouch:function(){var a=this;if(y){var b={},c={};p.on("touchstart",function(a){c=a.originalEvent.targetTouches[0],b.pageX=a.originalEvent.targetTouches[0].pageX,b.pageY=a.originalEvent.targetTouches[0].pageY,clearInterval(x)}),p.on("touchmove",function(d){if(o>m&&0!==m)return!1;var f=d.originalEvent;c=f.targetTouches[0];var g=Math.abs(c.pageX-b.pageX),h=Math.abs(c.pageY-b.pageY);e.vertical===!0?(3*h>g&&d.preventDefault(),a.touchMove(c.pageY,b.pageY)):(3*g>h&&d.preventDefault(),a.touchMove(c.pageX,b.pageX))}),p.on("touchend",function(){if(o>m&&0!==m)return!1;var d;d=e.vertical===!0?c.pageY-b.pageY:c.pageX-b.pageX,a.touchEnd(d)})}},build:function(){var b=this;b.initialStyle(),this.doCss()&&(e.enableTouch===!0&&b.enableTouch(),e.enableDrag===!0&&b.enableDrag()),a(window).on("focus",function(){b.auto()}),a(window).on("blur",function(){clearInterval(x)}),b.pager(),b.pauseOnHover(),b.controls(),b.keyPress()}},d.build(),z.init=function(){z.chbreakpoint(),e.vertical===!0?(o=e.item>1?e.verticalHeight:h.outerHeight(),p.css("height",o+"px")):o=p.outerWidth(),e.loop===!0&&"slide"===e.mode&&z.clone(),z.calL(),"slide"===e.mode&&g.removeClass("lSSlide"),"slide"===e.mode&&(z.calSW(),z.sSW()),setTimeout(function(){"slide"===e.mode&&g.addClass("lSSlide")},1e3),e.pager&&z.createPager(),e.adaptiveHeight===!0&&e.vertical===!1&&g.css("height",h.eq(q).outerHeight(!0)),e.adaptiveHeight===!1&&("slide"===e.mode?e.vertical===!1?d.setHeight(g,!1):d.auto():d.setHeight(g,!0)),e.gallery===!0&&d.slideThumb(),"slide"===e.mode&&d.slide(),e.autoWidth===!1?h.length<=e.item?p.find(".lSAction").hide():p.find(".lSAction").show():z.calWidth(!1)<o&&0!==m?p.find(".lSAction").hide():p.find(".lSAction").show()},g.goToPrevSlide=function(){if(q>0)e.onBeforePrevSlide.call(this,g,q),q--,g.mode(!1),e.gallery===!0&&d.slideThumb();else if(e.loop===!0){if(e.onBeforePrevSlide.call(this,g,q),"fade"===e.mode){var a=l-1;q=parseInt(a/e.slideMove)}g.mode(!1),e.gallery===!0&&d.slideThumb()}else e.slideEndAnimation===!0&&(g.addClass("leftEnd"),setTimeout(function(){g.removeClass("leftEnd")},400))},g.goToNextSlide=function(){var a=!0;if("slide"===e.mode){var b=d.slideValue();a=b<m-o-e.slideMargin}q*e.slideMove<l-e.slideMove&&a?(e.onBeforeNextSlide.call(this,g,q),q++,g.mode(!1),e.gallery===!0&&d.slideThumb()):e.loop===!0?(e.onBeforeNextSlide.call(this,g,q),q=0,g.mode(!1),e.gallery===!0&&d.slideThumb()):e.slideEndAnimation===!0&&(g.addClass("rightEnd"),setTimeout(function(){g.removeClass("rightEnd")},400))},g.mode=function(a){e.adaptiveHeight===!0&&e.vertical===!1&&g.css("height",h.eq(q).outerHeight(!0)),n===!1&&("slide"===e.mode?d.doCss()&&(g.addClass("lSSlide"),""!==e.speed&&p.css("transition-duration",e.speed+"ms"),""!==e.cssEasing&&p.css("transition-timing-function",e.cssEasing)):d.doCss()&&(""!==e.speed&&g.css("transition-duration",e.speed+"ms"),""!==e.cssEasing&&g.css("transition-timing-function",e.cssEasing))),a||e.onBeforeSlide.call(this,g,q),"slide"===e.mode?d.slide():d.fade(),p.hasClass("ls-hover")||d.auto(),setTimeout(function(){a||e.onAfterSlide.call(this,g,q)},e.speed),n=!0},g.play=function(){g.goToNextSlide(),e.auto=!0,d.auto()},g.pause=function(){e.auto=!1,clearInterval(x)},g.refresh=function(){z.init()},g.getCurrentSlideCount=function(){var a=q;if(e.loop){var b=p.find(".lslide").length,c=g.find(".clone.left").length;a=c-1>=q?b+(q-c):q>=b+c?q-b-c:q-c}return a+1},g.getTotalSlideCount=function(){return p.find(".lslide").length},g.goToSlide=function(a){q=e.loop?a+g.find(".clone.left").length-1:a,g.mode(!1),e.gallery===!0&&d.slideThumb()},g.destroy=function(){g.lightSlider&&(g.goToPrevSlide=function(){},g.goToNextSlide=function(){},g.mode=function(){},g.play=function(){},g.pause=function(){},g.refresh=function(){},g.getCurrentSlideCount=function(){},g.getTotalSlideCount=function(){},g.goToSlide=function(){},g.lightSlider=null,z={init:function(){}},g.parent().parent().find(".lSAction, .lSPager").remove(),g.removeClass("lightSlider lSFade lSSlide lsGrab lsGrabbing leftEnd right").removeAttr("style").unwrap().unwrap(),g.children().removeAttr("style"),h.removeClass("lslide active"),g.find(".clone").remove(),h=null,x=null,n=!1,q=0)},setTimeout(function(){e.onSliderLoad.call(this,g)},10),a(window).on("resize orientationchange",function(a){setTimeout(function(){a.preventDefault?a.preventDefault():a.returnValue=!1,z.init()},200)}),this}}(jQuery);
\ No newline at end of file @@ -6,8 +6,8 @@ site_description: 'Documentation for the Binary Ninja reverse engineering platfo site_author: 'Vector 35 Inc' google_analytics: ['UA-72420552-3', 'docs.binary.ninja' ] use_directory_urls: False -extra_css: [ 'docs.css?1585271138', 'lightslider.min.css?1585271138', 'github.min.css' ] -extra_javascript: ['lightslider.min.js?1585271138', 'highlight.min.js', 'cpp.min.js', 'python.min.js'] +extra_css: ['docs.css', 'github.min.css', 'juxtapose.css'] +extra_javascript: ['highlight.min.js', 'cpp.min.js', 'python.min.js', 'juxtapose.js'] theme: name: readthedocs favicon: 'img/favicon.ico' |
