Read more / Read less functionality failing - javascript

I'm using the following code to automatically shorten div elements that contain a lot of text. It abbreviates the first paragraph and adds a "Read More" link. This works fine, as does the "Read less" link, which appears after the content is expanded. However, the "Read More" link does not work the second time it is clicked.
Is there a JavaScript error that could be causing this problem in the code below? (Tested on mobile safari, iOS simulator.)
function ExpandableContent(container, userSettings) {
/************ Validation *************/
if (!this.constructor || !this.constructor instanceof ExpandableContent) {
return new ExpandableContent(container, userSettings);
}
if (typeof container !== 'object') {
console.error("Must provide DOM element.");
return;
}
if (!container.find('p').first().length) {
console.error("Containing element must include at least one paragraph element.");
return;
}
/************ Process user-provided settings *************/
var settings = {
previewLen: 75,
readMoreClass: 'read-more',
readLessClass: 'read-less',
readMoreText: 'Read More >',
readLessText: '< Read Less',
ellipsis: true
};
// Any property can be overridden by adding a data attribute to the container
for (var prop in settings) {
if (userSettings && prop in userSettings) settings[prop] = userSettings[prop];
if (typeof container.data(prop) !== 'undefined') settings[prop] = container.data(prop);
}
/************ Initialization *************/
var containerOrig, para1, para1Orig, bottomBuffer, readMore, readLess;
function init() {
readMore = $("<a href='javascript:undefined;'></a>").addClass(settings.readMoreClass),
readLess = $("<a href='javascript:undefined;'></a>").addClass(settings.readLessClass);
readMore.text(settings.readMoreText);
readLess.text(settings.readLessText);
// Store the original state of the container
containerOrig = (function(o) {
return {
height: o.height,
top: o.top
};
})(container.offset()),
// Store the original state of the container's first paragraph if it exists
para1 = container.find('p').first();
para1Orig = (function(para1, o) {
return {
content: para1.html(),
height: o.height,
top: o.top
};
})(para1, para1.offset());
// Shortened divs will be extended by the pixel equivalent of 1rem to make room for CSS borders.
bottomBuffer = getFontSizeAsPixels($('h1'));
}
init();
hide();
/************ Public hide, show and text abbreviation methods *************/
function show(){
readMore.remove();
// Show all elements after paragraph 1
elementsAfterPara1().map(function(el) { $(el).show(); });
// Restore height of container and its 1st paragraph
para1.html( para1Orig.content ).removeClass('abbreviated');
container.removeClass('abbreviated').css('height', containerOrig.height);
// Generate 'Read less' link
container.append(readLess);
readLess.click(function(){
hide();
scrollToEl(container);
});
}
function abbreviate(text) {
if (text.length <= settings.previewLen) return text; // Nothing to abbreviate
text = text.substr(0, settings.previewLen);
if (settings.ellipsis === true) text+= '...';
return text;
}
function elementsAfterPara1() {
var result = [], children = container.children(), start = children.index(para1) + 1;
if (!children[start]) return; // nothing to hide
for (var i = start, l = children.length; i < l; i++)
result.push(children[i]);
return result;
}
function hide(){
// Remove 'Read Less' if such a link is leftover from a previous request
readLess.remove();
// Get abbreviated text for first paragraph
var abbrev = abbreviate(para1Orig.content);
// abbreviate the first paragraph, shortening the text and appending an '...' if necessary
para1.html(abbrev);
//Shorten the container so it's just tall enough to encompass paragraph 1
var containerNewHeight = (para1Orig.top - containerOrig.top) + para1.offset().height;
// Hide everything after the first paragraph
elementsAfterPara1().map(function(el) { $(el).hide(); });
// Setting overflow-y to hidden prevents the user from scrolling the abbreviated div
container.addClass('abbreviated').css('height', containerNewHeight).css('overflow-y','hidden');
// Prevent the user from scrolling internally through the DIV
container.on('touchmove', function(e) {
e.preventDefault();
});
//Generate a 'Read More' link and place it below the text
para1.append(readMore);
readMore.on('tap click', show);
}
};

