Instantly share code, notes, and snippets.

Embed
What would you like to do?
$.inside

$.fn

Synopsis

$el.inside( <ancestor> [, <includeMargin>] )

Arguments

<ancestor>: The ancestor to compare $el with

    'selector' | jQuery | node

<includeMargin>: Whether to take margins into account

Returns

{
    left: <left>
    top: <top>
}

<left|top>: Position of $el to <ancestor>

    +-----+                   +-----+
    | 0/0 |                   | 1/0 | 
    +-----+                   +-----+
           +-----------------+
           |     +-----+     |
           |     |.5/.5|     |
           |     +-----+     |
           +-----------------+
    +-----+                   +-----+
    | 0/1 |                   | 1/1 |
    +-----+                   +-----+

Example

Determine if an element is in the viewport — and how far:

$('#foo').inside('html');

$.event.special

Synopsis

$(el).bind('inside', {ancestor: 'html'}, function (e, inside) {
  // inside.left
  // inside.top
});
body {margin:auto;}
html, body {height:100%;}
html {display:table;width:100%; overflow:hidden;}
body {display:table-cell; vertical-align:middle; text-align:center;}
#foo,
#bar {
background:rgba(255,255,255,.5);
display:inline-block; width:5em; height:3.75em;
border:.25em solid rgba(0,0,0,.5);
}
#bar {
width:8.75em; height:5em;
font-size:215%;
}
#bar:hover {cursor:move;}
#bar.overlap {background-color:rgba(255,249,0,.25);}
#bar .ui-resizable-handle {width:.5em; height:.5em; position:absolute; right:0; bottom:0; background:rgba(0,0,0,.5); cursor:nwse-resize;}
#bar {min-width:.5em; min-height:.5em;}
.value {font-family:georgia; font-size:500%; position:fixed;width:100%;margin-left:-50%; top:0;left:50%; text-align:center; margin-top:.5em;}
meter {position:fixed; width:100%;}
meter.horizontal {left:0; bottom:0;}
meter.vertical {
left:0; bottom:0;
-webkit-transform:rotate(-90deg);-webkit-transform-origin:left top;
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>$.inside</title>
<link rel="stylesheet" href="index.css">
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
<script src="jquery.inside.js"></script>
<script src="index.js"></script>
</head>
<body>
<meter class="horizontal" min="0" max="100" value="100"></meter>
<meter class="vertical" min="0" max="100" value="100"></meter>
<span class="value"></span>
<div id="foo">
<div id="bar" style="position:relative; left:-43px;top:-29px;"></div>
</div>
</body>
</html>
$(function () {
function handler(e, inside) {
var insideLeft = zeroOneZero(inside.left),
insideTop = zeroOneZero(inside.top);
$('.value').text(inside.left.toFixed(1) + " / " + inside.top.toFixed(1));
$(this).toggleClass('overlap', insideLeft>=0 && insideLeft<=1 && insideTop>=0 && insideTop<=1);
$('meter.horizontal').val(100 * insideLeft);
$('meter.vertical').val(100 * insideTop);
}
$('#bar')
.draggable()
.resizable()
.bind('inside', {
ancestor: '#foo',
frequency: 1000 / 15
}, handler);
(function resize() {
$('meter.vertical').width($(window).height());
}());
$(window).resize(resize);
// Helper
function zeroOneZero(zeroToOne) {
return -1 * Math.abs((zeroToOne - .5) * 2) + 1;
}
});
(function ($) {
"use strict";
//
// $.fn.offsetRelative dependency (https://gist.github.com/3191472)
//
$.fn.offsetRelative = $.fn.offsetRelative || function (selector) {
selector || (selector = '*');
var elOffset = this.offset(),
parentOffset = this.parent().closest(selector).offset();
return {
left: elOffset.left - parentOffset.left,
top: elOffset.top - parentOffset.top
};
};
//
// Inside plugin
//
$.fn.inside = $.fn.inside || function (container, includeMargin) {
includeMargin || (includeMargin = false);
var $el = this.eq(0),
$container = $(container);
if (!$.contains($container.get(0), $el.get(0))) {
return;
}
var o = $el.offsetRelative($container),
w = $container.outerWidth(includeMargin),
h = $container.outerHeight(includeMargin),
W = $el.outerWidth(includeMargin),
H = $el.outerHeight(includeMargin);
return {
left: (o.left + W) / (w + W),
top: (o.top + H) / (h + H)
};
};
//
// 'inside' special event
//
$.event.special.inside = $.event.special.inside || (function () {
var registry = {};
// Main handler
function handler(key) {
$(this).trigger('inside', $(this).inside(registry[key].handleObj.data.ancestor));
}
return {
add: function (handleObj) {
var frequency = handleObj.data.frequency || 200,
key = handleObj.guid;
// Interval
var interval = setInterval($.proxy(function () {
return handler.apply(this, [key]);
}, this), frequency);
// Store to the registry
registry[key] = {
handleObj: handleObj,
interval: interval
};
},
remove: function (handleObj) {
var key = handleObj.guid;
// Clear from the registry
clearInterval(registry[key].interval);
delete registry[key];
}
};
}());
}(jQuery));
@abernier

This comment has been minimized.

Show comment
Hide comment
Owner

abernier commented Jul 28, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment