I am writing a simple jQuery plugin for my purpose, which:
creates a background div (for blocking purposes, like a modal dialog). (referenced with backDiv)
shows that background.
shows $(this).
removes background and hides $(this) when background clicked.
I am able to do all of these except 4th one: As I can't save a reference to the background div, I cannot get it back and remove it.
I tried $(this).data('backDiv',backDiv); and $(this)[0].backDiv = backDiv;
I know that there are various plugins that does this including the jQuery's own dialog function, but I want to create my own version.
I cannot keep this variable globally, so, how can I keep a reference to backDiv in a jQuery object, (or DOM object?) if that's even possible at all?
update: I allow multiple of these elements show on top of each other: Nested modal dialogs.
update-2:
(function($) {
$.fn.showModal = function() {
var backDiv = $('<div style="width: 100%; height: 100%; background-color: rgba(55, 55, 55, 0.5); position:absolute;top:0px;left:0px;">This is backDiv</div>');
$(this).data('backDiv', backDiv);
$('body').append(backDiv);
//TODO: bringToFront(backDiv);
$(this).show();
//TODO: bringToFront($(this);
var thisRef = $(this);
backDiv.click(function() {
thisRef.closeModal();
});
return $(this);
};
$.fn.closeModal = function() {
//PROBLEM (null): var backDiv = $(this).data('backDiv');
//backDiv.remove();
$(this).data('backDiv', '');
$(this).hide();
}
}(jQuery));
$(document).ready(function() {
$('#a').showModal();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="a" style="display:none;z-Index:2;background:red; width: 100px; height:50px;position:absolute"></div>
I suggest you to work in terms of complex dom objects, something similar angular directives, basically, you have to work with components that are represented in the dom as Group of Objects.
So, following what I'm saying, your modal component should be something like that:
var Modal = (function($) {
var tpl = '<div style="display:none;" class="modal"><div class="modal-backdrop"></div><div class="modal-content"></div></div>';
function Modal(container) {
var self = this;
this.container = $(container || 'body');
this.tpl = $(tpl).appendTo(this.container);
this.content = $('.modal-content', this.tpl);
this.backdrop = $('.modal-backdrop', this.tpl);
this.isOpened = false;
this.ANIMATION_DURATION = 500;
this.backdrop.click(function(e) { self.toggle(e) });
}
Modal.prototype.show = function(cb) {
var self = this;
cb = $.isFunction(cb) ? cb : $.noop;
this.tpl.fadeIn(this.ANIMATION_DURATION, function() {
self.isOpened = true;
cb();
});
return this;
};
Modal.prototype.hide = function(cb) {
var self = this;
cb = $.isFunction(cb) ? cb : $.noop;
this.tpl.fadeOut(this.ANIMATION_DURATION, function() {
self.isOpened = false;
cb();
});
return this;
};
Modal.prototype.toggle = function() {
if(this.isOpened) {
return this.hide();
}
return this.show();
};
Modal.prototype.setContent = function(content) {
this.content.html($('<div />').append(content).html());
return this;
};
return Modal;
})(window.jQuery);
function ExampleCtrl($) {
var modal = new Modal();
modal.setContent('<h1>Hello World</h1>');
$('#test').click(function() {
modal.show();
});
}
window.jQuery(document).ready(ExampleCtrl);
.modal {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.modal .modal-backdrop {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, .8);
}
.modal .modal-content {
width: 300px;
height: 150px;
background: #fff;
border: 1px solid yellow;
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px;
margin-top: -75px;
line-height: 150px;
text-align: center;
}
h1 {
line-height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="test">Test Modal</button>
Add data-backDiv="" into you dynamic modal div
Change below
var backDiv = $('<div data-backDiv="" style="width: 100%; height: 100%; background-color: rgba(55, 55, 55, 0.5); position:absolute;top:0px;left:0px;">This is backDiv</div>');
In order to retrive data attribute value using JQuery use following code
Syntax
$('selector').data('data-KeyName');
Example
1. $(this).data('backDiv'); // use to retrive value or
2. var temp=$(this).data('backDiv'); // use to retrive value and assign into variable
Related
I want to create some divs and place the around the body. That means left , right, up and down. I create a div every time a client connect via socket. and here is the code
var parent = document.getElementById("#parent-div")
socket.on("isConnected", function(data) {
// Receive the 'data' and check if 'isConnected' is true
if(data.isConnected == true) {
parent.innerHTML += "<div class='new-div'></div>"
}
});
and here is the style of the div :
.ZE {
position: fixed;
width: 400px;
height: 100px;
background-color: #73AD81;
overflow: hidden;
border-radius: 20px 60px;
border: 2px solid #965D31;
}
how can i do that ?
Your code will work as you have it once you've made a few adjustments.
jsFiddle Demo
First, you have a number symbol (#) you don't need in your getElementById():
Should be:
var parent = document.getElementById("parent-div");
Next, create classes for the locations you want to place them in:
.ZE.left {
top: 50%;
transform: translateY(-50%);
}
.ZE.right {
right: 0;
top: 50%;
transform: translateY(-50%);
}
.ZE.up {
left: 50%;
transform: translateX(-50%);
}
.ZE.down {
left: 50%;
transform: translateX(-50%);
bottom: 0;
}
Up to you how you place them. Above is just one way to place them left/right/top/bottom and may not be the best way at that but I've based it on your existing code.
Lastly you'll want to add those classes, incrementally, or otherwise in your callback function:
// for demo purposes
var data = {
isConnected: true
},
classes = ['left', 'right', 'up', 'down'];
//socket.on("isConnected", function(data) {
// Receive the 'data' and check if 'isConnected' is true
// loop for demo purposes
for (var i = 0; i < 4; i++) {
if(data.isConnected === true) {
parent.innerHTML += "<div class='ZE " + classes[i] + "'></div>"
}
}
//});
var newDiv = document.createElement("div");
var parentDiv = document.getElementById("div_to_place_within");
parentDiv.appendChild(newDiv);
newDiv.id = "some_id";
newDiv.className = "some classnames";
createElement & appendChild
Fiddle
var orangeMode = true
flip = function() {
orangeMode = !orangeMode;
}
document.getElementById("box").addEventListener("click", flip);
if (orangeMode) {
document.getElementById("circle").style.backgroundColor = "orange";
} else {
document.getElementById("circle").style.backgroundColor = "blue";
}
Manually changing the variable from true to false on the first line flips the color of the circle from orange to blue, but tapping the box in the corner is meant to flip between them, but doesn't work. Feel like there is something basic I'm doing wrong here?
check the orange value in flip method itself
var orangeMode = true
flip = function() {
orangeMode = !orangeMode;
if (orangeMode) {
document.getElementById("circle").style.backgroundColor = "orange";
} else {
document.getElementById("circle").style.backgroundColor = "blue";
}
}
document.getElementById("box").addEventListener("click", flip);
Although, moving the code to change colour inside the event handler will work, I'd suggest to use classList API.
Updated Fiddle
Create a CSS class to set the background color to blue and toggle this class when the box is clicked.
classList.toggle('className') will add the class if it is not already added on the element otherwise it'll remove the class.
document.getElementById("box").addEventListener("click", function() {
document.getElementById('circle').classList.toggle('blue');
});
#box {
width: 50px;
height: 50px;
position: absolute;
bottom: 0;
right: 0;
background-color: red;
}
#circle {
width: 50px;
height: 50px;
background: orange;
border-radius: 50px;
position: absolute;
top: 50%;
left: 50%;
}
#circle.blue {
background: blue;
}
<div id="box"></div>
<div id="circle"></div>
You could actually check the color and get rid of the global variable:
var flip = function() {
var baseColor = "orange";
var currcolor = document.getElementById("circle").style.backgroundColor;
document.getElementById("circle").style.backgroundColor = (currcolor == baseColor) ? "blue" : baseColor;
}
document.getElementById("box").addEventListener("click", flip);
I've searched for similar question for quite a long time but all my searches gone in vain. Here is my code
<div class="footer-sidebar container" style="height:40px;"></div>
<button class="button">Click</button>
Now if someone clicks on button then my .container height should increase to 400px and if someone clicks on the same button it must back to 40px.
Edit: (Added CSS)
.footer-sidebar {
position: fixed;
z-index: 1500;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
overflow: hidden;
}
Thanks
You could do that by adding a class to your div like this:
$('.button').on('click', function(){
$('.container').toggleClass('open');
}
Inline styles for this should be avoided. Use your css file and add something like this to it:
.container {
height: 40px;
}
.container.open {
height: 400px;
}
Javascript version (opposed to the previously added JQuery option):
Using booleans (tested):
var fullSize = false; // Used for toggling
var button = document.getElementsByClassName("button")[0]; // Get button
var div = document.getElementsByClassName("footer-sidebar")[0]; // Get div
button.onclick = function() {
if(fullSize) { div.style.bottom = 0 + "px"; fullSize = false; } // If div is already 400px...
else { div.style.bottom = -360 + "px"; fullSize = true; } // If div is already 40px...
};
Fiddle
Using classes (untested):
CSS:
.open {
height: 400px;
}
.closed {
height: 40px;
}
Javascript:
var button = document.getElementById("button"); // Get button
var div = document.getElementsByClassName("footer-sidebar container")[0]; // Get div
button.onclick = function() {
if(div.className = "closed") { div.className = "open" }
else if(div.className = "open") { div.className = "closed" }
else { div.className = "open" }
}
Hope this helps.
I have an image button which changes images with a click of a button . This is the following code
function changeImg(thisImg)
{
var altImg = "http://ww1.prweb.com/prfiles/2011/10/12/8875514/star_white.jpg";
var tmpImg = null;
function changeImg(thisImg) {
tmpImg = thisImg.src;
thisImg.src = altImg;
altImg = tmpImg;
}
this is the fiddle http://jsfiddle.net/pUbrv/ which I did previously for clickable images
<img alt="" src="http://www.gettyicons.com/free-icons/136/stars/png/256/star_gold_256.png" id="imgClickAndChange" onclick="changeImg(this)" />
Instead of just chnaging the image by click of a button , I want to pop up a div which contains clickable images after I click the image in the div , the image choud change . Can please anybody help me?
Here is simple Javascript solution.
DEMO
HTML
<body>
<img alt="" src="http://www.gettyicons.com/free-icons/136/stars/png/256/star_gold_256.png" id="imgClickAndChange" onclick="myfunction(this)" />
</body>
SCRIPT
var altImg = "http://ww1.prweb.com/prfiles/2011/10/12/8875514/star_white.jpg";
var tmpImg = null;
function changeImg(thisImg) {
tmpImg = thisImg.src;
thisImg.src = altImg;
altImg = tmpImg;
}
function myfunction(ele) {
var pop=new myPop();
pop.popOut(ele);
}
function myPop() {
this.square = null;
this.overdiv = null;
this.popOut = function(ele) {
tmpImg = ele.src;
//filter:alpha(opacity=25);-moz-opacity:.25;opacity:.25;
this.overdiv = document.createElement("div");
this.overdiv.className = "overdiv";
this.square = document.createElement("div");
this.square.className = "square";
this.square.Code = this;
var msg = document.createElement("div");
msg.className = "msg";
msg.innerHTML = '<img alt="" src="'+altImg+'" id="imgClickAndChange" />';
altImg = tmpImg;
this.square.appendChild(msg);
var closebtn = document.createElement("button");
closebtn.onclick = function() {
this.parentNode.Code.popIn();
}
closebtn.innerHTML = "Close";
this.square.appendChild(closebtn);
document.body.appendChild(this.overdiv);
document.body.appendChild(this.square);
}
this.popIn = function() {
if (this.square != null) {
document.body.removeChild(this.square);
this.square = null;
}
if (this.overdiv != null) {
document.body.removeChild(this.overdiv);
this.overdiv = null;
}
}
}
CSS
div.overdiv { filter: alpha(opacity=75);
-moz-opacity: .75;
opacity: .75;
background-color: #c0c0c0;
position: absolute;
top: 0px;
left: 0px;
width: 100%; height: 100%; }
div.square { position: absolute;
top: 200px;
left: 200px;
background-color: Menu;
border: #f9f9f9;
height: 200px;
width: 300px; }
div.square div.msg { color: #3e6bc2;
font-size: 15px;
padding: 15px; }
Pollisbly the jQuery UI dialog can help you.
Since the changing of images you have already implemented, you just need to put the images in the dialog.
Also you may like the modal functionality of the dialog.
Edit
If you don't want to use jQuery UI, then here is what you can do:
Create a new div.
Initially make it hidden or set its display property to none.
When user clicks on the image, make this div visible.
Set its position to absolute and set its left and top corrdinates as you want.
Add the image this div,
and finally add the event handler to this div for changing the images.
I'm trying to create a dialog window using the following CSS:
#blackOverlay {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000000;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
filter: alpha(opacity=80);
-moz-opacity: 0.8;
-khtml-opacity: 0.8;
opacity: 0.8;
z-index: 1001;
}
#whiteOverlay {
display: block;
position: absolute;
top: 10%;
left: 10%;
width: 80%;
height: 80%;
z-index:2002;
overflow: auto;
background: #c4e982;
}
and the following JS:
var div = $("<div id='blackOverlay'></div");
$("body").prepend(div);
var div = $("<div id='whiteOverlay'></div");
div.html("Loading......");
var u = "myurl?function=example";
div.load(u);
$("body").prepend(div);
This works correctly in Firefox, Safari, Chrome and Opera.
Unfortunately it fails in IE, at least on version 8.0. The color/opacity is only applied to body and NOT on other DIV's. Instead of "hidding" everything behind the blackOverlay, everything (links, buttons, input fields, ...) is still usable although the loaded content is displayed correctly (in front, center of screen).
Any help is appreciated!
Thank you jduren for pointing me in the right direction. After attempting to handle it in similar way as described here I came up with the following workaround:
function shime() {
jQuery.each(jQuery.browser, function(i) {
if($.browser.msie){
$('div').each(function() {
$(this).addClass("shine");
});
}
});
}
function unshime() {
jQuery.each(jQuery.browser, function(i) {
if($.browser.msie){
$(".shine").each(function() {
$(this).removeClass("shine");
});
}
});
}
And the following CSS:
div.shine {
display: none;
}
I know that it's not the best solution, but I'm getting tired of running in circles due to IE "features".
You need to create what's called an iFrame shim. IE paints controls over everything that isn't windowed so you won't be able to handle this by CSS/HTML hacks alone.
Here is a quick overview of Iframe Shimming http://www.macridesweb.com/oltest/IframeShim.html
Also, the Mootools More library includes an iFrame shim Feature http://mootools.net/docs/more/Utilities/IframeShim as do most popular javascript frameworks that create overlayed UI elements.
This is the IFrame Shim class from mootools more library to give you an idea of what's involved, don't use this as it depends on other Mootoosl classes.
var IframeShim = new Class({
Implements: [Options, Events, Class.Occlude],
options: {
className: 'iframeShim',
src: 'javascript:false;document.write("");',
display: false,
zIndex: null,
margin: 0,
offset: {x: 0, y: 0},
browsers: (Browser.Engine.trident4 || (Browser.Engine.gecko && !Browser.Engine.gecko19 && Browser.Platform.mac))
},
property: 'IframeShim',
initialize: function(element, options){
this.element = document.id(element);
if (this.occlude()) return this.occluded;
this.setOptions(options);
this.makeShim();
return this;
},
makeShim: function(){
if(this.options.browsers){
var zIndex = this.element.getStyle('zIndex').toInt();
if (!zIndex){
zIndex = 1;
var pos = this.element.getStyle('position');
if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
this.element.setStyle('zIndex', zIndex);
}
zIndex = ($chk(this.options.zIndex) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
if (zIndex < 0) zIndex = 1;
this.shim = new Element('iframe', {
src: this.options.src,
scrolling: 'no',
frameborder: 0,
styles: {
zIndex: zIndex,
position: 'absolute',
border: 'none',
filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
},
'class': this.options.className
}).store('IframeShim', this);
var inject = (function(){
this.shim.inject(this.element, 'after');
this[this.options.display ? 'show' : 'hide']();
this.fireEvent('inject');
}).bind(this);
if (!IframeShim.ready) window.addEvent('load', inject);
else inject();
} else {
this.position = this.hide = this.show = this.dispose = $lambda(this);
}
},
position: function(){
if (!IframeShim.ready || !this.shim) return this;
var size = this.element.measure(function(){
return this.getSize();
});
if (this.options.margin != undefined){
size.x = size.x - (this.options.margin * 2);
size.y = size.y - (this.options.margin * 2);
this.options.offset.x += this.options.margin;
this.options.offset.y += this.options.margin;
}
this.shim.set({width: size.x, height: size.y}).position({
relativeTo: this.element,
offset: this.options.offset
});
return this;
},
hide: function(){
if (this.shim) this.shim.setStyle('display', 'none');
return this;
},
show: function(){
if (this.shim) this.shim.setStyle('display', 'block');
return this.position();
},
dispose: function(){
if (this.shim) this.shim.dispose();
return this;
},
destroy: function(){
if (this.shim) this.shim.destroy();
return this;
}
});
window.addEvent('load', function(){
IframeShim.ready = true;
});