Only thing I can think of is that line: readMore.on('tap click', show);
Are you sure that 'tap click' (with space) is the correct event?
Why don't you stick to the
readMore.click(function(){
...
});
you used in the show function?

Related

Copy content from div to textarea in HTML

Main Target :
To create a website that will have a live preview of an HTML/CSS code. LINK
More specifically :
The HTML/CSS code will be editable form the user in some specific parts. So, the code in the live preview will not derive from text areas but from divs.
Image of what I am trying to do :
Progress so far :
So, in my previous questions :
a) Question 1
b) Question 2
I tried to find a way to make the live preview box work after getting the code from the black boxes. It did not work because the code was given in a div tag and not a textarea. I would like to add that the code in the div tags use xmp tags because some parts are editable from the user.
So, I found out that the best solution is to keep the div tags in order for the user to change/alter the code and then use a hidden textarea that will be used for the live preview.
Main Question :
How can I copy the content of the div in the textarea? I am using a JS script (below) to copy it in the clipboard. Is it possible to copy it in the textarea content?
After I do this, I will try to make it work without a copy(update code) button.
Here is my script :
$(document).ready(function() {
var highestBox = 0;
$('.top').each(function() {
if ($(this).height() > highestBox) {
highestBox = $(this).height();
}
});
$('.top').height(highestBox);
});
document.getElementById("copyButton1").addEventListener("click", function() {
copyToClipboard(document.getElementById("copyTarget1"));
});
document.getElementById("copyButton2").addEventListener("click", function() {
copyToClipboard(document.getElementById("copyTarget2"));
});
function copyToClipboard(elem) {
// create hidden text element, if it doesn't already exist
var targetId = "_hiddenCopyText_";
var isInput = elem.tagName === "INPUT" || elem.tagName === "textarea";
var origSelectionStart, origSelectionEnd;
if (isInput) {
// can just use the original source element for the selection and copy
target = elem;
origSelectionStart = elem.selectionStart;
origSelectionEnd = elem.selectionEnd;
} else {
// must use a temporary form element for the selection and copy
target = document.getElementById(targetId);
if (!target) {
var target = document.createElement("textarea");
target.style.position = "absolute";
target.style.left = "-9999px";
target.style.top = "0";
target.id = targetId;
document.body.appendChild(target);
}
target.textContent = elem.textContent;
}
// select the content
var currentFocus = document.activeElement;
target.focus();
target.setSelectionRange(0, target.value.length);
// copy the selection
var succeed;
try {
succeed = document.execCommand("copy");
} catch(e) {
succeed = false;
}
// restore original focus
if (currentFocus && typeof currentFocus.focus === "function") {
currentFocus.focus();
}
if (isInput) {
// restore prior selection
elem.setSelectionRange(origSelectionStart, origSelectionEnd);
} else {
// clear temporary content
target.textContent = "";
}
return succeed;
}
Cheers
I combined many things I found online and made it work using this script:
var MyDiv1 = document.getElementById('copyTarget2');
var MyDiv2 = document.getElementById('copyTarget1');
$('#Update').click(function(e) {
textareahtml.value=$.trim(MyDiv1.innerText)
textareacss.value=$.trim(MyDiv2.innerText)
});
and I put a button in my HTML code.

Highlight Deepest Child DOM Element with Div Overlay when Moused Over in Pure Javascript

