I have a Table of Contents with id #TableOfContents in which each href points to a h2 or h3.
The problem I am having is that once the Heading, h2 or h3 is observed by intersection observer, Entry for that is highlighted by adding class side-active for that link in #TableOfContents, but as soon as the long content (such as p paragraph) after the heading comes in viewport the highlight for that section is removed since the heading is not in viewport.
This is a problem since I want the section (h2, h3) to still be highlighted until next h2 or h3 doesn't cross half of viewport.
What can I do?
window.addEventListener('DOMContentLoaded', () => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const id = entry.target.getAttribute('id');
if (entry.intersectionRatio > 0) {
document.querySelector(`#TableOfContents a[href="#${id}"]`).classList.add('side-active');
} else {
document.querySelector(`#TableOfContents a[href="#${id}"]`).classList.remove('side-active');
}
});
});
toc = document.querySelectorAll('#TableOfContents a');
// get content so that link refer to it
toc.forEach(function (link) {
var id = link.getAttribute("href");
var element = document.querySelector(id);
observer.observe(element);
});
});
Text is highlighted when heading in viewport
Text is not highlighted once heading is not in viewport
So the thing was we needed to calculate containerBottom by:
adding current container's top + next container's top
Or if it is last container then,
current container's top + it's outerHeight()
Once that; if ith container is in scrollposition add class to it And remove class from all containers previous to ith container (line no 18-21) (reverse loop)
$(function () {
// Table of contents (`ul`) that contains `a` tag in `li` which we want to highlight
var sectionIds = $('#TableOfContents a');
$(document).on('scroll', function(){
sectionIds.each(function(i, e){
var container = $(this).attr('href');
var containerOffset = $(container).offset().top; // container's top
var nextContainer = $(sectionIds[i+1]).attr('href')
if (i != sectionIds.length-1) {
// if this container isn't last container
var containerHeight = $(nextContainer).offset().top;
} else {
// last container's height will be outerHeight
var containerHeight = $(container).outerHeight();
}
var containerBottom = containerOffset + containerHeight;
var scrollPosition = $(document).scrollTop();
if(scrollPosition < containerBottom - 20 && scrollPosition >= containerOffset - 20){
for (var j = i; j >= 0; j--) {
$(sectionIds[j]).removeClass('active');
}
$(sectionIds[i]).addClass('active');
} else{
$(sectionIds[i]).removeClass('active');
}
});
});
});
Check the first heading ("Line Equations" h1) that is highlighted stays highlighted even though the title is not in viewport until next sub heading ("Distance of a point from a line") comes into view.
Right now I have a lovely code (that was initially for flowing snowflakes) that lets cloned divs fall from the top of the window, to the bottom and repeat. The thing is that I want the content to change on click. However, this is not yet working.
I know how to change content of a div without it being cloned, but I have serious trouble figuring out how to do the same with one div being cloned within the code.
Anyone have any tips what I should do, even a hint in which direction to go. I'm clueless.
This is the fiddle:
http://jsfiddle.net/4yaxvt7h/
the javascript:
function changeImage(){
document.getElementById('toChange').src='https://i.pinimg.com/originals/6e/19/56/6e195649034f042d1dea5230234570a8.gif';
}
// Array to store our Snowflake objects
var snowflakes = [];
// Global variables to store our browser's window size
var browserWidth;
var browserHeight;
// Specify the number of snowflakes you want visible
var numberOfSnowflakes = 15;
// Flag to reset the position of the snowflakes
var resetPosition = false;
// Handle accessibility
var enableAnimations = false;
var reduceMotionQuery = matchMedia("(prefers-reduced-motion)");
// Handle animation accessibility preferences
function setAccessibilityState() {
if (reduceMotionQuery.matches) {
enableAnimations = false;
} else {
enableAnimations = true;
}
}
setAccessibilityState();
reduceMotionQuery.addListener(setAccessibilityState);
//
// It all starts here...
//
function setup() {
if (enableAnimations) {
window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
window.addEventListener("resize", setResetFlag, false);
}
}
setup();
//
// Constructor for our Snowflake object
//
function Snowflake(element, speed, xPos, yPos) {
// set initial snowflake properties
this.element = element;
this.speed = speed;
this.xPos = xPos;
this.yPos = yPos;
this.scale = 1;
// declare variables used for snowflake's motion
this.counter = 0;
this.sign = Math.random() < 0.5 ? 1 : -1;
// setting an initial opacity and size for our snowflake
this.element.style.opacity = 1;
}
//
// The function responsible for actually moving our snowflake
//
Snowflake.prototype.update = function () {
// using some trigonometry to determine our x and y position
this.counter += this.speed / 5000;
this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
this.scale = .5 + Math.abs(10 * Math.cos(this.counter) / 20);
// setting our snowflake's position
setTransform(Math.round(this.xPos), Math.round(this.yPos), this.scale, this.element);
// if snowflake goes below the browser window, move it back to the top
if (this.yPos > browserHeight) {
this.yPos = -50;
}
}
//
// A performant way to set your snowflake's position and size
//
function setTransform(xPos, yPos, scale, el) {
el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})`;
}
//
// The function responsible for creating the snowflake
//
function generateSnowflakes() {
// get our snowflake element from the DOM and store it
var originalSnowflake = document.querySelector(".snowflake");
// access our snowflake element's parent container
var snowflakeContainer = originalSnowflake.parentNode;
snowflakeContainer.style.display = "block";
// get our browser's size
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
// create each individual snowflake
for (var i = 0; i < numberOfSnowflakes; i++) {
// clone our original snowflake and add it to snowflakeContainer
var snowflakeClone = originalSnowflake.cloneNode(true);
snowflakeContainer.appendChild(snowflakeClone);
// set our snowflake's initial position and related properties
var initialXPos = getPosition(50, browserWidth);
var initialYPos = getPosition(50, browserHeight);
var speed = 5 + Math.random() * 40;
// create our Snowflake object
var snowflakeObject = new Snowflake(snowflakeClone,
speed,
initialXPos,
initialYPos);
snowflakes.push(snowflakeObject);
}
// remove the original snowflake because we no longer need it visible
snowflakeContainer.removeChild(originalSnowflake);
moveSnowflakes();
}
//
// Responsible for moving each snowflake by calling its update function
//
function moveSnowflakes() {
if (enableAnimations) {
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.update();
}
}
// Reset the position of all the snowflakes to a new value
if (resetPosition) {
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.xPos = getPosition(50, browserWidth);
snowflake.yPos = getPosition(50, browserHeight);
}
resetPosition = false;
}
requestAnimationFrame(moveSnowflakes);
}
//
// This function returns a number between (maximum - offset) and (maximum + offset)
//
function getPosition(offset, size) {
return Math.round(-1 * offset + Math.random() * (size + 2 * offset));
}
//
// Trigger a reset of all the snowflakes' positions
//
function setResetFlag(e) {
resetPosition = true;
}
html
<div id="snowflakeContainer">
<div class="snowflake"><img src="element1.png"
</div>
css
body{
background-color: black;
}
#snowflakeContainer {
position: absolute;
left: 0px;
top: 0px;
display: none;
}
.snowflake {
position: fixed;
background-color: red;
user-select: none;
z-index: 1000;
pointer-events: none;
border-radius: 50%;
width: 200px;
height: 200px;
}
img{
max-width: 100%;
}
any tips are super welcome!!
You have several different problems here. First, your CSS sets pointer-events: none; for all .snowflake elements. This will stop any clicks from triggering, so you have to remove it if you want mouse interactivity.
Second, your changeImage() function uses document.getElementById('toChange') to get the element to change the source of. No such element exists and even if it did, that would mean that clicking on any of the snowflakes would just change the source of that one image. You need to reference the snowflake that you clicked on. An easy way to do this is by passing this as an argument to the function in the onclick attribute:
HTML:
<div class="snowflake"><img src="https://vignette.wikia.nocookie.net/dragonballfanon/images/7/70/Random.png/revision/latest?cb=20161221030547" onclick="changeImage(this)"></div>
JS:
function changeImage(img) {
img.src = 'https://i.pinimg.com/originals/6e/19/56/6e195649034f042d1dea5230234570a8.gif';
}
Finally, your JSFiddle is configured to delay execution of the JavaScript until after the DOM is ready. This means that the code will be wrapped in a callback function, and therefore the changeImage() function will no longer be in the global scope. This makes it inaccessible to the elements that want to call it in their handlers (the snowflakes). Because you are already listening for the DOMContentLoaded event on your own, you can just change the code to execute normally and it should work. Click on the dropdown that says "JavaScript + jQuery 3.2.1" above your JS code and change the load type to any "No wrap" option and it should work.
I want to make a function that will automatically display items as the user scrolls upwards. Think messages, where older ones are up top, but we start at the bottom with the newest ones. I have another function that loads items at the bottom of a container, and as it does so, the current items remain in position, and scrollbar is smaller. We are not scrolled to the bottom. However, with the other direction, when I prepend items to an array, it scrolls all the way to the top, displaying the top of the loaded items, instead of remaining in the same place and letting the user scroll up as needed.
My code for the bottom scroll is this:
attachScrollWatcher: function (element, offset, callback) {
console.log('scrolling');
var contentHeight = element.scrollHeight;
var yOffset = element.scrollTop;
var y = yOffset + element.offsetHeight;
if (y >= ( contentHeight - offset ))
{
callback();
}
}
This function is attached to an object's onscroll event. However, now I need to make a function that does the opposite, going upwards. Any ideas how this can be implemented?
Basically, when scrollTop === 0 then you're at the top and you need to load a new item..
attachScrollWatcher: function (element, offset, callback) {
if(!element.scrollHeight) callback();
}
The problem is, loading a new item will keep the scrollTop at zero, so the user would have to scroll down and then scroll back up in order for the callback to be triggered again. So, what you wanna do is calculate the scrollHeight before the new item is added and then again after the item is added and then manually set the scrollTop to the difference between the original and the new scrollHeight.
Check out my example attachScrollListener method below...
class upScroller{
constructor(ele = document.body){
this.renderedItems = 0;
this.ele = ele; var i=0;
this.initBoxContents();
}
initBoxContents(){
if(this.ele.scrollHeight == this.ele.clientHeight)
this.populateNextItem().then(()=>this.initBoxContents());
else{
this.ele.scrollTop = this.ele.clientHeight;
this.attachScrollListener();
}
}
getNextItem(){
// Do something here to get the next item to render
// preferably using ajax but I'm using setTimeout
// to emulate the ajax call.
return new Promise(done=>setTimeout(()=>{
this.renderedItems++;
done(`<p>This is paragraph #${this.renderedItems}</p>`);
},50));
}
populateNextItem(){
return new Promise(done=>{
this.getNextItem().then(item=>{
this.ele.insertAdjacentHTML('afterbegin', item);
done();
});
});
}
attachScrollListener(){
this.ele.addEventListener('scroll', ()=>{
if(this.ele.scrollTop) return;
var sh = this.ele.scrollHeight;
this.populateNextItem().then(()=>{
this.ele.scrollTop = this.ele.scrollHeight - sh;
});
});
}
}
var poop = document.getElementById('poop');
new upScroller(poop);
#poop{ height: 300px; overflow: auto; border:1px solid black;}
<div id=poop></div>
I've posted this here as well....
Something like this may work.
attachScrollWatcher: function (element, offset, callback) {
console.log('scrolling');
var contentHeight = element.scrollHeight;
var yOffset = element.scrollTop;
var y = yOffset + element.offsetHeight;
if (y >= ( contentHeight - offset ))
{
callback();
} else {
callbackGoingUp();
}
}
My page is divided into three sections and each section can be accessed by respective menu item. I am trying to achieve this in Javascript: when the user has reached any of the sections by scrolling, the font color of respective menu item should change.
Here I call the function:
<body onscroll="detectScroll(); showPosition();">
This is the function that detects scrolling and changes some items accordingly. It's working fine:
function detectScroll() {
var header = document.querySelector(".headerOrig"),
header_height = getComputedStyle(header).height.split('px')[0],
header_class = "changeHeader",
logo = document.getElementById("logo")
;
if( window.pageYOffset > (parseInt(header_height) + 500)) {
header.classList.add(header_class);
logo.src = "images/logo2.png";
}
if( window.pageYOffset < (parseInt(header_height) + 500)) {
header.classList.remove(header_class);
logo.src = "images/logo1.png";
}
}
This JS function returns the position of an element. Works fine as well:
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while(element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
And, finally, this is the JS function that is being called when scrolling:
function showPosition() {
var myElement = document.getElementById("posBIKES");
var position = getPosition(myElement);
var bike = document.getElementById("bikesMenu");
//alert("The element is located at: " + position.x + ", " + position.y);
if(window.pageYOffset < position.y) {
window.getElementById("bikesMenu").classList.remove("changeMenu");
}
if(window.pageYOffset > position.y) {
window.getElementById("bikesMenu").classList.add("changeMenu");
}
}
The problem is everything works fine until I try to add or remove the class to the item selected (the last function). Any other statement works fine, for example, I tried putting alert("something"); in both conditions and both worked as desired. Whats wrong with adding and removing classes then?
And yes, I have checked the corresponding names and IDs of everything like million times, so theres no issue with that.
Any help is more than appreciated.
Thanks
I want to write a browser (Chrome/FF) extension that needs to select an element on a web page. I would like it to behave like Firebug's element inspector does. You click the inspect arrow and you can then hover/highlight elements. When you click on the element you want, the element is inspected. I'm just interested in the code to allow a user to select an element - not in actually inspecting it or anything similar.
Because I'm writing an extension, it might be nice if you could provide non-jQuery/Prototype/etc.. code so I don't have to distribute that.
I have recently required such a feature for a project I was working on, turned out that I had to use for sides to create a box because otherwise the event.target when you move the mouse would end up being the selector, and if I were to use z-index: -1 it would be a bit fishy when you have a lot of elements that overlap...etc.
Here is a version that I have converted from my project for your benefit, it involves jQuery but it is extremely simple to convert to vanilla as only the mousemove & css methods from jQuery are used.
Step by step instructions.
First create the 5 HTMLElements that are required.
<div id="selector">
<div id="selector-top"></div>
<div id="selector-left"></div>
<div id="selector-right"></div>
<div id="selector-bottom"></div>
</div>
Secondly create a mousemove event on the document (or your container)
$(document).mousemove(function(event) { ... });
Then inside the mousemove we will do some basic checking to prevent selecting the HTML, BODY, selector
var id = event.target.id, tagName = event.target.tagName;
if(id.indexOf('selector') !== -1 || tagName === 'BODY' || tagName === 'HTML') {
return;
}
Then we need to create a object to store our elements like so.
var elements = {
top: $('#selector-top'),
left: $('#selector-left'),
right: $('#selector-right'),
bottom: $('#selector-bottom')
};
After that we store some variables that hold some information about the target element like so.
var $target = event.target;
targetOffset = $target.getBoundingClientRect(),
targetHeight = targetOffset.height,
targetWidth = targetOffset.width;
Then all we do is calculate the position & height for all 4 sides of the selector like so.
elements.top.css({
left: (targetOffset.left - 4),
top: (targetOffset.top - 4),
width: (targetWidth + 5)
});
elements.bottom.css({
top: (targetOffset.top + targetHeight + 1),
left: (targetOffset.left - 3),
width: (targetWidth + 4)
});
elements.left.css({
left: (targetOffset.left - 5),
top: (targetOffset.top - 4),
height: (targetHeight + 8)
});
elements.right.css({
left: (targetOffset.left + targetWidth + 1),
top: (targetOffset.top - 4),
height: (targetHeight + 8)
});
All of the +aFewPixels is just a little optimization so that there is like 2px gap in between the selector and the target.
For the CSS this is what I have come up with.
#selector-top, #selector-bottom {
background: blue;
height:3px;
position: fixed;
transition:all 300ms ease;
}
#selector-left, #selector-right {
background: blue;
width:3px;
position: fixed;
transition:all 300ms ease;
}
The transition gives the selector a very nice sliding effect.
Try out a demo http://jsfiddle.net/rFc8E/9/
Note: This also works for transform: scale(2); eg. when a element is scaled in size.
Edit: I've just updated this, I noticed that the elements object was inside the event handler, I've moved it outside in the demo, this is quite an important performance improvement because now, the elements object is only created once instead of Hundreds of Thousands if not millions of times inside the mousemove event.
I wrote an implementation of this using jQuery as a component of another project. The source and documentation are available here: https://github.com/andrewchilds/jQuery.DomOutline
One simple way to do it is to use an outline instead of a border:
.highlight { outline: 4px solid #07C; }
Just add and remove that class to any element you want to select/deselect (code below is not properly tested):
document.body.addEventListener("mouseover", function(e) {
e.stopPropagation();
e.target.addEventListener("mouseout", function (e) {
e.target.className = e.target.className.replace(new RegExp(" highlight\\b", "g"), "");
});
e.target.className += " highlight";
});
Since you are using an outline, (which is supported by Chrome) instead of a border, elements will not jump around. I'm using something similar in my EasyReader Extension.
HTML Element Picker (Vanilla JS)
Pick and highlight any HTML element on a page with only Vanilla JS! Tested in Chrome, FF, and Opera, doesn't work in IE.
How it works:
What you need is actually very simple. You can just create an empty div box with a background in JS and move it around to highlight on top of hovered elements.
Here's the JS code:
const hoverBox = document.createElement("div");
console.log("hoverBox: ", hoverBox);
hoverBox.style.position = "absolute";
// change to whatever highlight color you want
hoverBox.style.background = "rgba(153, 235, 255, 0.5)";
// avoid blocking the hovered element and its surroundings
hoverBox.style.zIndex = "0";
document.body.appendChild(hoverBox);
let previousTarget;
document.addEventListener("mousemove", (e) => {
let target = e.target;
if (target === hoverBox) {
// the truely hovered element behind the added hover box
const hoveredElement = document.elementsFromPoint(e.clientX, e.clientY)[1];
if (previousTarget === hoveredElement){
// avoid repeated calculation and rendering
return;
} else{
target = hoveredElement;
}
} else{
previousTarget = target;
}
const targetOffset = target.getBoundingClientRect();
const targetHeight = targetOffset.height;
const targetWidth = targetOffset.width;
// add a border around hover box
const boxBorder = 5;
hoverBox.style.width = targetWidth + boxBorder * 2 + "px";
hoverBox.style.height = targetHeight + boxBorder * 2 + "px";
// need scrollX and scrollY to account for scrolling
hoverBox.style.top = targetOffset.top + window.scrollY - boxBorder + "px";
hoverBox.style.left = targetOffset.left + window.scrollX - boxBorder + "px";
});
See Demo
I also made an npm package for the element picker with many more user configurations like background color, border width, transition, etc.
Here's the GitHub page.
I ended up asking in the Firebug group and got some great help:
http://groups.google.com/group/firebug/browse_thread/thread/7d4bd89537cd24e7/2c9483d699efe257?hl=en#2c9483d699efe257
Here is a library that written in pure javascript as an alternative.
TheRoom JS: https://github.com/hsynlms/theroomjs
// theroom information template for target element
var template="";
template += "<div id=\"theroom-info\">";
template += " <span id=\"theroom-tag\"><\/span>";
template += " <span id=\"theroom-id\"><\/span>";
template += " <span id=\"theroom-class\"><\/span>";
template += "<\/div>";
template += "";
template += "<style>";
template += " #theroom-info {";
template += " position: fixed;";
template += " bottom: 0;";
template += " width: 100%;";
template += " left: 0;";
template += " font-family: \"Courier\";";
template += " background-color: #ffffff;";
template += " padding: 10px;";
template += " color: #333333;";
template += " text-align: center;";
template += " box-shadow: 0px 4px 20px rgba(0,0,0,0.3);";
template += " }";
template += "";
template += " #theroom-tag {";
template += " color: #C2185B;";
template += " }";
template += "";
template += " #theroom-id {";
template += " color: #5D4037;";
template += " }";
template += "";
template += " #theroom-class {";
template += " color: #607D8B;";
template += " }";
template += "<\/style>";
var options = {
template: template,
showInfo: true
};
// initialize
theRoom.start(options);
codepen demo
There was a similar question asked on Stackoverflow and it had lots of good answers:
Does anyone know a DOM inspector javascript library or plugin?
For those who are looking for a quick and dirty solution:
http://userscripts.org/scripts/review/3006 is the easiest. Just put the code within <script></script> tags and you are good to go.
https://github.com/josscrowcroft/Simple-JavaScript-DOM-Inspector/blob/master/inspector.js is slightly better and still very easy to integrate in.
For a more sophisticated element inspector, you might want to check out the SelectorGadget as pointed by Udi. The inspector selection code is in http://www.selectorgadget.com/stable/lib/interface.js
Also check this one out:
http://rockingcode.com/tutorial/element-dom-tree-jquery-plugin-firebug-like-functionality/
I found it pretty insightful.. and there's a demo here:
http://rockingcode.com/demos/elemtree/
Hope this helps.
A very basic implementation can be done very easily without jQuery using .onmouseover and e.target:
var last,
bgc;
document.onmouseover = function(e) {
var elem = e.target;
if (last != elem) {
if (last != null) {
last.classList.remove("hovered");
}
last = elem;
elem.classList.add("hovered");
}
}
With the CSS below if you want the children to change background as well:
.hovered,
.hovered * {
cursor: pointer;
color: black;
background-color: red;
}
Demo
If you want to select elements only near the edges (or select the parent near the edges and the element itself everywhere else) you could use .getBoundingClientRect.
var last;
window.addEventListener("mousemove", function(e) {
if(last) {
last.style.background = ''; // empty is enough to restore previous value
}
var elem = e.target;
if(elem === document.body || elem === document.documentElement) {
return;
}
var bb = elem.getBoundingClientRect();
var xr = e.pageX - bb.left; // x relative to elem
var yr = e.pageY - bb.top; // y relative to elem
var ew = 10; // edge width
if(
xr <= ew
|| xr >= bb.width - ew
|| yr <= ew
|| yr >= bb.height - ew
){
elem.style.background = 'red';
last = elem;
}
});
Paired with some borders, this can be pretty usable for selection. Demo
What you need to do is to create 4 elements for the highlighting. They will form an empty square, and so your mouse events are free to fire. This is similar to this overlay example I've made.
The difference is that you only need the four elements (no resize markers), and that the size and position of the 4 boxes are a bit different (to mimick the red border). Then you can use event.target in your event handler, because it gets the real topmost element by default.
Another approach is to hide the exra element, get elementFromPoint, calculate then put it back.
They're faster than light, I can tell you. Even Einstein would agree :)
1.) elementFromPoint overlay/borders - [Demo1] FF needs v3.0+
var box = $("<div class='outer' />").css({
display: "none", position: "absolute",
zIndex: 65000, background:"rgba(255, 0, 0, .3)"
}).appendTo("body");
var mouseX, mouseY, target, lastTarget;
// in case you need to support older browsers use a requestAnimationFrame polyfill
// e.g: https://gist.github.com/paulirish/1579671
window.requestAnimationFrame(function frame() {
window.requestAnimationFrame(frame);
if (target && target.className === "outer") {
box.hide();
target = document.elementFromPoint(mouseX, mouseY);
}
box.show();
if (target === lastTarget) return;
lastTarget = target;
var $target = $(target);
var offset = $target.offset();
box.css({
width: $target.outerWidth() - 1,
height: $target.outerHeight() - 1,
left: offset.left,
top: offset.top
});
});
$("body").mousemove(function (e) {
mouseX = e.clientX;
mouseY = e.clientY;
target = e.target;
});
2.) mouseover borders - [Demo2]
var box = new Overlay();
$("body").mouseover(function(e){
var el = $(e.target);
var offset = el.offset();
box.render(el.outerWidth(), el.outerHeight(), offset.left, offset.top);
});
/**
* This object encapsulates the elements and actions of the overlay.
*/
function Overlay(width, height, left, top) {
this.width = this.height = this.left = this.top = 0;
// outer parent
var outer = $("<div class='outer' />").appendTo("body");
// red lines (boxes)
var topbox = $("<div />").css("height", 1).appendTo(outer);
var bottombox = $("<div />").css("height", 1).appendTo(outer);
var leftbox = $("<div />").css("width", 1).appendTo(outer);
var rightbox = $("<div />").css("width", 1).appendTo(outer);
// don't count it as a real element
outer.mouseover(function(){
outer.hide();
});
/**
* Public interface
*/
this.resize = function resize(width, height, left, top) {
if (width != null)
this.width = width;
if (height != null)
this.height = height;
if (left != null)
this.left = left;
if (top != null)
this.top = top;
};
this.show = function show() {
outer.show();
};
this.hide = function hide() {
outer.hide();
};
this.render = function render(width, height, left, top) {
this.resize(width, height, left, top);
topbox.css({
top: this.top,
left: this.left,
width: this.width
});
bottombox.css({
top: this.top + this.height - 1,
left: this.left,
width: this.width
});
leftbox.css({
top: this.top,
left: this.left,
height: this.height
});
rightbox.css({
top: this.top,
left: this.left + this.width - 1,
height: this.height
});
this.show();
};
// initial rendering [optional]
// this.render(width, height, left, top);
}