![JAR search and dependency download from the Maven repository](/logo.png)
jquery-fracs-0.15.0.jquery.fracs-0.15.0.js Maven / Gradle / Ivy
/* jQuery.fracs 0.15.0 - http://larsjung.de/jquery-fracs/ */
(function () {
'use strict';
// Some often used references.
var $ = jQuery;
var $window = $(window);
var $document = $(document);
var extend = $.extend;
var isFn = $.isFunction;
var mathMax = Math.max;
var mathMin = Math.min;
var mathRound = Math.round;
var getId = (function () {
var ids = {};
var nextId = 1;
return function (element) {
if (!element) {
return 0;
}
if (!ids[element]) {
ids[element] = nextId;
nextId += 1;
}
return ids[element];
};
}());
function isTypeOf(obj, type) {
return typeof obj === type;
}
function isInstanceOf(obj, type) {
return obj instanceof type;
}
function isHTMLElement(obj) {
return obj && obj.nodeType;
}
function getHTMLElement(obj) {
return isHTMLElement(obj) ? obj : (isInstanceOf(obj, $) ? obj[0] : undefined);
}
function reduce(elements, fn, current) {
$.each(elements, function (idx, element) {
current = fn.call(element, current, idx, element);
});
return current;
}
function equal(obj1, obj2, props) {
var i, l, prop;
if (obj1 === obj2) {
return true;
}
if (!obj1 || !obj2 || obj1.constructor !== obj2.constructor) {
return false;
}
for (i = 0, l = props.length; i < l; i += 1) {
prop = props[i];
if (obj1[prop] && isFn(obj1[prop].equals) && !obj1[prop].equals(obj2[prop])) {
return false;
}
if (obj1[prop] !== obj2[prop]) {
return false;
}
}
return true;
}
// Objects
// =======
// Rect
// ----
// Holds the position and dimensions of a rectangle. The position might be
// relative to document, viewport or element space.
function Rect(left, top, width, height) {
// Top left corner of the rectangle rounded to integers.
this.left = mathRound(left);
this.top = mathRound(top);
// Dimensions rounded to integers.
this.width = mathRound(width);
this.height = mathRound(height);
// Bottom right corner of the rectangle.
this.right = this.left + this.width;
this.bottom = this.top + this.height;
}
// ### Prototype
extend(Rect.prototype, {
// Checks if this instance equals `that` in position and dimensions.
equals: function (that) {
return equal(this, that, ['left', 'top', 'width', 'height']);
},
// Returns the area of this rectangle.
area: function () {
return this.width * this.height;
},
// Returns a new `Rect` representig this rect relative to `rect`.
relativeTo: function (rect) {
return new Rect(this.left - rect.left, this.top - rect.top, this.width, this.height);
},
// Returns a new rectangle representing the intersection of this
// instance and `rect`. If there is no intersection the return value
// is `null`.
intersection: function (rect) {
if (!isInstanceOf(rect, Rect)) {
return null;
}
var left = mathMax(this.left, rect.left);
var right = mathMin(this.right, rect.right);
var top = mathMax(this.top, rect.top);
var bottom = mathMin(this.bottom, rect.bottom);
var width = right - left;
var height = bottom - top;
return (width >= 0 && height >= 0) ? new Rect(left, top, width, height) : null;
},
// Returns a new rectangle representing the smallest rectangle
// containing this instance and `rect`.
envelope: function (rect) {
if (!isInstanceOf(rect, Rect)) {
return this;
}
var left = mathMin(this.left, rect.left);
var right = mathMax(this.right, rect.right);
var top = mathMin(this.top, rect.top);
var bottom = mathMax(this.bottom, rect.bottom);
var width = right - left;
var height = bottom - top;
return new Rect(left, top, width, height);
}
});
// ### Static methods
extend(Rect, {
// Returns a new instance of `Rect` representing the content of the
// specified element. Since the coordinates are in content space the
// `left` and `top` values are always set to `0`. If `inDocSpace` is
// `true` the rect gets returned in document space.
ofContent: function (element, inContentSpace) {
if (!element || element === document || element === window) {
return new Rect(0, 0, $document.width(), $document.height());
}
if (inContentSpace) {
return new Rect(0, 0, element.scrollWidth, element.scrollHeight);
} else {
return new Rect(element.offsetLeft - element.scrollLeft, element.offsetTop - element.scrollTop, element.scrollWidth, element.scrollHeight);
}
},
// Returns a new instance of `Rect` representing the viewport of the
// specified element. If `inDocSpace` is `true` the rect gets returned
// in document space instead of content space.
ofViewport: function (element, inContentSpace) {
if (!element || element === document || element === window) {
return new Rect($window.scrollLeft(), $window.scrollTop(), $window.width(), $window.height());
}
if (inContentSpace) {
return new Rect(element.scrollLeft, element.scrollTop, element.clientWidth, element.clientHeight);
} else {
return new Rect(element.offsetLeft, element.offsetTop, element.clientWidth, element.clientHeight);
}
},
// Returns a new instance of `Rect` representing a given
// `HTMLElement`. The dimensions respect padding and border widths. If
// the element is invisible (as determined by jQuery) the return value
// is null.
ofElement: function (element) {
var $element = $(element);
if (!$element.is(':visible')) {
return null;
}
var offset = $element.offset();
return new Rect(offset.left, offset.top, $element.outerWidth(), $element.outerHeight());
}
});
// Fractions
// ---------
// The heart of the library. Creates and holds the
// fractions data for the two specified rects. `viewport` defaults to
// `Rect.ofViewport()`.
function Fractions(visible, viewport, possible, rects) {
this.visible = visible || 0;
this.viewport = viewport || 0;
this.possible = possible || 0;
this.rects = (rects && extend({}, rects)) || null;
}
// ### Prototype
extend(Fractions.prototype, {
// Checks if this instance equals `that` in all attributes.
equals: function (that) {
return this.fracsEqual(that) && this.rectsEqual(that);
},
// Checks if this instance equals `that` in all fraction attributes.
fracsEqual: function (that) {
return equal(this, that, ['visible', 'viewport', 'possible']);
},
// Checks if this instance equals `that` in all rectangle attributes.
rectsEqual: function (that) {
return equal(this.rects, that.rects, ['document', 'element', 'viewport']);
}
});
// ### Static methods
extend(Fractions, {
of: function (rect, viewport) {
var intersection, intersectionArea, possibleArea;
rect = (isHTMLElement(rect) && Rect.ofElement(rect)) || rect;
viewport = (isHTMLElement(viewport) && Rect.ofViewport(viewport)) || viewport || Rect.ofViewport();
if (!(rect instanceof Rect)) {
return new Fractions();
}
intersection = rect.intersection(viewport);
if (!intersection) {
return new Fractions();
}
intersectionArea = intersection.area();
possibleArea = mathMin(rect.width, viewport.width) * mathMin(rect.height, viewport.height);
return new Fractions(
intersectionArea / rect.area(),
intersectionArea / viewport.area(),
intersectionArea / possibleArea,
{
document: intersection,
element: intersection.relativeTo(rect),
viewport: intersection.relativeTo(viewport)
}
);
}
});
// Group
// -----
function Group(elements, viewport) {
this.els = elements;
this.viewport = viewport;
}
// ### Helpers
// Accepted values for `property` parameters below.
var rectProps = ['width', 'height', 'left', 'right', 'top', 'bottom'];
var fracsProps = ['possible', 'visible', 'viewport'];
// Returns the specified `property` for `HTMLElement element` or `0`
// if `property` is invalid.
function getValue(element, viewport, property) {
var obj;
if ($.inArray(property, rectProps) >= 0) {
obj = Rect.ofElement(element);
} else if ($.inArray(property, fracsProps) >= 0) {
obj = Fractions.of(element, viewport);
}
return obj ? obj[property] : 0;
}
// Sorting functions.
function sortAscending(entry1, entry2) {
return entry1.val - entry2.val;
}
function sortDescending(entry1, entry2) {
return entry2.val - entry1.val;
}
// ### Prototype
extend(Group.prototype, {
// Returns a sorted list of objects `{el: HTMLElement, val: Number}`
// for the specified `property`. `descending` defaults to `false`.
sorted: function (property, descending) {
var viewport = this.viewport;
return $.map(this.els, function (element) {
return {
el: element,
val: getValue(element, viewport, property)
};
})
.sort(descending ? sortDescending : sortAscending);
},
// Returns the first element of the sorted list returned by `sorted` above,
// or `null` if this list is empty.
best: function (property, descending) {
return this.els.length ? this.sorted(property, descending)[0] : null;
}
});
// ScrollState
// -----------
function ScrollState(element) {
var content = Rect.ofContent(element, true);
var viewport = Rect.ofViewport(element, true);
var w = content.width - viewport.width;
var h = content.height - viewport.height;
this.content = content;
this.viewport = viewport;
this.width = w <= 0 ? null : viewport.left / w;
this.height = h <= 0 ? null : viewport.top / h;
this.left = viewport.left;
this.top = viewport.top;
this.right = content.right - viewport.right;
this.bottom = content.bottom - viewport.bottom;
}
// ### Prototype
extend(ScrollState.prototype, {
// Checks if this instance equals `that`.
equals: function (that) {
return equal(this, that, ['width', 'height', 'left', 'top', 'right', 'bottom', 'content', 'viewport']);
}
});
// Viewport
// --------
function Viewport(element) {
this.el = element || window;
}
// ### Prototype
extend(Viewport.prototype, {
// Checks if this instance equals `that`.
equals: function (that) {
return equal(this, that, ['el']);
},
scrollState: function () {
return new ScrollState(this.el);
},
scrollTo: function (left, top, duration) {
var $el = this.el === window ? $('html,body') : $(this.el);
left = left || 0;
top = top || 0;
duration = isNaN(duration) ? 1000 : duration;
$el.stop(true).animate({scrollLeft: left, scrollTop: top}, duration);
},
scroll: function (left, top, duration) {
var $el = this.el === window ? $window : $(this.el);
left = left || 0;
top = top || 0;
this.scrollTo($el.scrollLeft() + left, $el.scrollTop() + top, duration);
},
scrollToRect: function (rect, paddingLeft, paddingTop, duration) {
paddingLeft = paddingLeft || 0;
paddingTop = paddingTop || 0;
this.scrollTo(rect.left - paddingLeft, rect.top - paddingTop, duration);
},
scrollToElement: function (element, paddingLeft, paddingTop, duration) {
var rect = Rect.ofElement(element).relativeTo(Rect.ofContent(this.el));
this.scrollToRect(rect, paddingLeft, paddingTop, duration);
}
});
// Callbacks
// =========
// callbacks mix-in
// ----------------
// Expects `context: HTMLElement` and `updatedValue: function`.
var callbacksMixIn = {
// Initial setup.
init: function () {
this.callbacks = $.Callbacks('memory unique');
this.currVal = null;
this.prevVal = null;
// A proxy to make `check` bindable to events.
this.checkProxy = $.proxy(this.check, this);
this.autoCheck();
},
// Adds a new callback function.
bind: function (callback) {
this.callbacks.add(callback);
},
// Removes a previously added callback function.
unbind: function (callback) {
if (callback) {
this.callbacks.remove(callback);
} else {
this.callbacks.empty();
}
},
// Triggers all callbacks with the current values.
trigger: function () {
this.callbacks.fireWith(this.context, [this.currVal, this.prevVal]);
},
// Checks if value changed, updates attributes `currVal` and
// `prevVal` accordingly and triggers the callbacks. Returns
// `true` if value changed, otherwise `false`.
check: function (event) {
var value = this.updatedValue(event);
if (value === undefined) {
return false;
}
this.prevVal = this.currVal;
this.currVal = value;
this.trigger();
return true;
},
// Auto-check configuration.
$autoTarget: $window,
autoEvents: 'load resize scroll',
// Enables/disables automated checking for changes on the specified `window`
// events.
autoCheck: function (on) {
this.$autoTarget[on === false ? 'off' : 'on'](this.autoEvents, this.checkProxy);
}
};
// FracsCallbacks
// --------------
function FracsCallbacks(element, viewport) {
this.context = element;
this.viewport = viewport;
this.init();
}
// ### Prototype
extend(FracsCallbacks.prototype, callbacksMixIn, {
updatedValue: function () {
var value = Fractions.of(this.context, this.viewport);
if (!this.currVal || !this.currVal.equals(value)) {
return value;
}
}
});
// GroupCallbacks
// --------------
function GroupCallbacks(elements, viewport, property, descending) {
this.context = new Group(elements, viewport);
this.property = property;
this.descending = descending;
this.init();
}
// ### Prototype
extend(GroupCallbacks.prototype, callbacksMixIn, {
updatedValue: function () {
var best = this.context.best(this.property, this.descending);
if (best) {
best = best.val > 0 ? best.el : null;
if (this.currVal !== best) {
return best;
}
}
}
});
// ScrollStateCallbacks
// --------------------
function ScrollStateCallbacks(element) {
if (!element || element === window || element === document) {
this.context = window;
} else {
this.context = element;
this.$autoTarget = $(element);
}
this.init();
}
// ### Prototype
extend(ScrollStateCallbacks.prototype, callbacksMixIn, {
updatedValue: function () {
var value = new ScrollState(this.context);
if (!this.currVal || !this.currVal.equals(value)) {
return value;
}
}
});
/* modplug 1.4.1 - http://larsjung.de/modplug/ */
// This function is ment to be copied into your plugin file as a local
// variable.
//
// `modplug` expects a string `namespace` and a configuration object
// `options`.
//
// options = {
// statics: hash of functions,
// methods: hash of functions,
// defaultStatic: String/function,
// defaultMethod: String/function
// }
//
// For more details see .
var modplug = function (namespace, options) {
'use strict';
// Some references to enhance minification.
var slice = [].slice,
$ = jQuery,
extend = $.extend,
isFn = $.isFunction,
// Save the initial settings.
settings = extend({}, options),
// Helper function to apply default methods.
applyMethod = function (obj, args, methodName, methods) {
// If `methodName` is a function apply it to get the actual
// method name.
methodName = isFn(methodName) ? methodName.apply(obj, args) : methodName;
// If method exists then apply it and return the result ...
if (isFn(methods[methodName])) {
return methods[methodName].apply(obj, args);
}
// ... otherwise raise an error.
$.error('Method "' + methodName + '" does not exist on jQuery.' + namespace);
},
// This function gets exposed as `$.`.
statics = function () {
// Try to apply a default method.
return applyMethod(this, slice.call(arguments), settings.defaultStatic, statics);
},
// This function gets exposed as `$(selector).`.
methods = function (method) {
// If `method` exists then apply it ...
if (isFn(methods[method])) {
return methods[method].apply(this, slice.call(arguments, 1));
}
// ... otherwise try to apply a default method.
return applyMethod(this, slice.call(arguments), settings.defaultMethod, methods);
},
// Adds/overwrites plugin methods. This function gets exposed as
// `$..modplug` to make the plugin extendable.
plug = function (options) {
if (options) {
extend(statics, options.statics);
extend(methods, options.methods);
}
// Make sure that `$..modplug` points to this function
// after adding new methods.
statics.modplug = plug;
};
// Save objects or methods previously registered to the desired namespace.
// They are available via `$..modplug.prev`.
plug.prev = {
statics: $[namespace],
methods: $.fn[namespace]
};
// Init the plugin by adding the specified statics and methods.
plug(options);
// Register the plugin.
$[namespace] = statics;
$.fn[namespace] = methods;
};
// Register the plug-in
// ====================
// The namespace used to register the plug-in and to attach data to
// elements.
var namespace = 'fracs';
// The methods are sorted in alphabetical order. All methods that do not
// provide a return value will return `this` to enable method chaining.
modplug(namespace, {
// Static methods
// --------------
// These methods are accessible via `$.fracs.`.
statics: {
// Build version.
version: '0.15.0',
// Publish object constructors (for testing).
Rect: Rect,
Fractions: Fractions,
Group: Group,
ScrollState: ScrollState,
Viewport: Viewport,
FracsCallbacks: FracsCallbacks,
GroupCallbacks: GroupCallbacks,
ScrollStateCallbacks: ScrollStateCallbacks,
// ### fracs
// This is the **default method**. So instead of calling
// `$.fracs.fracs(...)` simply call `$.fracs(...)`.
//
// Returns the fractions for a given `Rect` and `viewport`,
// viewport defaults to `$.fracs.viewport()`.
//
// $.fracs(rect: Rect, [viewport: Rect]): Fractions
fracs: function (rect, viewport) {
return Fractions.of(rect, viewport);
}
},
// Instance methods
// ----------------
// These methods are accessible via `$(selector).fracs('', ...)`.
methods: {
// ### 'content'
// Returns the content rect of the first selected element in content space.
// If no element is selected it returns the document rect.
//
// .fracs('content'): Rect
content: function (inContentSpace) {
return this.length ? Rect.ofContent(this[0], inContentSpace) : null;
},
// ### 'envelope'
// Returns the smallest rectangle that containes all selected elements.
//
// .fracs('envelope'): Rect
envelope: function () {
return reduce(this, function (current) {
var rect = Rect.ofElement(this);
return current ? current.envelope(rect) : rect;
});
},
// ### 'fracs'
// This is the **default method**. So the first parameter `'fracs'`
// can be omitted.
//
// Returns the fractions for the first selected element.
//
// .fracs(): Fractions
//
// Binds a callback function that will be invoked if fractions have changed
// after a `window resize` or `window scroll` event.
//
// .fracs(callback(fracs: Fractions, prevFracs: Fractions)): jQuery
//
// Unbinds the specified callback function.
//
// .fracs('unbind', callback): jQuery
//
// Unbinds all callback functions.
//
// .fracs('unbind'): jQuery
//
// Checks if fractions changed and if so invokes all bound callback functions.
//
// .fracs('check'): jQuery
fracs: function (action, callback, viewport) {
if (!isTypeOf(action, 'string')) {
viewport = callback;
callback = action;
action = null;
}
if (!isFn(callback)) {
viewport = callback;
callback = null;
}
viewport = getHTMLElement(viewport);
var ns = namespace + '.fracs.' + getId(viewport);
if (action === 'unbind') {
return this.each(function () {
var cbs = $(this).data(ns);
if (cbs) {
cbs.unbind(callback);
}
});
} else if (action === 'check') {
return this.each(function () {
var cbs = $(this).data(ns);
if (cbs) {
cbs.check();
}
});
} else if (isFn(callback)) {
return this.each(function () {
var $this = $(this),
cbs = $this.data(ns);
if (!cbs) {
cbs = new FracsCallbacks(this, viewport);
$this.data(ns, cbs);
}
cbs.bind(callback);
});
}
return this.length ? Fractions.of(this[0], viewport) : null;
},
// ### 'intersection'
// Returns the greatest rectangle that is contained in all selected elements.
//
// .fracs('intersection'): Rect
intersection: function () {
return reduce(this, function (current) {
var rect = Rect.ofElement(this);
return current ? current.intersection(rect) : rect;
});
},
// ### 'max'
// Reduces the set of selected elements to those with the maximum value
// of the specified property.
// Valid values for property are `possible`, `visible`, `viewport`,
// `width`, `height`, `left`, `right`, `top`, `bottom`.
//
// .fracs('max', property: String): jQuery
//
// Binds a callback function to the set of selected elements that gets
// triggert whenever the element with the highest value of the specified
// property changes.
//
// .fracs('max', property: String, callback(best: Element, prevBest: Element)): jQuery
max: function (property, callback, viewport) {
if (!isFn(callback)) {
viewport = callback;
callback = null;
}
viewport = getHTMLElement(viewport);
if (callback) {
new GroupCallbacks(this, viewport, property, true).bind(callback);
return this;
}
return this.pushStack(new Group(this, viewport).best(property, true).el);
},
// ### 'min'
// Reduces the set of selected elements to those with the minimum value
// of the specified property.
// Valid values for property are `possible`, `visible`, `viewport`,
// `width`, `height`, `left`, `right`, `top`, `bottom`.
//
// .fracs('min', property: String): jQuery
//
// Binds a callback function to the set of selected elements that gets
// triggert whenever the element with the lowest value of the specified
// property changes.
//
// .fracs('min', property: String, callback(best: Element, prevBest: Element)): jQuery
min: function (property, callback, viewport) {
if (!isFn(callback)) {
viewport = callback;
callback = null;
}
viewport = getHTMLElement(viewport);
if (callback) {
new GroupCallbacks(this, viewport, property).bind(callback);
return this;
}
return this.pushStack(new Group(this, viewport).best(property).el);
},
// ### 'rect'
// Returns the dimensions for the first selected element in document space.
//
// .fracs('rect'): Rect
rect: function () {
return this.length ? Rect.ofElement(this[0]) : null;
},
// ### 'scrollState'
// Returns the current scroll state for the first selected element.
//
// .fracs('scrollState'): ScrollState
//
// Binds a callback function that will be invoked if scroll state has changed
// after a `resize` or `scroll` event.
//
// .fracs('scrollState', callback(scrollState: scrollState, prevScrollState: scrollState)): jQuery
//
// Unbinds the specified callback function.
//
// .fracs('scrollState', 'unbind', callback): jQuery
//
// Unbinds all callback functions.
//
// .fracs('scrollState', 'unbind'): jQuery
//
// Checks if scroll state changed and if so invokes all bound callback functions.
//
// .fracs('scrollState', 'check'): jQuery
scrollState: function (action, callback) {
var ns = namespace + '.scrollState';
if (!isTypeOf(action, 'string')) {
callback = action;
action = null;
}
if (action === 'unbind') {
return this.each(function () {
var cbs = $(this).data(ns);
if (cbs) {
cbs.unbind(callback);
}
});
} else if (action === 'check') {
return this.each(function () {
var cbs = $(this).data(ns);
if (cbs) {
cbs.check();
}
});
} else if (isFn(callback)) {
return this.each(function () {
var $this = $(this),
cbs = $this.data(ns);
if (!cbs) {
cbs = new ScrollStateCallbacks(this);
$this.data(ns, cbs);
}
cbs.bind(callback);
});
}
return this.length ? new ScrollState(this[0]) : null;
},
// ### 'scroll'
// Scrolls the selected elements relative to its current position,
// `padding` defaults to `0`, `duration` to `1000`.
//
// .fracs('scroll', element: HTMLElement/jQuery, [paddingLeft: int,] [paddingTop: int,] [duration: int]): jQuery
scroll: function (left, top, duration) {
return this.each(function () {
new Viewport(this).scroll(left, top, duration);
});
},
// ### 'scrollTo'
// Scrolls the selected elements to the specified element or an absolute position,
// `padding` defaults to `0`, `duration` to `1000`.
//
// .fracs('scrollTo', element: HTMLElement/jQuery, [paddingLeft: int,] [paddingTop: int,] [duration: int]): jQuery
// .fracs('scrollTo', [left: int,] [top: int,] [duration: int]): jQuery
scrollTo: function (element, paddingLeft, paddingTop, duration) {
if ($.isNumeric(element)) {
duration = paddingTop;
paddingTop = paddingLeft;
paddingLeft = element;
element = null;
}
element = getHTMLElement(element);
return this.each(function () {
if (element) {
new Viewport(this).scrollToElement(element, paddingLeft, paddingTop, duration);
} else {
new Viewport(this).scrollTo(paddingLeft, paddingTop, duration);
}
});
},
// ### 'scrollToThis'
// Scrolls the viewport (window) to the first selected element in the specified time,
// `padding` defaults to `0`, `duration` to `1000`.
//
// .fracs('scrollToThis', [paddingLeft: int,] [paddingTop: int,] [duration: int,] [viewport: HTMLElement/jQuery]): jQuery
scrollToThis: function (paddingLeft, paddingTop, duration, viewport) {
viewport = new Viewport(getHTMLElement(viewport));
viewport.scrollToElement(this[0], paddingLeft, paddingTop, duration);
return this;
},
// ### 'softLink'
// Converts all selected page intern links `` into soft links.
// Uses `scrollTo` to scroll to the location.
//
// .fracs('softLink', [paddingLeft: int,] [paddingTop: int,] [duration: int,] [viewport: HTMLElement/jQuery]): jQuery
softLink: function (paddingLeft, paddingTop, duration, viewport) {
viewport = new Viewport(getHTMLElement(viewport));
return this.filter('a[href^=#]').each(function () {
var $a = $(this);
$a.on('click', function () {
viewport.scrollToElement($($a.attr('href'))[0], paddingLeft, paddingTop, duration);
});
});
},
// ### 'sort'
// Sorts the set of selected elements by the specified property.
// Valid values for property are `possible`, `visible`, `viewport`,
// `width`, `height`, `left`, `right`, `top`, `bottom`. The default
// sort order is descending.
//
// .fracs('sort', property: String, [ascending: boolean]): jQuery
sort: function (property, ascending, viewport) {
if (!isTypeOf(ascending, 'boolean')) {
viewport = ascending;
ascending = null;
}
viewport = getHTMLElement(viewport);
return this.pushStack($.map(new Group(this, viewport).sorted(property, !ascending), function (entry) {
return entry.el;
}));
},
// ### 'viewport'
// Returns the current viewport of the first selected element in content space.
// If no element is selected it returns the document's viewport.
//
// .fracs('viewport'): Rect
viewport: function (inContentSpace) {
return this.length ? Rect.ofViewport(this[0], inContentSpace) : null;
}
},
// Defaults
// --------
defaultStatic: 'fracs',
defaultMethod: 'fracs'
});
}());
© 2015 - 2025 Weber Informatics LLC | Privacy Policy