The short version:
I want to mimic Google Chrome's Inspect Element tool in pure JavaScript.
The long version:
I am working on an extension for Google Chrome. I want to implement something similar to the Inspect Element tool in pure JavaScript (no jQuery or any other libraries/frameworks/dependencies). If anyone uses AdBlock, I specifically want to mimic the "Block an ad on this page" functionality that allows the user to select an element on the page.
While the extension is active, the user should be able to:
Mouse over an element
If a 'P' element with a 'CODE' element nested inside is being moused over, the entire 'P' element should have the 'DIV' overlay over it
If the mouse moves over the nested 'CODE' element it should re-size the 'DIV' overlay to cover only the deeper nested 'CODE' element
When clicked, the underlying element should be stored and the 'DIV' overlay hidden
Why use a 'DIV' overlay instead of just adding a class to the element that adds a border/outline/background color?
The overlay prevents the user from directly interacting with the element. If there is an href/onClick attribute I do not want it to activate when clicked.
Can you just write something that stores all inline 'onclick' attributes, sets them to null/return false; and then restores the original 'onclick' code?
Tried that:
onclicks = document.querySelectorAll('[onclick]');
saved = [];
// disable onclicks
function disableOnclicks() {
for (var i = 0; i < onclicks.length; i++) {
saved[i] = onclicks[i].cloneNode();
onclicks[i].onclick = "return false;";
};
console.log("onclicks disabled");
}
// enable onclicks
function enableOnclicks() {
for (var i = 0; i < onclicks.length; i++) {
onclicks[i].onclick = saved[i].onclick;
};
console.log("onclicks enabled");
}
// if injecting script, make sure all elements have loaded
window.onload = function(){
disableOnclicks();
console.log("onclicks disabled");
enableOnclicks();
console.log("onclicks enabled");
}
unfortunately, it doesn't handle any invisible event listeners that may be on a given page.
My current code formatted to paste into console:
// CSS to highlight element
var overlayCSS = document.createElement("style");
overlayCSS.type = "text/css";
overlayCSS.innerHTML = "body .highlight-element{z-index:2147483647!important}.highlight-element{background-color:rgba(130,180,230,.4);outline:#0F4D9A solid 1px;box-sizing:border-box;position:absolute;display:none}";
document.body.appendChild(overlayCSS); // append style tag to body
// create div overlay to highlight elements & prevent onclick events
var overlay = document.createElement("div");
overlay.className = "highlight-element";
document.body.appendChild(overlay); // append div overlay to body
// check if overlay was appended
if (overlay === document.getElementsByClassName('highlight-element')[0]) {
console.log("overlay exists");
};
// positions div overlay based on targetRect AKA element.getBoundingClientRect()
function moveOverlay (targetRect) {
var overlay = document.getElementsByClassName('highlight-element')[0];
// correct for page scroll
overlay.style.top = (targetRect.top + window.scrollY) + "px";
overlay.style.left = targetRect.left + "px";
overlay.style.height = targetRect.height + "px";
overlay.style.width = targetRect.width + "px";
overlay.style.display = "block";
}
// set start time for lastfire
var lastfire = Date.now();
function getInnermostHovered(e) {
// difference between now and the last event
var difference = Date.now() - lastfire;
// console.log(difference);
// delay handling mousemove by some milliseconds
// making 0 may induce epileptic shock...
if (difference > 100) {
// prevent endless highlight loop
if (e.target.getAttribute('class') == "highlight-element") {
e.target.style.display = "none";
}
// get element under mouse
var n = document.querySelector(":hover");
var nn;
// get deepest child element that has :hover
while (n) {
nn = n;
n = nn.querySelector(":hover");
}
console.log("nn: " + nn);
// get dimensions to pass to div overlay
var targetRect = nn.getBoundingClientRect();
// console.log(targetRect.top);
// display overlay div at element position under mouse
moveOverlay(targetRect);
// event fired, so overwrite last fire time
lastfire = Date.now();
}
}
// onMouseMove get deepest child element under the mouse
document.addEventListener('mousemove', getInnermostHovered, false);
Feel free to test it out on this page (refresh the page to cancel), currently I have the overlay sort-of working by alternating displaying/hiding the overlay 'DIV' on the 'mousemove' event. Ideally I want it to run as smooth Chrome's Inspect Element and give me the element data. Any and all ideas are appreciated, but I must stress that I really want to do this in pure JavaScript.
Solve it with document.elementFromPoint(x,y).
This code will work pasted in Chrome's console, press ESC to cancel.
var rootNode = document.documentElement;
var currentNode = currentNode || {};
var lastNode = lastNode || {};
var nodeClone = nodeClone || {};
var prevOnClick = prevOnClick || {};
function nodeHandler (e) {
var x = e.clientX;
var y = e.clientY;
// console.log(x+", "+y);
currentNode = document.elementFromPoint(x, y);
if (currentNode === rootNode || currentNode === document.body){
// If current node is HTML or BODY, do nothing
} else {
if (currentNode === lastNode) {
// If still on same node, do nothing
// console.log('Same node');
} else {
// console.log('Different node');
// if lastNode has classList, check for onclick attribute and remove highlight-element class
if (lastNode.classList) {
// If lastNode had onclick attribute, replace with the untouched value from nodeClone
if (lastNode.getAttribute("onclick") != null) {
prevOnClick = nodeClone.getAttribute("onclick");
lastNode.setAttribute("onclick", prevOnClick);
}
lastNode.classList.remove('highlight-element');
}
// Save currentNode and preserve any inline event (onclick) attributes
nodeClone = currentNode.cloneNode();
// if currentNode has onclick attribute, disable it
if (currentNode.getAttribute("onclick")) {
currentNode.setAttribute("onclick", "return false;");
};
// Add highlight class to currentNode
currentNode.classList.add('highlight-element');
}
// store node
lastNode = currentNode;
}
}
function clickHandler (e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
console.log("Clicked Node:\n");
console.log(nodeClone);
}
function cancelNodeSelect (e) {
if (e.keyCode == 27) {
// if lastNode has classList, check for onclick attribute and remove highlight-element class
if (lastNode.classList) {
if (lastNode.getAttribute("onclick") != null) {
prevOnClick = nodeClone.getAttribute("onclick");
lastNode.setAttribute("onclick", prevOnClick);
}
lastNode.classList.remove('highlight-element');
}
// remove event listeners
document.removeEventListener('click', clickHandler, false);
document.removeEventListener('mousemove', nodeHandler, false);
document.removeEventListener('keyup', cancelNodeSelect, false);
console.log("escape pressed");
};
}
document.addEventListener('click', clickHandler, false);
document.addEventListener('mousemove', nodeHandler, false);
document.addEventListener('keyup', cancelNodeSelect, false);
And the css:
.highlight-element {
background-color: rgba(130, 180, 230, 0.4);
outline: solid 1px #0F4D9A;
box-sizing: border-box;
}
This answer was posted as edits https://stackoverflow.com/revisions/33050714/2 and https://stackoverflow.com/revisions/33050714/3 to the question Highlight Deepest Child DOM Element with Div Overlay when Moused Over in Pure Javascript by the OP g_let under CC BY-SA 3.0.

