Related
So I have someone who wanted a special class title to use so they could be able to change the padding of a div. I quickly created a class called .columnpadding so they could do this. Later I was asked to make a few more classes so they could change the padding across multiple pages. Instead of having to duplicate the css class over and over and change the padding for each, is there a way I could have the variable changed via the class title.
For example.
If the class title is .columnpadding-100
Is there a way to have a class with its padding at 100px?
My website runs on Php and Less. Let me know if the coding would be too complicated. Im hoping its not something too crazy! Thanks!
So let's presume we have the following basic structure:
div {
border: 1px solid black;
height: 10px;
width: 10px;
}
<div class="columnpadding-50"></div>
<div class="columnpadding-30"></div>
<div class="dontchangeme"></div>
<div class="columnpadding-10"></div>
Using only vanilla JS we can easily achieve the desired result:
var divs = document.querySelectorAll("div[class^='columnpadding-']");
for (let i = 0; i < divs.length; i++){
let psize = divs[i].getAttribute('class');
psize = psize.substring(psize.indexOf('-') +1, psize.length);
divs[i].style.padding = psize + 'px';
}
div {
border: 1px solid black;
height: 10px;
width: 10px;
}
<div class="columnpadding-50"></div>
<div class="columnpadding-30"></div>
<div class="dontchangeme"></div>
<div class="columnpadding-10"></div>
Where we first select all divs containg class with value columnpadding- into a NodeList
Then we retrieve a string of the each class attribute, and substring it from the - to receive the size
Last but not least, we apply style.padding to our selected elements in NodeList
And voilà, produces the expected result!
Use JQuery
CSS - not needed, but here for the example
div {
display: inline-block;
}
HTML
<div class="columnpadding-100">This has 100 padding
</div>
<div class="columnpadding-50">This had 50 padding
</div>
javascript / jQuery
$(document).ready(function(){ // wait until the page is completely loaded
$("[class^='columnpadding-']").each(function(){ // get every element that has a class starting with "columnpadding-"
let classNamesString = $(this).attr('class'); // get the string of class nameS from this element
let classNames = classNamesString.split(" "); // create an array of class names
$.each(classNames, function(index, className){ // loop through the class names looking for the one we want
if (className.startsWith("columnpadding-")) { // hey, this is the one we want
let amount = className.substring(14); // get the amount after the hyphen
$("." + className).css("padding", amount + "px"); // set the css for the padding on the element
}
});
});
});
How can I get windowWidth, windowHeight, pageWidth, pageHeight, screenWidth, screenHeight, pageX, pageY, screenX, screenY which will work in all major browsers?
You can get the size of the window or document with jQuery:
// Size of browser viewport.
$(window).height();
$(window).width();
// Size of HTML document (same as pageHeight/pageWidth in screenshot).
$(document).height();
$(document).width();
For screen size you can use the screen object:
window.screen.height;
window.screen.width;
This has everything you need to know: Get viewport/window size
but in short:
var win = window,
doc = document,
docElem = doc.documentElement,
body = doc.getElementsByTagName('body')[0],
x = win.innerWidth || docElem.clientWidth || body.clientWidth,
y = win.innerHeight|| docElem.clientHeight|| body.clientHeight;
alert(x + ' × ' + y);
Fiddle
Please stop editing this answer. It's been edited 22 times now by different people to match their code format preference. It's also been pointed out that this isn't required if you only want to target modern browsers - if so you only need the following:
const width = window.innerWidth || document.documentElement.clientWidth ||
document.body.clientWidth;
const height = window.innerHeight|| document.documentElement.clientHeight||
document.body.clientHeight;
console.log(width, height);
Here is a cross browser solution with pure JavaScript (Source):
var width = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var height = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
A non-jQuery way to get the available screen dimension. window.screen.width/height has already been put up, but for responsive webdesign and completeness sake I think its worth to mention those attributes:
alert(window.screen.availWidth);
alert(window.screen.availHeight);
http://www.quirksmode.org/dom/w3c_cssom.html#t10 :
availWidth and availHeight - The available width and height on the
screen (excluding OS taskbars and such).
But when we talk about responsive screens and if we want to handle it using jQuery for some reason,
window.innerWidth, window.innerHeight
gives the correct measurement. Even it removes the scroll-bar's extra space and we don't need to worry about adjusting that space :)
Full 2020
I am surprised that question have about 10 years and it looks like so far nobody has given a full answer (with 10 values) yet. So I carefully analyse OP question (especially picture) and have some remarks
center of coordinate system (0,0) is in the viewport (browser window without bars and main borders) top left corner and axes are directed to right and down (what was marked on OP picture) so the values of pageX, pageY, screenX, screenY must be negative (or zero if page is small or not scrolled)
for screenHeight/Width OP wants to count screen height/width including system menu bar (eg. in MacOs) - this is why we NOT use .availWidth/Height (which not count it)
for windowWidth/Height OP don't want to count size of scroll bars so we use .clientWidth/Height
the screenY - in below solution we add to position of top left browser corner (window.screenY) the height of its menu/tabls/url bar). But it is difficult to calculate that value if download-bottom bar appears in browser and/or if developer console is open on page bottom - in that case this value will be increased of size of that bar/console height in below solution. Probably it is impossible to read value of bar/console height to make correction (without some trick like asking user to close that bar/console before measurements...)
pageWidth - in case when pageWidth is smaller than windowWidth we need to manually calculate size of <body> children elements to get this value (we do example calculation in contentWidth in below solution - but in general this can be difficult for that case)
for simplicity I assume that <body> margin=0 - if not then you should consider this values when calculate pageWidth/Height and pageX/Y
function sizes() {
const contentWidth = [...document.body.children].reduce(
(a, el) => Math.max(a, el.getBoundingClientRect().right), 0)
- document.body.getBoundingClientRect().x;
return {
windowWidth: document.documentElement.clientWidth,
windowHeight: document.documentElement.clientHeight,
pageWidth: Math.min(document.body.scrollWidth, contentWidth),
pageHeight: document.body.scrollHeight,
screenWidth: window.screen.width,
screenHeight: window.screen.height,
pageX: document.body.getBoundingClientRect().x,
pageY: document.body.getBoundingClientRect().y,
screenX: -window.screenX,
screenY: -window.screenY - (window.outerHeight-window.innerHeight),
}
}
// TEST
function show() {
console.log(sizes());
}
body { margin: 0 }
.box { width: 3000px; height: 4000px; background: red; }
<div class="box">
CAUTION: stackoverflow snippet gives wrong values for screenX-Y,
but if you copy this code to your page directly the values will be right<br>
<button onclick="show()" style="">CALC</button>
</div>
I test it on Chrome 83.0, Safari 13.1, Firefox 77.0 and Edge 83.0 on MacOs High Sierra
Graphical answer:
(............)
function wndsize(){
var w = 0;var h = 0;
//IE
if(!window.innerWidth){
if(!(document.documentElement.clientWidth == 0)){
//strict mode
w = document.documentElement.clientWidth;h = document.documentElement.clientHeight;
} else{
//quirks mode
w = document.body.clientWidth;h = document.body.clientHeight;
}
} else {
//w3c
w = window.innerWidth;h = window.innerHeight;
}
return {width:w,height:h};
}
function wndcent(){
var hWnd = (arguments[0] != null) ? arguments[0] : {width:0,height:0};
var _x = 0;var _y = 0;var offsetX = 0;var offsetY = 0;
//IE
if(!window.pageYOffset){
//strict mode
if(!(document.documentElement.scrollTop == 0)){offsetY = document.documentElement.scrollTop;offsetX = document.documentElement.scrollLeft;}
//quirks mode
else{offsetY = document.body.scrollTop;offsetX = document.body.scrollLeft;}}
//w3c
else{offsetX = window.pageXOffset;offsetY = window.pageYOffset;}_x = ((wndsize().width-hWnd.width)/2)+offsetX;_y = ((wndsize().height-hWnd.height)/2)+offsetY;
return{x:_x,y:_y};
}
var center = wndcent({width:350,height:350});
document.write(center.x+';<br>');
document.write(center.y+';<br>');
document.write('<DIV align="center" id="rich_ad" style="Z-INDEX: 10; left:'+center.x+'px;WIDTH: 350px; POSITION: absolute; TOP: '+center.y+'px; HEIGHT: 350px"><!--К сожалению, у Вас не установлен flash плеер.--></div>');
You can also get the WINDOW width and height, avoiding browser toolbars and other stuff. It is the real usable area in browser's window.
To do this, use:
window.innerWidth and window.innerHeight properties (see doc at w3schools).
In most cases it will be the best way, in example, to display a perfectly centred floating modal dialog. It allows you to calculate positions on window, no matter which resolution orientation or window size is using the browser.
To check height and width of your current loaded page of any website using "console" or after clicking "Inspect".
step 1: Click the right button of mouse and click on 'Inspect' and then click 'console'
step 2: Make sure that your browser screen should be not in 'maximize' mode. If the browser screen is in 'maximize' mode, you need to first click the maximize button (present either at right or left top corner) and un-maximize it.
step 3: Now, write the following after the greater than sign ('>') i.e.
> window.innerWidth
output : your present window width in px (say 749)
> window.innerHeight
output : your present window height in px (say 359)
Complete guide related to Screen sizes
JavaScript
For height:
document.body.clientHeight // Inner height of the HTML document body, including padding
// but not the horizontal scrollbar height, border, or margin
screen.height // Device screen height (i.e. all physically visible stuff)
screen.availHeight // Device screen height minus the operating system taskbar (if present)
window.innerHeight // The current document's viewport height, minus taskbars, etc.
window.outerHeight // Height the current window visibly takes up on screen
// (including taskbars, menus, etc.)
Note: When the window is maximized this will equal screen.availHeight
For width:
document.body.clientWidth // Full width of the HTML page as coded, minus the vertical scroll bar
screen.width // Device screen width (i.e. all physically visible stuff)
screen.availWidth // Device screen width, minus the operating system taskbar (if present)
window.innerWidth // The browser viewport width (including vertical scroll bar, includes padding but not border or margin)
window.outerWidth // The outer window width (including vertical scroll bar,
// toolbars, etc., includes padding and border but not margin)
Jquery
For height:
$(document).height() // Full height of the HTML page, including content you have to
// scroll to see
$(window).height() // The current document's viewport height, minus taskbars, etc.
$(window).innerHeight() // The current document's viewport height, minus taskbars, etc.
$(window).outerHeight() // The current document's viewport height, minus taskbars, etc.
For width:
$(document).width() // The browser viewport width, minus the vertical scroll bar
$(window).width() // The browser viewport width (minus the vertical scroll bar)
$(window).innerWidth() // The browser viewport width (minus the vertical scroll bar)
$(window).outerWidth() // The browser viewport width (minus the vertical scroll bar)
Reference: https://help.optimizely.com/Build_Campaigns_and_Experiments/Use_screen_measurements_to_design_for_responsive_breakpoints
With the introduction of globalThis in ES2020 you can use properties like.
For screen size:
globalThis.screen.availWidth
globalThis.screen.availHeight
For Window Size
globalThis.outerWidth
globalThis.outerHeight
For Offset:
globalThis.pageXOffset
globalThis.pageYOffset
...& so on.
alert("Screen Width: "+ globalThis.screen.availWidth +"\nScreen Height: "+ globalThis.screen.availHeight)
If you need a truly bulletproof solution for the document width and height (the pageWidth and pageHeight in the picture), you might want to consider using a plugin of mine, jQuery.documentSize.
It has just one purpose: to always return the correct document size, even in scenarios when jQuery and other methods fail. Despite its name, you don't necessarily have to use jQuery – it is written in vanilla Javascript and works without jQuery, too.
Usage:
var w = $.documentWidth(),
h = $.documentHeight();
for the global document. For other documents, e.g. in an embedded iframe you have access to, pass the document as a parameter:
var w = $.documentWidth( myIframe.contentDocument ),
h = $.documentHeight( myIframe.contentDocument );
Update: now for window dimensions, too
Ever since version 1.1.0, jQuery.documentSize also handles window dimensions.
That is necessary because
$( window ).height() is buggy in iOS, to the point of being useless
$( window ).width() and $( window ).height() are unreliable on mobile because they don't handle the effects of mobile zooming.
jQuery.documentSize provides $.windowWidth() and $.windowHeight(), which solve these issues. For more, please check out the documentation.
I wrote a small javascript bookmarklet you can use to display the size. You can easily add it to your browser and whenever you click it you will see the size in the right corner of your browser window.
Here you find information how to use a bookmarklet
https://en.wikipedia.org/wiki/Bookmarklet
Bookmarklet
javascript:(function(){!function(){var i,n,e;return n=function(){var n,e,t;return t="background-color:azure; padding:1rem; position:fixed; right: 0; z-index:9999; font-size: 1.2rem;",n=i('<div style="'+t+'"></div>'),e=function(){return'<p style="margin:0;">width: '+i(window).width()+" height: "+i(window).height()+"</p>"},n.html(e()),i("body").prepend(n),i(window).resize(function(){n.html(e())})},(i=window.jQuery)?(i=window.jQuery,n()):(e=document.createElement("script"),e.src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js",e.onload=n,document.body.appendChild(e))}()}).call(this);
Original Code
The original code is in coffee:
(->
addWindowSize = ()->
style = 'background-color:azure; padding:1rem; position:fixed; right: 0; z-index:9999; font-size: 1.2rem;'
$windowSize = $('<div style="' + style + '"></div>')
getWindowSize = ->
'<p style="margin:0;">width: ' + $(window).width() + ' height: ' + $(window).height() + '</p>'
$windowSize.html getWindowSize()
$('body').prepend $windowSize
$(window).resize ->
$windowSize.html getWindowSize()
return
if !($ = window.jQuery)
# typeof jQuery=='undefined' works too
script = document.createElement('script')
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'
script.onload = addWindowSize
document.body.appendChild script
else
$ = window.jQuery
addWindowSize()
)()
Basically the code is prepending a small div which updates when you resize your window.
In some cases related with responsive layout $(document).height() can return wrong data that displays view port height only.
For example when some div#wrapper has height:100%, that #wrapper can be stretched by some block inside it. But it's height still will be like viewport height. In such situation you might use
$('#wrapper').get(0).scrollHeight
That represents actual size of wrapper.
I developed a library for knowing the real viewport size for desktops and mobiles browsers, because viewport sizes are inconsistents across devices and cannot rely on all the answers of that post (according to all the research I made about this) : https://github.com/pyrsmk/W
Sometimes you need to see the width/height changes while resizing the window and inner content.
For that I've written a little script that adds a log box that dynamicly monitors all the resizing and almost immediatly updates.
It adds a valid HTML with fixed position and high z-index, but is small enough, so you can:
use it on an actual site
use it for testing mobile/responsive
views
Tested on: Chrome 40, IE11, but it is highly possible to work on other/older browsers too ... :)
function gebID(id){ return document.getElementById(id); }
function gebTN(tagName, parentEl){
if( typeof parentEl == "undefined" ) var parentEl = document;
return parentEl.getElementsByTagName(tagName);
}
function setStyleToTags(parentEl, tagName, styleString){
var tags = gebTN(tagName, parentEl);
for( var i = 0; i<tags.length; i++ ) tags[i].setAttribute('style', styleString);
}
function testSizes(){
gebID( 'screen.Width' ).innerHTML = screen.width;
gebID( 'screen.Height' ).innerHTML = screen.height;
gebID( 'window.Width' ).innerHTML = window.innerWidth;
gebID( 'window.Height' ).innerHTML = window.innerHeight;
gebID( 'documentElement.Width' ).innerHTML = document.documentElement.clientWidth;
gebID( 'documentElement.Height' ).innerHTML = document.documentElement.clientHeight;
gebID( 'body.Width' ).innerHTML = gebTN("body")[0].clientWidth;
gebID( 'body.Height' ).innerHTML = gebTN("body")[0].clientHeight;
}
var table = document.createElement('table');
table.innerHTML =
"<tr><th>SOURCE</th><th>WIDTH</th><th>x</th><th>HEIGHT</th></tr>"
+"<tr><td>screen</td><td id='screen.Width' /><td>x</td><td id='screen.Height' /></tr>"
+"<tr><td>window</td><td id='window.Width' /><td>x</td><td id='window.Height' /></tr>"
+"<tr><td>document<br>.documentElement</td><td id='documentElement.Width' /><td>x</td><td id='documentElement.Height' /></tr>"
+"<tr><td>document.body</td><td id='body.Width' /><td>x</td><td id='body.Height' /></tr>"
;
gebTN("body")[0].appendChild( table );
table.setAttribute(
'style',
"border: 2px solid black !important; position: fixed !important;"
+"left: 50% !important; top: 0px !important; padding:10px !important;"
+"width: 150px !important; font-size:18px; !important"
+"white-space: pre !important; font-family: monospace !important;"
+"z-index: 9999 !important;background: white !important;"
);
setStyleToTags(table, "td", "color: black !important; border: none !important; padding: 5px !important; text-align:center !important;");
setStyleToTags(table, "th", "color: black !important; border: none !important; padding: 5px !important; text-align:center !important;");
table.style.setProperty( 'margin-left', '-'+( table.clientWidth / 2 )+'px' );
setInterval( testSizes, 200 );
EDIT: Now styles are applied only to logger table element - not to all tables - also this is a jQuery-free solution :)
You can use the Screen object to get this.
The following is an example of what it would return:
Screen {
availWidth: 1920,
availHeight: 1040,
width: 1920,
height: 1080,
colorDepth: 24,
pixelDepth: 24,
top: 414,
left: 1920,
availTop: 414,
availLeft: 1920
}
To get your screenWidth variable, just use screen.width, same with screenHeight, you would just use screen.height.
To get your window width and height, it would be screen.availWidth or screen.availHeight respectively.
For the pageX and pageY variables, use window.screenX or Y. Note that this is from the VERY LEFT/TOP OF YOUR LEFT/TOP-est SCREEN. So if you have two screens of width 1920 then a window 500px from the left of the right screen would have an X value of 2420 (1920+500). screen.width/height, however, display the CURRENT screen's width or height.
To get the width and height of your page, use jQuery's $(window).height() or $(window).width().
Again using jQuery, use $("html").offset().top and $("html").offset().left for your pageX and pageY values.
here is my solution!
// innerWidth
const screen_viewport_inner = () => {
let w = window,
i = `inner`;
if (!(`innerWidth` in window)) {
i = `client`;
w = document.documentElement || document.body;
}
return {
width: w[`${i}Width`],
height: w[`${i}Height`]
}
};
// outerWidth
const screen_viewport_outer = () => {
let w = window,
o = `outer`;
if (!(`outerWidth` in window)) {
o = `client`;
w = document.documentElement || document.body;
}
return {
width: w[`${o}Width`],
height: w[`${o}Height`]
}
};
// style
const console_color = `
color: rgba(0,255,0,0.7);
font-size: 1.5rem;
border: 1px solid red;
`;
// testing
const test = () => {
let i_obj = screen_viewport_inner();
console.log(`%c screen_viewport_inner = \n`, console_color, JSON.stringify(i_obj, null, 4));
let o_obj = screen_viewport_outer();
console.log(`%c screen_viewport_outer = \n`, console_color, JSON.stringify(o_obj, null, 4));
};
// IIFE
(() => {
test();
})();
This how I managed to get the screen width in React JS Project:
If width is equal to 1680 then return 570 else return 200
var screenWidth = window.screen.availWidth;
<Label style={{ width: screenWidth == "1680" ? 570 : 200, color: "transparent" }}>a </Label>
Screen.availWidth
I am working on an application that involves getting the entire page content from a page using javascript and dumping the html to the database.On the page I have various components that will be parsed and stored using a ajax request.I do it like this.
function saveContent(){
var $getContent = $('#mainWrap').clone();
$getContent.find('.textBox, .pictureBox').removeAttr('id');
var saveContent = $getContent.wrap('<div></div>').html();
var getBodyStyle=$('body').attr('style');
var auto="auto";
$.ajax({
url:"save.php",
type:"POST",
dataType:"text",
data:"txtComp="+saveContent+"&auto="+auto+"&pageId="+pageId+"&webId="+webId+"&userId="+userId+"&bodyStyle="+getBodyStyle,
success:function(data){
var options = {"text":data,"layout":"topCenter","type":"success","animateOpen": {"opacity": "show"}};
setTimeout(function(){noty(options)}, 1000);
//$('#draftMsg').html(data).fadeIn(500);
}
});
}
Now I have social media components like facebook,twitter.When I try to save the facebook component it is not save entirely as it contains some parameters that are present in the script with '&'.
<div style="z-index: 1001; height: 560px; width: 413px; top: -20px; left: 121.5px;" id="com-IADDFSGNHLU7WNR3WM2KC3I8DA2DOIC6" class="facebookBox contentBox boxStyle">
<div class="blankDiv"></div>
<iframe class="facebookBoxObject" allowtransparency="true" style="border: medium none; overflow: hidden; height: 560px; width: 413px;" src="https://www.facebook.com/plugins/likebox.php?api_key=117096311791424&locale=en_US&height=560&header=true&show_faces=true&stream=true&width=413&href=http://www.facebook.com/cbil360" frameborder="0" scrolling="no">
</iframe>
</div>
The above is the content I want to store to the database and I get it when I say console.log but in the database it stores only the below content
<div style="z-index: 1001; height: 388px; width: 283px; top: -20px; left: 120.5px;" id="com-IADDFSGNHLU7WNR3WM2KC3I8DA2DOIC6" class="facebookBox contentBox boxStyle">
<div class="blankDiv"></div><iframe class="facebookBoxObject" allowtransparency="true" style="border: medium none; overflow: hidden; height: 388px; width: 283px;" src="https://www.facebook.com/plugins/likebox.php?api_key=117096311791424
It breaks after the api_key parameter as it has & after that.I am not asure as I don't get any error for this.Tried to debug but,not to a conclusion yet.
Please correct where am I going wrong.
Update: The query I am using is
$query = "insert into tbl_revision (userId,revisionContent,webId,pageId,status,saveType,dateAdded) values ('".$_SESSION['UserId']."','$revisionContent','$webId','$pageId','$status','$saveType','$toDate')"
I really doubt that the problem is happening before the data reaches your backend. It's happening on the front end because you are including a & as a normal character in your query string which causes some confusion. What I recommend is either you URL encode your saveContent variable (URL encode not HTML encode).
encodeURIComponent(saveContent) //that will replace the & with it's corresponding url encoding
There is also another workaround, you could submit the ajax request fields using the json form provided by jquery $.ajax. An example of that would be
$.ajax({
url:"save.php",
type:"POST",
dataType:"text",
data:{txtComp: saveContent, auto: auto }, //etc
success:function(data){
var options = {"text":data,"layout":"topCenter","type":"success","animateOpen": {"opacity": "show"}};
setTimeout(function(){noty(options)}, 1000);
//$('#draftMsg').html(data).fadeIn(500);
}
});
I also recommend that you have a look on that question to know the difference betweeen URL Encoding and HTML Encoding
Difference between Url Encode and HTML encode
Have you tried to encoded the input string and decoded the output string with htmlentities and html_entity_decode?
i have created a arraylist in php
It is place in a button . When i click on it opens the button, it opens all the aaraylist but there is some problem with the code the link to,the code is here.can someone tell me where is the problem.
var Arraylist<String> = new Arraylist<String>;
The problem is that any click will immediately hide the dropdown, after which you make it visible again by toggling it.
I'm trying to edit you fiddle to try and get it to work the way you want :).
Edit: here is a fiddle that does what I think you want it to do: fiddle
The idea I got from your fiddle is that you want to toggle the menu when you click it, and if you click anywhere else, the menu is hidden by default.
This works by remembering if the item was toggled or not, if not, it'll hide by default.
var nav = $('#nav');
nav.find('ul#nav').toggle();
var emp = $(this);
$("html").click(function() {});
$(document).bind('click', function(e) {
var dd = $("ul.dropdown");
var toggled = false;
var target = $(e.target); //2
if (target.parent().is('#nav')) {
var li = target.closest('li.menu');
toggled = true;
li.find('ul.dropdown').toggle();
}
if (!toggled) {
dd.hide();
}
});
OK, let's tackle all the problems with your code.
I'll explain what you're doing wrong and why, and what is recommended.
First up:
HTML Markup.
Your included example code contains markup errors. You're closing one of your list items inside the nested unordered list after the nested unordered list. Minor, but yet important for valid markup. Some browsers can go nuts over these things.
The second thing I noticed was that you're using the same ID for the lists. An ID is unique to the document in order to quickly reference it in CSS and Javascript. If you intend to select more than one element in the document, use classes, that's what they're there for. You can read more about it here or here.
Depending on what intended use you have for it; to achieve the same desired result, consider using this markup instead
<div class='emp_alt'>
<div class='container'>
<div class='title'>EMP</div>
<img src="http://www.iconarchive.com/download/i32215/tpdkdesign.net/refresh-cl/Symbols-Find.ico">
</div>
<div class='dropdown'>Contact no.</div>
</div>
Generally speaking, it requires less processing time for the client the less elements you have. When you apply CSS to the elements it is highly recommended to select them by class or ID, not by tag name. Using tag names can take up extra processing time because the client has to do more generalized searches. You can read more about efficient CSS here.
Here's a working example with your corrected markup.
Here's a working example using the alternate markup.
I'm not sure if you're trying to accomplish a sort of tooltip behavior, in which case, this example should suit you.
The JQuery (Javascript)
The other answers rightly pointed out your main problem was that you were hiding the dropdown on click. What they didn't address was that when the user clicks on something, and your document click picks up on it, it's going to return the element that is in the front.
So, when you click on the text, the #nav element is in the front. The image however, is an element in its own, and is in front of the #nav element.
This is why you should use the proper events instead because they include everything inside the element.
As you may have noticed in my examples above, there is a faster, cleaner and better way of achieving what you want.
You should be doing something like this instead
var dropdowns = $(".dropdown");
$(".nav > li").click(function(e){
//Prevent document click event from firing
e.stopPropagation();
var this_dropdown = $(this).children("ul.dropdown");
dropdowns.not(this_dropdown).hide();
this_dropdown.toggle();
});
//Hide all dropdowns if not clicked on a list item (or container)
$(document).click(function(){
dropdowns.hide();
});
Note: if you don't want to stop propagation you can use a "sensor" instead. Basically, a sensor determines a boolean's state which is then used to determine if the document click event should do anything or not. An if statement checking the boolean's state at document click should suffice.
var dropdowns = $(".dropdown");
var sensor_state = true;
$(".nav > li").click(function(e){
var this_dropdown = $(this).children("ul.dropdown");
dropdowns.not(this_dropdown).hide();
this_dropdown.toggle();
}).mouseenter(function(){
sensor_state = false;
}).mouseleave(function(){
sensor_state = true;
});
$(document).click(function(){
if(sensor_state){
dropdowns.hide();
}
});
This relies on the markup where the nav element has a dropdown child.
Here's an example using your example.
The problem here is that your markup makes this code toggle the dropdown when it itself is clicked. That's why I added a container to the earlier examples.
Hopefully, I've made at least some sense and cleared up your problem.
Update
After your latest comments, indicating you're using jqgrid and you want a dropdown inside, I decided to create a rather thorough example of how it can be done.
I suggest you study the code and learn from it. You don't have to do exactly as I did, as long as you know how and why.
Functionality:
When a user clicks a contact cell in the jqgrid it will show the dropdown container and the data provided from the "server" (custom array data is easier than staging an ajax event). The data provided by the server is in a hidden column (following the contact column)
If you click inside the dropdown container, it will not close. I added a close button inside it because users might otherwise get confused as to how to close it. It's better to have one than not to have one
If you click anywhere else in the document, it will close
If the user clicks the same cell while the dropdown container is visible, it will close
The dropdown container is not attached to the cell itself, but is instead positioned from the outside. This allows us to reuse the same container, instead of creating new containers for every single cell, saving us time in the process.
This is as far as writing your code I'm willing to go. The rest is up to you mate :)
I am reluctant to add more text to this post, but for completeness sake, I will add the entirety of the example code.
Code | JSFiddle Example
HTML
<link rel="stylesheet" type="text/css" media="screen" href="http://trirand.com/blog/jqgrid/themes/redmond/jquery-ui-custom.css" />
<link rel="stylesheet" type="text/css" media="screen" href="http://trirand.com/blog/jqgrid/themes/ui.jqgrid.css" />
<link rel="stylesheet" type="text/css" media="screen" href="http://trirand.com/blog/jqgrid/themes/ui.multiselect.css" />
<script src="http://trirand.com/blog/jqgrid/js/jquery.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/jquery-ui-custom.min.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/jquery.layout.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/i18n/grid.locale-en.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/ui.multiselect.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/jquery.jqGrid.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/jquery.tablednd.js" type="text/javascript"></script>
<script src="http://trirand.com/blog/jqgrid/js/jquery.contextmenu.js" type="text/javascript"></script>
<table id="list"></table>
<div id="pager"></div>
<div id="contact_info"></div>
CSS
#contact_info{
position: absolute;
top: 0;
left: 0;
display:none;
background-color: white;
border: 1px solid gray;
padding: 5px 3px;
-moz-box-shadow: 3px 3px 4px #CCC;
-webkit-box-shadow: 3px 3px 4px #CCC;
box-shadow: 3px 3px 4px #CCC;
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#CCCCCC')";
}
#list .contact{
cursor: pointer;
}
.container{
cursor: pointer;
}
td.contact:active{
background-color: #FBEC88;
}
.container .dropdown{
display: none;
}
.ui-jqgrid tr.jqgrow td{
white-space: normal;
}
/*
Style the dropdown box
*/
h2{
border-bottom: 1px solid lightgray;
}
p{
padding: 2px;
}
h2, p{
margin: 0;
}
.close_btn{
font-size: 10px;
line-height: 10px;
float: right;
text-decoration: none;
}
Javascript
//Preload the image to avoid flashes
search_img= new Image();
search_img.src = "http://www.iconarchive.com/download/i32215/tpdkdesign.net/refresh-cl/Symbols-Find.ico";
//The dropdown container
var contact_info = $("#contact_info");
//ID of last clicked row
var last_row;
//Sensor state determining whether document click will close the dropdown container on click
var sensor_state = true;
//Dropdown information data (base)
var dd_bp = "<img src='"+search_img.src+"'>",
dd_inf = "<h2>Contact information</h2><p>Phone: 555-12345<br/>E-mail: something#someplace.whatever<br/>P/O Box: 555555</p>"
//Data array (don't know what you use as a source, but I'll keep it simple)
//This setup allows you to send dropdown data from the server as well :)
var data_from_server = [
{id:"1",title:"Economy advisor",name:"Luke",lname:"North", contact: dd_bp, dropdown: dd_inf},
{id:"2",title:"Salesperson",name:"John",lname:"Smith",contact: dd_bp, dropdown: dd_inf},
{id:"3",title:"Economy advisor",name:"Jimmy",lname:"Hendrix",contact: dd_bp, dropdown: dd_inf},
{id:"6",title:"IT Manager",name:"Caroline",lname:"GlaDos",contact: dd_bp, dropdown: dd_inf},
{id:"5",title:"Quality Inspector",name:"Paul",lname:"Shoreman",contact: dd_bp, dropdown: dd_inf},
{id:"4",title:"Quality Inspector",name:"Liza",lname:"Ingridge",contact: dd_bp, dropdown: dd_inf},
{id:"8",title:"Distribution manager",name:"Elisabeth",lname:"Welman",contact: dd_bp, dropdown: dd_inf},
{id:"10",title:"Quality Inspector",name:"John",lname:"Johansson",contact: dd_bp, dropdown: dd_inf},
{id:"11",title:"Economy advisor",name:"Tommy",lname:"the Knuckle",contact: dd_bp, dropdown: dd_inf},
{id:"9",title:"Manufacturer",name:"Rosa",lname:"Minx",contact: dd_bp, dropdown: dd_inf}
];
//Adds the content to and repositions the dropdown container to the current row cell
function show_contact_info(rowid){
var row = $("#"+rowid),
contact_cell = $("td.contact", row),
dropdown_content = $("td.dropdown", row).html();
//Add the content
contact_info.html(dropdown_content).append("<a class='close_btn' href='#'>close</a>");
//Add a close button event
$(".close_btn").on("click", function(e){
e.preventDefault();
contact_info.hide();
});
//Position the contact info box
contact_info.css({
//The last calculations will center the container
left: contact_cell.offset().left - contact_info.outerWidth()/2 + contact_cell.outerWidth()/2,
//The last calculation will position the container below the cell, replace it with
// -contact_info.outerHeight() to position it above the cell
top: contact_cell.offset().top + contact_cell.outerHeight(),
});
contact_info.show();
}
function sensor_enter(){sensor_state = false;}
function sensor_leave(){sensor_state = true;}
function add_sensor(element){
element
.on("mouseenter", sensor_enter)
.on("mouseleave", sensor_leave);
}
//Setup jqgrid
$("#list").jqGrid({
datatype: "local",
width: 600,
colNames:['EID', 'Title','First name', 'Last name', 'Contact', "Dropdown"],
colModel:[
{name:'id',index:'id', width:20, sorttype:"int"},
{name:'title',index:'title', width:90},
{name:'name',index:'name', width:50, align:"left"},
{name:'lname',index:'lname', width:50, align:"left"},
{name:'contact',index:'contact', width:25, align:"center", classes:'contact'},
{name:'dropdown', index:'dropdown', hidden:true, classes:'dropdown'}
],
rowNum:10,
rowList:[5,10,15],
pager: '#pager',
viewrecords: true,
caption:"Employees",
onSelectRow: function(rowid, status, e){
var row = $("#"+rowid)
//"Hide" selection so that cell selection looks "cooler" :)
row.attr("class", "ui-widget-content jqgrow ui-row-ltr ui-state-hover");
},
onCellSelect: function(rowid, iCol, cellcontent, e){
if(iCol == 4){
if(last_row == rowid){
if(contact_info.is(":hidden")){
show_contact_info(rowid);
}else{
contact_info.hide();
}
}else{
show_contact_info(rowid);
}
last_row = rowid;
}
},
idPrefix: "emp_",
gridComplete: function(){
//Because the content is dynamic, we need to add it after the grid has finished
//This should be done for server generated content, ie the loadComplete event for server requests
add_sensor($("tr td.contact"));
}
});
$("#list").jqGrid('navGrid','#pager',{edit:false,add:false,del:false});
for(var i=0;i<=data_from_server.length;i++){
$("#list").jqGrid('addRowData',i+1,data_from_server[i]);
}
//Sensor for the dropdown container
add_sensor($("#contact_info"));
//Hide contact info on document click
$(document).click(function(){
if(sensor_state){
contact_info.hide();
}
});
Here is what it should look like
Here are all the references
Why must the ID attribute be unique on each page?
Using Classname (class) and ID in HTML
Writing efficient CSS
The difference between "return false;" and "e.preventDefault();"
return false vs e.stopPropagation();
.click
.children
.not
.on()
.offset()
.outerWidth()
.outerHeight()
jqGrid
jqGrid events
You just need to get rid of the additional hide() as you are hiding then toggling, overriding your toggle.
See this for instance with it working
http://jsfiddle.net/RxJer/11/
var nav = $('#nav');
nav.find('ul#nav').toggle();
var emp = $(this);
$("html").click(function() {});
$(document).bind('click', function(e) {
var target = $(e.target); //2
var dropdown = target.parents('#nav').find('li.menu ul.dropdown');
dropdown.toggle();
});
Try this:
$(document).bind('click', function(e) {
var target = $(e.target); //2
if (target.parent().is('#nav') || target.parent().is('.menu')) {
var li = target.closest('li.menu');
var dd = li.find('ul.dropdown');
var isVis = dd.is(':visible');
$("ul.dropdown").hide();
(isVis) ? dd.hide() : dd.show();
} else {
$("ul.dropdown").hide();
}
});
I've been looking through SO and Google trying to find a simple way to overlay a busy icon on an existing image. While applying filters and effects to images I'd like to let the user know it's being processed by showing a busy icon on top of the current image.
Do I need to create some sort of overlay image that I show at the start of the process and hide after it's complete using jquery?
Just looking for some ideas from people that might have done this already.
As #Diodeus said, ideally you'd have a wrapper around the image so the issue of positioning the loading image is trivial relative to the image.
If a wrapper is not an option (i.e. you're working with existing, unchangeable mark-up, or wrappers would break your CSS en-masse, it's not the end of the world. You can just plonk the icon over the image, taking advantage of the fact that jQuery makes it easy to get an element's coordinates relative to the body, not only its relative parent/ancestor.
HTML (put this directly in the body, not nested)
<img src='loading.png' id='loading' />
CSS
#loading { position: absolute; display: none; /* other styles, BG img etc */ }
JavaScript (el is the page element concerned)
var loading_img = $('#loading');
function func_called_when_stuff_happening(el) {
var el_coords = $(el).offset();
loading_img.show().css({
left: el_coords.left + (($(el).width() / 2) - (loading_img.width() / 2)),
top: el_coords.top + (($(el).height() / 2) - (loading_img.height() / 2)),
});
}
That will put the icon in the middle of the element.
Generally you absolutely-position an image over the content, in this case your image. You should use a wrapping element like this to get the positioning to work:
<div class="hasLoader">
<img src="...your image..." />
<img class="loading" src="...your LOADING image..." />
</div>
CSS:
.hasLoader {
position:relative;
}
.loading {
position:absolute;
top:0;
left:0;
}
If you need a good loading image, AjaxLoad has a good generator.
Look at this : http://jsfiddle.net/dystroy/M3AnJ/
After 2 seconds an overlay appears, exactly covering the image, with a spinner at center.
Here's how I do it :
javascript :
setTimeout(function(){
var o = $('<div id=overlay></div>');
o.prependTo('body');
var img = $('#test');
var pos = img.offset();
o.css({left:pos.left, top:pos.top, width:img.width(), height:img.height()});
}, 2000);
CSS :
#overlay {
position: fixed;
background-color:rgba(100,100,100,0.5);
background-image: url("http://dystroy.org/loading.gif");
background-position:center;
background-repeat:no-repeat;
};
I would create a transparent GIF and absolutely position it over the target image w/ JavaScript:
var targetImage = document.getElementById("targImgID");
var ovrlay = document.createElement("IMG");
ovrlay.src = "\my\image\url\overlay.gif";
ovrlay.style.position = "absolute";
ovrlay.style.left = targetImage.offsetLeft + "px";
ovrlay.style.top = targetImage.offsetTop + "px";
document.body.appendChild(ovrlay);
This is prototype code that hasn't been debugged, and leaves out some stuff like getting the absolute position of the target image, centering and setting a z-index for the overlay, and removing the thing w/ removeChild, but it's where I'd start.