Show button after selecting text for quoting

How to show a little image after selecting some text when we using the window.getSelection() code?
The most similar thing I found was this How can I position an element next to user text selection? but cant seem to get it to work properly :-s
Being kinda new to this also doesn't help.
Just need some simple code to do it, doesn't matter much where the image shows up, aslong as its near the selected text
-edit-
As I said in comment, the idea is to show a button (thought of image first but a button is better) floating near the selected text (after the selection is made), with link to quote what was selected, and if we clear what was selected the button doesn't show anymore.
And would this be possible by pulling mouse coords when finishing text selection and adding the x,y coords to the style of the button to be shown?
-edit-
got it working just like I wanted, having that coords idea in mind. Found this http://motyar.blogspot.pt/2010/02/get-user-selected-text-with-jquery-and.html and with it I came up with this:
function getSelected() {
if (window.getSelection) {
return window.getSelection();
}
else if (document.getSelection) {
return document.getSelection();
}
else {
var selection = document.selection && document.selection.createRange();
if (selection.text) {
return selection.text;
}
return false;
}
return false;
}
$(document).ready(function() {
var blank = '',
selectionImage;
$('#mensagem').mouseup(function(e) {
var selection = getSelected();
if (!selectionImage) {
selectionImage = $('<button>').attr({
type: 'button',
title: 'Citar Texto seleccionado',
id: 'quote-place'
}).html("Citar").css({
"color": "red"
}).hide();
$(document.body).append(selectionImage);
}
$("#quote-place").click(function quote() {
var txt = '';
if (window.getSelection) {
txt = window.getSelection();
}
else if (document.getSelection) {
txt = document.getSelection();
}
else if (document.selection) {
txt = document.selection.createRange().text;
}
else {
return;
}
document.aform.selectedtext.value = txt;
}).mousedown(function() {
if (selectionImage) {
selectionImage.fadeOut();
}
});
selectionImage.css({
top: e.pageY - 30,
//offsets
left: e.pageX - 13 //offsets
}).fadeIn();
});
});​
http://jsfiddle.net/ordhor/2Gc8c/
The problem now lies on when we click on the <div> without selecting text the button keeps showing. It should only appear when selecting text and I cant find how to fix it...
Let's suppose that image is the image element you want to insert. The idea is to place a place-holder <span> element after the selected text, since we can't compute the position of text nodes. So, we start with this CSS:
.place-holder {position: relative;}
.quote-image {
position: absolute;
top: 0;
left: 0;
}
The place-holder class is for our <span> element, and the position property for the image we want to put in, which is absolutely positioned in order to keep a zero-width <span>.
Now we want to check whether a selection is made or not. Unfortunately, there's no standard event raised when a selection is made. The onselect event is fired only if a selection is made in text fields, and not even when the selection is canceled.
But since the selection is usually made using mouse and keyboard events, we can listen to them and check if a selection is made.
var prevRng;
function checkSelection() {
var s = getSelection(), r = s.rangeCount && s.getRangeAt(0);
if (prevRng) {
if (!r || r.endContainer !== prevRng.endContainer
|| r.endOffset !== prevRng.endOffset) {
// The selection has changed or been cleared
selectionClear();
}
}
if (r) setPlaceHolder(r);
}
document.addEventListener("mouseup", checkSelection);
// mousedown usually clears the selection
document.addEventListener("mousedown", checkSelection);
// You can use the keyboard to extend the selection, or select all (Ctrl+A)
document.addEventListener("keyup", checkSelection);
prevRng is a variable in the function scope to store the selection made. Now we can make our working code:
function setPlaceHolder(range) {
if (range.startContainer === range.endContainer
&& range.startOffset === range.endOffset) {
// The selection is clear
prevRng = null;
return;
}
prevRng = range;
var endc = range.endContainer, span = document.createElement("span");
span.className = "place-holder";
span.appendChild(image);
if (endc.nodeType === Node.TEXT_NODE) { // Node.TEXT_NODE === 3
var p1 = endc.nodeValue.substring(0, range.endOffset),
p2 = endc.nodeValue.substring(range.endOffset);
endc.nodeValue = p1;
if (p2)
endc.parentNode.insertBefore(document.createTextNode(p2),
endc.nextSibling);
}
endc.parentNode.insertBefore(image, endc.nextSibling);
}
function selectionClear() {
if (!prevRng) return;
var endc = prevRng.endContainer;
if (endc.nextSibling.className === "place-holder") {
endc.parentNode.removeChild(endc.nextSibling);
if (endc.nodeType === Node.TEXT_NODE
&& endc.nextSibling.nodeType === Node.TEXT_NODE) {
// Joining previously divided text nodes
endc.nodeValue += endc.nextSibling.nodeValue;
endc.parentNode.removeChild(endc.nextSibling);
}
}
}
Edit: it seems I've misunderstood your question. I thought you wanted to insert the image after the selection... So, you want to know when the selection is actually made?
Edit 2: changed more or less everything to match the request.
For example:
$("div.rte").on("mouseup",function(){ // event binding on the div
if(window.getSelection().toString().length>0) //check length if >0 then only proceed
{
// do processing
}
this should resolve your problem from my understanding of the problem
I have been trying to implement similar functionality , my problem is that the document can be edited as well.
The way of saving the annotation is a challenge, currently Im thinking to save the start and end index of the annotion in the db, when document content changes , using mutation observers , I will calculate the new char count of the annotation and then save again in db
Please let me know are there any other ways of storing and retrieving from db

Z-index doesn't seem to change anything

I am building some custom dropdown controls and the z-index isn't working properly.
// Add the empty class to the container div if no check boxes are checked.
$('.qx-container').each(function ()
{
var container = $(this);
if (!container.find('input[type="checkbox"]').is(':checked'))
{
container.find('.qx-content').text($('.qx-content').attr('empty-message'));
container.find('.qx-content').addClass('qx-empty-content');
}
else
{
handleCheckBoxToggle(container.find('input[type="checkbox"]'));
}
});
// Wire a mouse enter event to the container div. Turns the drop-down list's colors to gray if the slider isn't visible.
$('.qx-container').mouseenter(function ()
{
var container = $(this);
if (!container.find('.qx-slider').is(':visible'))
{
container.find('.qx-container-border-outer').addClass('qx-container-border-outer-hover');
container.find('.qx-container-border-inner').addClass('qx-container-border-inner-hover');
container.find('.qx-container-border-background').addClass('qx-container-border-background-hover');
}
container.data('hoverState', true);
});
// Wire a mouse leave event to the container div. Turns the drop-down list's colors to white if the slider isn't visible and
// sets the container div's empty class if no check boxes are checked.
$('.qx-container').mouseleave(function ()
{
var container = $(this);
if (!container.find('.qx-slider').is(':visible'))
{
container.find('.qx-container-border-outer').removeClass('qx-container-border-outer-hover');
container.find('.qx-container-border-inner').removeClass('qx-container-border-inner-hover');
container.find('.qx-container-border-background').removeClass('qx-container-border-background-hover');
}
if (container.text() == '')
{
container.text($(this).attr('empty-message'));
container.addClass('qx-empty-content');
}
container.data('hoverState', false);
});
// Wire a click event to the content div. Shows or hides the slider and changes the drop-down list's colors based on the slider's visibility.
$('.qx-container-border-outer').click(function ()
{
var outer = $(this);
var inner = $(this).find('.qx-container-border-inner');
var background = $(this).find('.qx-container-border-background');
var container = outer.closest('.qx-container');
var slider = container.find('.qx-slider');
var sliders = $('.qx-container').find('.qx-slider').not(slider);
// Close any other open sliders.
sliders.each(function ()
{
$(this).hide();
var containerDiv = $(this).closest('.qx-container');
var outerBorder = containerDiv.find('.qx-container-border-outer');
var innerBorder = containerDiv.find('.qx-container-border-inner');
var backgroundDiv = containerDiv.find('.qx-container-border-background');
outerBorder.removeClass('qx-container-border-outer-selected');
outerBorder.removeClass('qx-container-border-outer-hover');
innerBorder.removeClass('qx-container-border-inner-selected');
inner.removeClass('qx-container-border-inner-hover');
backgroundDiv.removeClass('qx-container-border-background-selected');
background.removeClass('qx-container-border-background-hover');
});
// Toggle the slider.
slider.slideToggle(50, function ()
{
if (!container.data('hoverState'))
{
outer.removeClass('qx-container-border-outer-hover');
inner.removeClass('qx-container-border-inner-hover');
background.removeClass('qx-container-border-background-hover');
}
if (slider.is(':visible'))
{
outer.addClass('qx-container-border-outer-selected');
inner.addClass('qx-container-border-inner-selected');
background.addClass('qx-container-border-background-selected');
}
else
{
outer.removeClass('qx-container-border-outer-selected');
inner.removeClass('qx-container-border-inner-selected');
background.removeClass('qx-container-border-background-selected');
}
});
});
// Wire a change event to the check boxes. Stores the user's selection in the content element & displays the text of which check box is checked.
$('.qx-slider').find($('input[type="checkbox"]')).click(function (event)
{
event.stopPropagation();
handleCheckBoxToggle($(this));
});
// Wire a mouse enter event to the slider row so the background color changes to gray.
$('.qx-slider-row').mouseenter(function ()
{
$(this).find('td').addClass('qx-slider-cell-hover');
});
// Wire a mouse leave event to the slider row so the background color changes to white.
$('.qx-slider-row').mouseleave(function ()
{
$(this).find('td').removeClass('qx-slider-cell-hover');
});
// Wire a mouse click event to the slider row to toggle the check box's checked attribute.
$('.qx-slider-row').click(function ()
{
var checkBox = $(this).find('input[type="checkbox"]');
checkBox.attr('checked', !checkBox.is(':checked'));
handleCheckBoxToggle(checkBox);
});
// Handles the checked event for each check box.
function handleCheckBoxToggle(checkBox)
{
// Reference to the containing content div.
var content = checkBox.closest('.qx-container').find('.qx-content')
// Holds the checked values (data is associated with the content div).
var checkBoxData = content.data('checkBoxData');
// Reference to all the check boxes in the slider.
var checkBoxes = checkBox.closest('table').find('input[type="checkbox"]');
// Create an array of check box values (associated with the content div) if it doesn't exist.
if (checkBoxData == undefined)
{
checkBoxData = new Array();
checkBoxes.each(function ()
{
checkBoxData[$(this).attr('interest-level-description')] = 0;
});
}
// Store the checked values of each check box.
checkBoxes.each(function ()
{
checkBoxData[$(this).attr('interest-level-description')] = $(this).is(':checked') ? 1 : 0;
});
// Create a commo-delimited string from the checked values.
content.data('checkBoxData', checkBoxData);
var output = '';
for (var property in checkBoxData)
{
if (checkBoxData[property] == 1)
{
output += property + ", ";
}
}
// Remove the trailing comma.
if (output.match(",") != null)
{
output = output.substr(0, output.length - 2);
}
// Set the content text and class based on the checked values.
if (output == '')
{
content.text(content.attr('empty-message'));
content.addClass('qx-empty-content');
}
else
{
content.text(output);
content.removeClass('qx-empty-content');
}
}
http://jsfiddle.net/heray/1/
If you click the items you'll notice the dropdown menu appears behind subsequent dropdowns. I've added z-indexes and position relative to every element I can think of.
Just so you understand how to use z-index, never assign a z-index to something unless you want it to be displayed over top of another element. The best practice is not to define a z-index (especially not assigning a value of 0) until you need to. In your example, the class you have after clicking the button (the actual dropdown) should have a z-index of 1 or greater, and nothing else in your document should have any z-index definition. if you have an element with z-index of 1, and then you put another element in the same physical spot with a z-index of 2 -- the container with the higher z-index will overlap the one's with the lower.
Remove the z-indexes from the dropdowns. Also, what makes you think that setting a z-index of 0 on them will make things better?
Updated fiddle.

Jquery: Blur function does not work with Div tag

I am trying to create a Jquery Tree plugin for my current project. In the plugin, there are 3 compomnents: a text box containing the result selected from the tree , a div containing the tree and a button to show the div. It works fine, except that i cannot make it auto lose the popup div if the tree lose its focus.
Here is the code to create the div
createTree = function() {
$.getJSON(_options.jsonSrc, function(data) {
nDiv = document.createElement("div");
nDiv.id = "divRootAd";
$(nDiv).css('display', 'none');
jsonObj = data["treeJson"];
nUl = document.createElement("ul");
nUl.appendChild(createNode(jsonObj));
nDiv.appendChild(nUl);
$("body").append(nDiv);
//$(nDiv).focus();
repositionDiv();
});
};
repositionDiv = function() {
if ($('#divRootAd').is(':hidden')) {
// get the field position
var sf_pos = $("#txtAdVal").offset();
var sf_top = sf_pos.top;
var sf_left = sf_pos.left;
// get the field size
var sf_height = $("#txtAdVal").height();
// apply the css styles - optimized for Firefox
$("#divRootAd").css("position","absolute");
$("#divRootAd").css("left", sf_left);
$("#divRootAd").css("top", sf_top + sf_height + 5);
$('#divRootAd').show();
$('#divRootAd').blur(function(event){
alert("lose focus");
clearDiv();
});
} else {
clearDiv();
}
};
The line alert("lose focus") does not work when i move the mouse outside the div. Can anyone suggest a solution for this ?
Instead of blur you could use mouseout
$('#divRootAd').mouseout(function(event){
alert("lose focus");
clearDiv();
});
Hope it helps

Categories

Resources