Flip Effect without Transform or Rotate - javascript

I stumbple upon this Javascript flip effect page.
When I inspect its obfuscated source code, I can not find css property transform or rotate .
I want to know how the flip effect is achieved. What CSS properties are involved?

$(document).ready(function() {
/* The following code is executed once the DOM is loaded */
$('.sponsorFlip').click(function() {
// $(this) point to the clicked .sponsorFlip element (caching it in elem for speed):
var elem = $(this);
// data('flipped') is a flag we set when we flip the element:
if (elem.data('flipped')) {
// If the element has already been flipped, use the revertFlip method
// defined by the plug-in to revert to the default state automatically:
elem.revertFlip();
// Unsetting the flag:
elem.data('flipped', false)
} else {
// Using the flip method defined by the plugin:
elem.flip({
direction: 'lr',
speed: 350,
onBefore: function() {
// Insert the contents of the .sponsorData div (hidden
// from view with display:none) into the clicked
// .sponsorFlip div before the flipping animation starts:
elem.html(elem.siblings('.sponsorData').html());
}
});
// Setting the flag:
elem.data('flipped', true);
}
});
});
body {
/* Setting default text color, background and a font stack */
font-size: 0.825em;
color: #666;
background-color: #fff;
font-family: Arial, Helvetica, sans-serif;
}
.sponsorListHolder {
margin-bottom: 30px;
}
.sponsor {
width: 180px;
height: 180px;
float: left;
margin: 4px;
/* Giving the sponsor div a relative positioning: */
position: relative;
cursor: pointer;
}
.sponsorFlip {
/* The sponsor div will be positioned absolutely with respect
to its parent .sponsor div and fill it in entirely */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: 1px solid #ddd;
background: url("img/background.jpg") no-repeat center center #f9f9f9;
}
.sponsorFlip:hover {
border: 1px solid #999;
/* CSS3 inset shadow: */
-moz-box-shadow: 0 0 30px #999 inset;
-webkit-box-shadow: 0 0 30px #999 inset;
box-shadow: 0 0 30px #999 inset;
}
.sponsorFlip img {
/* Centering the logo image in the middle of the .sponsorFlip div */
position: absolute;
top: 50%;
left: 50%;
margin: -70px 0 0 -70px;
}
.sponsorData {
/* Hiding the .sponsorData div */
display: none;
}
.sponsorDescription {
font-size: 11px;
padding: 50px 10px 20px 20px;
font-style: italic;
}
.sponsorURL {
font-size: 10px;
font-weight: bold;
padding-left: 20px;
}
.clear {
/* This class clears the floats */
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://demo.tutorialzine.com/2010/03/sponsor-wall-flip-jquery-css/jquery.flip.min.js"></script>
<div title="Click to flip" class="sponsor">
<div class="sponsorFlip">
<img alt="More about google" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAACXCAMAAAAvQTlLAAABF1BMVEX////qQzU0qFNChfT7vAU8gvTz9/5pm/bh6f3m7f4edvMhePPqPi/7tgD7uAD7ugAyfvPpOCjpNCIopUv0+vb62NYAnjf97ezU6tnrTkKv2LhCrF7whX4YokLpLRnC4cn+9/bymZPoHgDt8v4zqkHo9Ov0qqX2vrrpOzb8wgB1vob+7s+ExZNUsmv/+e9XkPXT4PzsX1WZzqX4ycbudW374+JiuHdKqU7btQPsuxaTtfj8w0U8lrSux/prrEQDpljF1vsmf+Gmz8SRsD40pGf/4Kj86cGmsjY3oH85maKAqfc/jtQ/k8Q5nZL3qBT81oTtXC/xfCb1lxvvbyHNtyb8y2MAaPK1syznAhj2nzjuZirzjSD80nX4U1R1AAAFc0lEQVR4nO2YC1faSBiGQwCtEAzJxBgICSGFoMilQERbWy+tdXfb3bXdrXvt//8dO1wOEDIZkkmGePbMo+eoR8DHb9755hs4jsFgMBgMBoPBYDAYDMYzxDo+HzsN1x1C3FqjPT62rNSdjpza0LRNU5aEGZJs2rbkNtpHKUqN3UoGCmV8CLKcqTSOrDSsxg3BRjmt3Oyhc75rq/ZQkIOdlmoZd5dmljO0MZVaR7LdnSVtPJRDWs3MBNfahdWRG7ZWSzPJoa/lCFI0qykm7ZidD83oVtOS2W2aWuMKQbHmyDV6Wk7UZK1juseUtGrbOxYOqWLRsLJcsmitvDJUwu8SR2uOUKHRYC033iLCalGJV8xsUaoW14idLSrVam+rliBJ8hQJjoe7q9aRjZWSzQqcn502BM7Tw4y5uUMoVcsa4sY/W2qMz63Vo+G079rm+jOEDJ1RB5N5OVND/k3HXZlRqhY3Dsy8YNeCWqXVrph0q3VcCSwWfnpxMhLFanFOwCoK9rZp7xyWjFa1uOOAvSgPQ5x2DZtWtbga+lg0h6H+oEPr0nH2+wlSi+KUF4rH3L8IMdNNWatfyp3+mtk0k3Zz88LweJiDYl+8YoJJK8xh6V+JOcjpV4+YlOJ7NXMeZlpQ7LeTlZncSFuL+36YW4it1lLIpG3F9RflmoqJ/yzEZKo31FA8lHIrTucNQ0i7RXBry7gI2bRh2OO0rTjuSsx5xMQvJ0IlbSl4BuV8fP0r/XQtu8R6yf7GTRF7kSD2+njo8xK/Yx5/MNiPArHYo9/r8CPOq5CPQOElqdeTfx1LfaxXNgLFV4Ra/dcIL9wTonmV35F6IeJ1laDXG1Kvks/rEBf7iF75Twl64WIf1Wuf0OvM71VK0muQoNcD8/pfeD2HfKH24+Pz9BKfnoPXoe8cEnMJepH2r/4V1XObuN8j54mzxLyIz0fk/IUL/o7mCeS8+qRgvP4oFosF+DH/LEx/mn9XKPu9iOcv7sGvJV5rmCe8COLgjV+MfF71BV/8dmGMiF7qE6Jg5BcPr5eY+5PneYPolYo+qzz5vcMbMDF3fTP1IinYK/+OIN+O3o4vXs60eL7Xiv5CiHiRb0eOs1YLKX6bWxEV7GCA6BMvyL2WCymKH/glauSCvUOknvR0nLF4h0J8fX2z8gITTA9D4k99rHhxix0pXvIeQMSVRKQrWyDuqjMeSnANf7jxevFqPcpr3CK08gPyLjEDtocPm1qwYriuv0k2n/gywuRfXvi1YMVCi+3tI7Sy2XjLCFvYBcIKoofdlPuIVSSfCVdUDbRYuIztIbXipn6KoqO9eNDd/uSXA6QW8Wi/Th0EiBn6lpAp7++QWtnybQJe3CRIDIARrsNqHfUeKZZIueC/HeQFzdRRQP6V+kQFPGi+Lfu3YzHO0bhGUPRni8l3EBugNZoY8/+m+ZOvYmXii9AmXYwYDwxjUtVaremSKkqrpdW7QF2VuHl/t1GxAfEAvYmiBy/lQk3vTTqQSU83DO+Dwf1nz7lduE1KC65LULPwCECQv2i+XTuKYp9AHjQ1hFggzR+X6Y99YG8Q2MVCAfTP8/jnY9yCAsRiVQyAn8vJdVQP1VgV45u/5PM0tOJWDIbsrhjjDoRB29IutmAY8acINC0d12C3APgoQ240FGznx2v1ot6iIlEN6J3brFTs6JEASuDYg8HoRbpBkVHnIy4mMLqUizVHqfIRagbAhOCdFjJaVRCymQG1Q28bIlDqvaDxYb1UemdntVqijXQVkzSgGp3qTnLlQ9FGPZ03NusGABwNe516OlILWvVqd6IbqqoakOkXfdId1XcaqiAUONdrWh2iaS34Q9o+DAaDwWAwGAwGg8FgMJD8B0Y0n3erXn7HAAAAAElFTkSuQmCC">
</div>
<div class="sponsorData">
<div class="sponsorDescription">
The company that redefined web search.
</div>
<div class="sponsorURL">
http://www.google.com/
</div>
</div>
</div>

It's a jQuery plugin they use to achieve this result. It's called jquery.flip.min.js 😉
• Here is a more legible version of their JavaScript code:
eval(function(p, a, c, k, e, r) {
e = function(c) {
return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
};
if (!''.replace(/^/, String)) {
while (c--) r[e(c)] = k[c] || e(c);
k = [
function(e) {
return r[e]
}
];
e = function() {
return '\\w+'
};
c = 1
};
while (c--)
if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p
}('(5($){5 H(a){a.1D.1f[a.1E]=1F(a.1G,10)+a.1H}6 j=5(a){1I({1J:"1g.Z.1K 1L 1M",1N:a})};6 k=5(){7(/*#1O!#*/11&&(1P 1Q.1h.1f.1R==="1S"))};6 l={1T:[0,4,4],1U:[1i,4,4],1V:[1j,1j,1W],1X:[0,0,0],1Y:[0,0,4],1Z:[1k,1l,1l],20:[0,4,4],21:[0,0,A],22:[0,A,A],23:[12,12,12],24:[0,13,0],26:[27,28,1m],29:[A,0,A],2a:[2b,1m,2c],2d:[4,1n,0],2e:[2f,2g,2h],2i:[A,0,0],2j:[2k,2l,2m],2n:[2o,0,R],2p:[4,0,4],2q:[4,2r,0],2s:[0,t,0],2t:[2u,0,2v],2w:[1i,1o,1n],2x:[2y,2z,1o],2A:[1p,4,4],2B:[1q,2C,1q],2D:[R,R,R],2E:[4,2F,2G],2H:[4,4,1p],2I:[0,4,0],2J:[4,0,4],2K:[t,0,0],2L:[0,0,t],2M:[t,t,0],2N:[4,1k,0],2O:[4,S,2P],2Q:[t,0,t],2R:[t,0,t],2S:[4,0,0],2T:[S,S,S],2U:[4,4,4],2V:[4,4,0],9:[4,4,4]};6 m=5(a){T(a&&a.1r("#")==-1&&a.1r("(")==-1){7"2W("+l[a].2X()+")"}2Y{7 a}};$.2Z($.30.31,{u:H,v:H,w:H,x:H});$.1s.32=5(){7 U.1t(5(){6 a=$(U);a.Z(a.B(\'1u\'))})};$.1s.Z=5(i){7 U.1t(5(){6 c=$(U),3,$8,C,14,15,16=k();T(c.B(\'V\')){7 11}6 e={I:(5(a){33(a){W"X":7"Y";W"Y":7"X";W"17":7"18";W"18":7"17";34:7"Y"}})(i.I),y:m(i.D)||"#E",D:m(i.y)||c.z("19-D"),1v:c.J(),F:i.F||1w,K:i.K||5(){},L:i.L||5(){},M:i.M||5(){}};c.B(\'1u\',e).B(\'V\',1).B(\'35\',e);3={s:c.s(),n:c.n(),y:m(i.y)||c.z("19-D"),1x:c.z("36-37")||"38",I:i.I||"X",G:m(i.D)||"#E",F:i.F||1w,o:c.1y().o,p:c.1y().p,1z:i.1v||39,9:"9",1a:i.1a||11,K:i.K||5(){},L:i.L||5(){},M:i.M||5(){}};16&&(3.9="#3a");$8=c.z("1b","3b").8(3c).B(\'V\',1).3d("1h").J("").z({1b:"1A",3e:"3f",p:3.p,o:3.o,3g:0,3h:3i});6 f=5(){7{1B:3.9,1x:0,3j:0,u:0,w:0,x:0,v:0,N:3.9,O:3.9,P:3.9,Q:3.9,19:"3k",3l:\'3m\',n:0,s:0}};6 g=5(){6 a=(3.n/13)*25;6 b=f();b.s=3.s;7{"q":b,"1c":{u:0,w:a,x:a,v:0,N:\'#E\',O:\'#E\',o:(3.o+(3.n/2)),p:(3.p-a)},"r":{v:0,u:0,w:0,x:0,N:3.9,O:3.9,o:3.o,p:3.p}}};6 h=5(){6 a=(3.n/13)*25;6 b=f();b.n=3.n;7{"q":b,"1c":{u:a,w:0,x:0,v:a,P:\'#E\',Q:\'#E\',o:3.o-a,p:3.p+(3.s/2)},"r":{u:0,w:0,x:0,v:0,P:3.9,Q:3.9,o:3.o,p:3.p}}};14={"X":5(){6 d=g();d.q.u=3.n;d.q.N=3.y;d.r.v=3.n;d.r.O=3.G;7 d},"Y":5(){6 d=g();d.q.v=3.n;d.q.O=3.y;d.r.u=3.n;d.r.N=3.G;7 d},"17":5(){6 d=h();d.q.w=3.s;d.q.P=3.y;d.r.x=3.s;d.r.Q=3.G;7 d},"18":5(){6 d=h();d.q.x=3.s;d.q.Q=3.y;d.r.w=3.s;d.r.P=3.G;7 d}};C=14[3.I]();16&&(C.q.3n="3o(D="+3.9+")");15=5(){6 a=3.1z;7 a&&a.1g?a.J():a};$8.1d(5(){3.K($8,c);$8.J(\'\').z(C.q);$8.1e()});$8.1C(C.1c,3.F);$8.1d(5(){3.M($8,c);$8.1e()});$8.1C(C.r,3.F);$8.1d(5(){T(!3.1a){c.z({1B:3.G})}c.z({1b:"1A"});6 a=15();T(a){c.J(a)}$8.3p();3.L($8,c);c.3q(\'V\');$8.1e()})})}})(3r);', 62, 214, '|||flipObj|255|function|var|return|clone|transparent||||||||||||||height|top|left|start|second|width|128|borderTopWidth|borderBottomWidth|borderLeftWidth|borderRightWidth|bgColor|css|139|data|dirOption|color|999|speed|toColor|int_prop|direction|html|onBefore|onEnd|onAnimation|borderTopColor|borderBottomColor|borderLeftColor|borderRightColor|211|192|if|this|flipLock|case|tb|bt|flip||false|169|100|dirOptions|newContent|ie6|lr|rl|background|dontChangeColor|visibility|first|queue|dequeue|style|jquery|body|240|245|165|42|107|140|230|224|144|indexOf|fn|each|flipRevertedSettings|content|500|fontSize|offset|target|visible|backgroundColor|animate|elem|prop|parseInt|now|unit|throw|name|js|plugin|error|message|cc_on|typeof|document|maxHeight|undefined|aqua|azure|beige|220|black|blue|brown|cyan|darkblue|darkcyan|darkgrey|darkgreen||darkkhaki|189|183|darkmagenta|darkolivegreen|85|47|darkorange|darkorchid|153|50|204|darkred|darksalmon|233|150|122|darkviolet|148|fuchsia|gold|215|green|indigo|75|130|khaki|lightblue|173|216|lightcyan|lightgreen|238|lightgrey|lightpink|182|193|lightyellow|lime|magenta|maroon|navy|olive|orange|pink|203|purple|violet|red|silver|white|yellow|rgb|toString|else|extend|fx|step|revertFlip|switch|default|flipSettings|font|size|12px|null|123456|hidden|true|appendTo|position|absolute|margin|zIndex|9999|lineHeight|none|borderStyle|solid|filter|chroma|remove|removeData|jQuery'.split('|'), 0, {}))

Related

How make a textarea with tags in react that have clickable dropdown

Id like to make a component in react that allows me to have a textarea with tags that can be inserted when clicked from a dropdown. Id also like this textarea to be able to mix text aswell. I have currently been trying to use tagify with react but I cant seem to figure out a way to the tagify's function that adds the tag to be accessed by the onClick that is connected to the dropdown.
Any ideas?
I believe you can get your answer in this URL of other question asked on StackOverflow https://stackoverflow.com/a/38119725/15405352
var $container = $('.container');
var $backdrop = $('.backdrop');
var $highlights = $('.highlights');
var $textarea = $('textarea');
var $toggle = $('button');
// yeah, browser sniffing sucks, but there are browser-specific quirks to handle that are not a matter of feature detection
var ua = window.navigator.userAgent.toLowerCase();
var isIE = !!ua.match(/msie|trident\/7|edge/);
var isWinPhone = ua.indexOf('windows phone') !== -1;
var isIOS = !isWinPhone && !!ua.match(/ipad|iphone|ipod/);
function applyHighlights(text) {
text = text
.replace(/\n$/g, '\n\n')
.replace(/[A-Z].*?\b/g, '<mark>$&</mark>');
if (isIE) {
// IE wraps whitespace differently in a div vs textarea, this fixes it
text = text.replace(/ /g, ' <wbr>');
}
return text;
}
function handleInput() {
var text = $textarea.val();
var highlightedText = applyHighlights(text);
$highlights.html(highlightedText);
}
function handleScroll() {
var scrollTop = $textarea.scrollTop();
$backdrop.scrollTop(scrollTop);
var scrollLeft = $textarea.scrollLeft();
$backdrop.scrollLeft(scrollLeft);
}
function fixIOS() {
// iOS adds 3px of (unremovable) padding to the left and right of a textarea, so adjust highlights div to match
$highlights.css({
'padding-left': '+=3px',
'padding-right': '+=3px'
});
}
function bindEvents() {
$textarea.on({
'input': handleInput,
'scroll': handleScroll
});
$toggle.on('click', function() {
$container.toggleClass('perspective');
});
}
if (isIOS) {
fixIOS();
}
bindEvents();
handleInput();
#import url(https://fonts.googleapis.com/css?family=Open+Sans);
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 30px;
background-color: #f0f0f0;
}
.container, .backdrop, textarea {
width: 460px;
height: 180px;
}
.highlights, textarea {
padding: 10px;
font: 20px/28px 'Open Sans', sans-serif;
letter-spacing: 1px;
}
.container {
display: block;
margin: 0 auto;
transform: translateZ(0);
-webkit-text-size-adjust: none;
}
.backdrop {
position: absolute;
z-index: 1;
border: 2px solid #685972;
background-color: #fff;
overflow: auto;
pointer-events: none;
transition: transform 1s;
}
.highlights {
white-space: pre-wrap;
word-wrap: break-word;
color: transparent;
}
textarea {
display: block;
position: absolute;
z-index: 2;
margin: 0;
border: 2px solid #74637f;
border-radius: 0;
color: #444;
background-color: transparent;
overflow: auto;
resize: none;
transition: transform 1s;
}
mark {
border-radius: 3px;
color: transparent;
background-color: #b1d5e5;
}
button {
display: block;
width: 300px;
margin: 30px auto 0;
padding: 10px;
border: none;
border-radius: 6px;
color: #fff;
background-color: #74637f;
font: 18px 'Opens Sans', sans-serif;
letter-spacing: 1px;
appearance: none;
cursor: pointer;
}
.perspective .backdrop {
transform:
perspective(1500px)
translateX(-125px)
rotateY(45deg)
scale(.9);
}
.perspective textarea {
transform:
perspective(1500px)
translateX(155px)
rotateY(45deg)
scale(1.1);
}
textarea:focus, button:focus {
outline: none;
box-shadow: 0 0 0 2px #c6aada;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="backdrop">
<div class="highlights"></div>
</div>
<textarea>This demo shows how to highlight bits of text within a textarea. Alright, that's a lie. You can't actually render markup inside a textarea. However, you can fake it by carefully positioning a div behind the textarea and adding your highlight markup there. JavaScript takes care of syncing the content and scroll position from the textarea to the div, so everything lines up nicely. Hit the toggle button to peek behind the curtain. And feel free to edit this text. All capitalized words will be highlighted.</textarea>
</div>
<button>Toggle Perspective</button>
Reference- https://codepen.io/lonekorean/pen/gaLEMR for example

JavaScript Etch-a-Sketch shading pen stops increasing opacity after another pen has been clicked on

I'm creating an Etch-a-Sketch for The Odin Project using HTML, CSS, & JavaScript. I'm having some difficulties with the JavaScript for the "shader pen" I've implemented.
Note: The "pens" described in this question are not to be confused with code pens.
There are two pens: a black pen that turns a cell black and the shader pen which, on the first pass, turns the cell black but changes the opacity to 0.1 so that it's almost transparent. This creates the illusion of slight darkening since the background behind the cell is the same as the original color of the cell. After each subsequent pass with the shader pen, the opacity increases by 0.1.
The shader pen is the default pen. It works fine at first, but when I click on the black pen and then go back to the shader pen, the shader pen increases the opacity once and stops. It also overrides the black cells.
Here's how I set up the pens:
makeGrid(16); // generate grid
pen("shader"); // default pen: shader
document.querySelector('#black').addEventListener("click", e => pen("black"));
document.querySelector('#shader').addEventListener("click", e => pen("shader"));
function pen(selected) {
let cells = document.querySelectorAll('div.cell');
cells.forEach(cell => {
cell.addEventListener('mouseover', function(e) {
if (selected == "black") {
// turns cell black
cell.classList.remove('shade');
cell.style.backgroundColor = '#101010';
cell.style.opacity = '1';
console.log('Make cell black')
} else if (selected == "shader") {
let opacity = cell.style.opacity;
if (cell.classList.contains("shade")) {
// increases opacity by 0.1
cell.style.opacity = (Number(opacity) + 0.1);
console.log('If there is shade, increase opacity.')
} else {
// turns cell to 0.1 opacity
cell.classList.add('shade');
cell.setAttribute('style', 'opacity:0.1');
cell.style.backgroundColor = '#101010';
console.log('Else, add shade class.')
}
}
})
});
}
I ran this code with a console.log statement in each conditional block and it looks like the black pen is still running when I go back to using the shader pen. My best guess is that this is what's causing the problem, but I'm not sure how to fix it.
I've created a CodePen with the rest of the code so you can see it in action. As previously mentioned, the default pen is the shader. It works as intended at the beginning, but it just stops after the black pen is selected.
Any help or guidance would be greatly appreciated.
There's so many problems with your code, The main one is when you change the pen type (when you call the pen() function) you add a new mouseover event listener.
Let's walk through it
Your code starts by calling pen('shader') making the shader the default pen type
pen("shader");
let's look at the pen() definition
function pen(selected) {
let cells = document.querySelectorAll('div.cell');
cells.forEach(cell => {
cell.addEventListener('mouseover', function(e){
...
})
});
}
What happens is the event listener takes the string shader and closes on it (This is called a closure) for that instance now whenever you hover over a cell the pen type will be shader
Now when you select the black pen you call the function pen() again adding a new set of event listeners.
This does not replace the old event listener with the new one, it stacks them like calling two functions one after the other.
Now when you hover over a cell the first event listener with the pen type shader will fire and then the second one with the black pen will fire after it, you can see this in the console you see two messages being printed from both if statement conditions.
Now when you pick the shader again you add a new set of event listeners with the shader pen type, what happens is the very first event listener will fire setting opacity to 0.1 then comes the black one removing the shade class then comes the third listener again checking if the cell has the class shade if(cell.classList.contains("shade")) which is false then falls down to the last else statement.
There's a ton of ways to fix this, but seeing that you're a beginner i will give you simple solutions
First make the pen type a global variable and on each button click you change it
Second add only one event listener to all cels at the start of your code and have them check the global variable
Demo
let penType = 'shader';
makeGrid(4); // generate grid
document.querySelector('#black').addEventListener("click", e => penType = "black");
document.querySelector('#shader').addEventListener("click", e => penType = "shader");
// generate grid
function makeGrid(dimension) {
const canvas = document.querySelector('#canvas');
const canvasWidth = document.getElementById("canvas").offsetWidth;
const cellWidth = canvasWidth / dimension;
for (let x = 1; x <= dimension * dimension; x++) {
const makeCell = document.createElement('div');
makeCell.classList.add('cell');
canvas.appendChild(makeCell);
};
canvas.style.gridTemplateRows = `repeat(${dimension}, ${cellWidth}px [row-start]`;
canvas.style.gridTemplateColumns = `repeat(${dimension}, ${cellWidth}px [column-start]`;
// after all cells have been generated add the event listener
// this is not the most optimize version of this but it gets the job done
let cells = document.querySelectorAll('div.cell');
cells.forEach(cell => {
cell.addEventListener('mouseover', function(e) {
console.log(penType)
if (penType == "black") { // turns cell black
cell.classList.remove('shade');
cell.style.backgroundColor = '#101010';
cell.style.opacity = '1';
console.log('Make cell black')
} else if (penType == "shader") { // turns cell 0.1
let opacity = cell.style.opacity;
if (cell.classList.contains("shade")) {
cell.style.opacity = (Number(opacity) + 0.1);
console.log('If there is shade, increase opacity.')
} else {
cell.classList.add('shade');
cell.setAttribute('style', 'opacity:0.1');
cell.style.backgroundColor = '#101010';
console.log('Else, add shade class.')
}
}
})
});
}
body {
margin: 0;
background-color: #514c53;
color: #fff;
font-size: 18pt;
}
/* DIV STYLING */
#container {
margin: 20px auto;
max-width: 400px;
display: flex;
flex-wrap: wrap;
}
.full {
width: 100%;
}
.left {
width: 75%;
margin-top: 15px;
}
.right {
width: 25%;
text-align: right;
}
#canvas {
display: grid;
flex-wrap: wrap;
grid-template-rows: repeat(16, 30px [row-start]);
grid-template-columns: repeat(16, 30px [col-start]);
background: #e8dfd6;
}
.cell {
background: #e8dfd6;
}
/* CELL SHADING */
.black {
background-color: #101010;
}
.shade {
background-color: #101010;
width: 100%;
height: 100%;
}
/* ELEMENT STYLING */
button {
font-weight: 700;
margin: 10px 0;
background-color: #b9967d;
color: #fff;
padding: 0px 15px;
text-shadow: 1px 1px #2e2e2e;
box-shadow: 3px 3px #2e2e2e;
border-radius: 5px;
border: 0px;
text-transform: uppercase;
height: 30px;
outline: none;
transition: 0.3s;
}
button:hover {
cursor: pointer;
background-color: #aa8062;
box-shadow: 0px -3px #2e2e2e;
}
button:active {
background-color: #997963;
}
.circle {
float: left;
height: 15px;
width: 15px;
border: 1px solid #fff;
border-radius: 50%;
margin: 1px 5px 0 0;
}
.circle:hover {
cursor: pointer;
/*transition: 0.3s;
border: 2px solid #fff;*/
}
.meaning {
float: left;
font-size: .542em;
text-transform: uppercase;
padding-top: 2px;
margin-right: 10px;
}
#black {
background-color: #101010;
}
#shader {
background-image: linear-gradient(#807b76, #dfd8d0);
}
<div id="container">
<div class="left" style="margin-bottom:10px">
<div class="circle" id="black"></div>
<div class="meaning">Black</div>
<div class="circle" id="shader"></div>
<div class="meaning">Shader</div>
</div>
<div id="canvas" class="full">
<!--grid generates here-->
</div>
</div>
<!--container-->
One tiny problem with your logic, when go to the black pen you don't have to remove the shade class because then when you come back to the shade pen and you hover over a black cell it sets opacity back to 0.1
I changed a lot, so I can't describe all of the changes, but here's a link to my forked codepen:
https://codepen.io/scoutskylar/pen/ExxWPMb
The biggest change was removing the black and shade classes and just changing the opacity instead. (All of the cells now start with 0 opacity.) I also added erasers just for fun. :) The other big thing was making the event handlers once instead of adding a handler every time the pen changed.
Here's the code:
var currentPen = "shader"; // default pen
makeGrid(16); // generate grid
document.querySelector("#black").addEventListener("click", e => {
currentPen = "black";
});
document.querySelector("#shader").addEventListener("click", e => {
currentPen = "shader";
});
document.querySelector("#eraser").addEventListener("click", e => {
currentPen = "eraser";
});
document.querySelector("#deshader").addEventListener("click", e => {
currentPen = "deshader";
});
// generate grid
function makeGrid(dimension) {
const canvas = document.querySelector("#canvas");
const canvasWidth = document.getElementById("canvas").offsetWidth;
const cellWidth = canvasWidth / dimension;
for (let x = 1; x <= dimension * dimension; x++) {
const makeCell = document.createElement("div");
makeCell.classList.add("cell");
canvas.appendChild(makeCell);
}
canvas.style.gridTemplateRows = `repeat(${dimension}, ${cellWidth}px [row-start]`;
canvas.style.gridTemplateColumns = `repeat(${dimension}, ${cellWidth}px [column-start]`;
let cells = document.querySelectorAll("div.cell");
cells.forEach(cell => {
cell.addEventListener("mouseover", function(e) {
if (currentPen == "black") {
// turns cell black
cell.style.opacity = "1";
// console.log("Make cell black");
} else if (currentPen == "shader") {
// turns cell 0.1 opacity darker
let opacity = Number(cell.style.opacity);
cell.style.opacity = opacity >= 1 ? "1" : opacity + 0.1 + "";
// console.log("Increase opacity");
} else if (currentPen == "eraser") {
// resets color
cell.style.opacity = "0";
// console.log("Reset opacity");
} else if (currentPen == "deshader") {
// turns cell 0.1 opacity lighter
let opacity = Number(cell.style.opacity);
cell.style.opacity = opacity <= 0 ? "0" : opacity - 0.1 + "";
// console.log("Decrease opacity");
}
});
});
}
body {
margin: 0;
background-color: #514c53;
color: #fff;
font-size: 18pt;
}
/* DIV STYLING */
#container {
margin: 20px auto;
max-width: 400px;
display: flex;
flex-wrap: wrap;
}
.full {
width: 100%;
}
.left {
width: 75%;
margin-top: 15px;
}
.right {
width: 25%;
text-align: right;
}
#canvas {
display: grid;
flex-wrap: wrap;
grid-template-rows: repeat(16, 30px [row-start]);
grid-template-columns: repeat(16, 30px [col-start]);
background: #e8dfd6;
}
.cell {
/* background: #e8dfd6; */
background-color: #101010;
opacity: 0;
}
/* CELL SHADING */
/* .black {
background-color: #101010;
} */
/* .shade {
background-color: #101010;
width: 100%;
height: 100%;
} */
/* ELEMENT STYLING */
button {
font-weight: 700;
margin: 10px 0;
background-color: #b9967d;
color: #fff;
padding: 0px 15px;
text-shadow: 1px 1px #2e2e2e;
box-shadow: 3px 3px #2e2e2e;
border-radius: 5px;
border: 0px;
text-transform: uppercase;
height: 30px;
outline: none;
transition: 0.3s;
cursor: pointer;
}
button:hover {
background-color: #aa8062;
box-shadow: 0px -3px #2e2e2e;
}
button:active {
background-color: #997963;
}
.circle {
display: inline-block;
height: 15px;
width: 15px;
border: 1px solid #fff;
border-radius: 50%;
margin: 1px 5px 0 0;
cursor: pointer;
}
.meaning {
font-size: 0.542em;
text-transform: uppercase;
padding-top: 2px;
margin-right: 10px;
cursor: pointer;
}
.penbutton {
display: inline-block;
}
#black .circle {
background-color: #101010;
}
#shader .circle {
background: linear-gradient(#807b76, #dfd8d0);
}
#eraser .circle {
background-color: #e8dfd6;
}
#deshader .circle {
background: linear-gradient(#9e9a96, #e8dfd6);
}
<head>
<title>Etch-a-Sketch</title>
</head>
<body>
<div id="container">
<div class="left" style="margin-bottom:10px">
<span id="black" class="penbutton">
<span class="circle"></span>
<span class="meaning">Black</span>
</span>
<span id="shader" class="penbutton">
<span class="circle"></span>
<span class="meaning">Shader</span>
</span>
<span id="eraser" class="penbutton">
<span class="circle"></span>
<span class="meaning">Super Eraser</span>
</span>
<span id="deshader" class="penbutton">
<span class="circle"></span>
<span class="meaning">Light Eraser</span>
</span>
</div>
<div id="canvas" class="full">
<!--grid generates here-->
</div>
</div>
<!--container-->
</body>
<script src="assets/js/eas.js"></script>

infoWindow in google maps on multiple markers [duplicate]

This question already has answers here:
Google Maps JS API v3 - Simple Multiple Marker Example
(15 answers)
Closed 6 years ago.
i've created a google maps, which retrieve data from a csv file. This seem to work fine, however when i loop through all the objects the infoWindow does not seem to work. i guess this is due to the fact that the marker variable is inside a for loop. i've tried to move the code to inside the loop, however this result in the infoWindow placed randomly on the map instead above the clicked marker. How can i achieve the infoWindow to work with multiple markers?
db.csv example
40.740;-74.18;test;haha;
40.740;-74.20;test;haha;
html & java
<head>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="normalize.css">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
</head>
<body>
<div id="mapContainer">
<div id="map"></div>
</div>
<div id="abc">
<div id="popupContact">
<section class="register">
<h1>CAMP INFORMATIONER:</h1>
<form method="post" action="index.html">
<div class="reg_section personal_info">
<input type="text" name="username" value="" placeholder="Campnavn">
<textarea name="textarea" id="description" placeholder="Beskrivelse"></textarea>
</div>
<div>
<span class="submit" style="text-align: left; padding: 0 10px;"><input TYPE="button"name="commit" value="Tilføj" onclick="placeMarker(currentMarker, document.getElementById('description'));"></span>
<span class="submit" style="text-align: right; padding: 0 10px;"><input TYPE="button" name="commit" value="Fortryd" onclick="div_hide();"></span>
</div>
</form>
</section>
</div>
</div>
</div>
<script>
var mapCanvas;
var currentMarker;
function initialize() {
var myOptions = {
center: {lat: 40.740, lng: -74.18},
zoom : 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
mapCanvas = new google.maps.Map(document.getElementById("mapContainer"), myOptions);
var returnValue = "";
var request = new XMLHttpRequest();
// Read the lat/long info for markers
request.open("GET", "db.csv", false);
request.send(null);
returnValue = request.responseText;
// Convert our data from the CVS file to a usable array
var data = CSVToArray(returnValue);
for (var i = 0; i < data.length; i++)
{
// Create a lat/long object readable by Google
var myLatlng = new google.maps.LatLng(parseFloat(data[i][0]), parseFloat(data[i][1]));
// Generate a marker from the lat/long object and add it to the map
var marker = new google.maps.Marker({
position: myLatlng,
map: mapCanvas,
title: data[i][2],
description: data[i][3]
});
}
var imageBounds = {
north: 40.773941,
south: 40.712216,
east: -74.12544,
west: -74.22655
};
historicalOverlay = new google.maps.GroundOverlay(
'http://i.stack.imgur.com/0mgx2.jpg',
imageBounds);
historicalOverlay.setMap(mapCanvas);
// This event listener calls addMarker() when the map is clicked.
google.maps.event.addListener(historicalOverlay, 'click', function(e) {
console.log("clicked'");
currentMarker = e.latLng;
infowindow.close();
div_show();
});
//Changes zoom levels when the projection is available.
google.maps.event.addListenerOnce(mapCanvas, "projection_changed", function(){
mapCanvas.setMapTypeId(google.maps.MapTypeId.HYBRID); //Changes the MapTypeId in short time.
setZoomLimit(mapCanvas, google.maps.MapTypeId.ROADMAP);
setZoomLimit(mapCanvas, google.maps.MapTypeId.HYBRID);
setZoomLimit(mapCanvas, google.maps.MapTypeId.SATELLITE);
setZoomLimit(mapCanvas, google.maps.MapTypeId.TERRAIN);
mapCanvas.setMapTypeId(google.maps.MapTypeId.ROADMAP); //Sets the MapTypeId to original.
});
// InfoWindow content
var content = '<div id="iw-container">' +
'<div class="iw-title">title</div>' +
'<div class="iw-content">' +
'<p>Founded in 1824, the Porcelain Factory of Vista Alegre was the first industrial unit dedicated to porcelain production in Portugal. For the foundation and success of this risky industrial development was crucial the spirit of persistence of its founder, José Ferreira Pinto Basto. Leading figure in Portuguese society of the nineteenth century farm owner, daring dealer, wisely incorporated the liberal ideas of the century, having become "the first example of free enterprise" in Portugal.</p>' +
'</div>' +
'<div class="iw-bottom-gradient"></div>' +
'</div>';
// A new Info Window is created and set content
var infowindow = new google.maps.InfoWindow({
content: content,
// Assign a maximum value for the width of the infowindow allows
// greater control over the various content elements
maxWidth: 350
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(mapCanvas, marker);
//title
document.getElementById("iw-title").innerHTML = marker.title;
//description
document.getElementById("iw-content p").innerHTML = marker.description;
});
// Event that closes the Info Window with a click on the map
google.maps.event.addListener(mapCanvas, 'click', function() {
infowindow.close();
});
google.maps.event.addListener(infowindow, 'domready', function() {
// Reference to the DIV that wraps the bottom of infowindow
var iwOuter = $('.gm-style-iw');
/* Since this div is in a position prior to .gm-div style-iw.
* We use jQuery and create a iwBackground variable,
* and took advantage of the existing reference .gm-style-iw for the previous div with .prev().
*/
var iwBackground = iwOuter.prev();
// Removes background shadow DIV
iwBackground.children(':nth-child(2)').css({'display' : 'none'});
// Removes white background DIV
iwBackground.children(':nth-child(4)').css({'display' : 'none'});
// Moves the infowindow 115px to the right.
iwOuter.parent().parent().css({left: '115px'});
// Moves the shadow of the arrow 76px to the left margin.
iwBackground.children(':nth-child(1)').attr('style', function(i,s){ return s + 'left: 76px !important;'});
// Moves the arrow 76px to the left margin.
iwBackground.children(':nth-child(3)').attr('style', function(i,s){ return s + 'left: 76px !important;'});
// Changes the desired tail shadow color.
iwBackground.children(':nth-child(3)').find('div').children().css({'z-index' : '1'});
// Reference to the div that groups the close button elements.
var iwCloseBtn = iwOuter.next();
// Apply the desired effect to the close button
iwCloseBtn.css({opacity: '1', right: '38px', top: '3px', border: '7px solid #fff', 'border-radius': '13px', 'box-shadow': '0 0 5px #7D0F33'});
// If the content of infowindow not exceed the set maximum height, then the gradient is removed.
if($('.iw-content').height() < 140){
$('.iw-bottom-gradient').css({display: 'none'});
}
// The API automatically applies 0.7 opacity to the button after the mouseout event. This function reverses this event to the desired value.
iwCloseBtn.mouseout(function(){
$(this).css({opacity: '1'});
});
});
}
function div_show() {
$('#abc').fadeIn(400);
}
//Function to Hide Popup
function div_hide(){
$('#abc').fadeOut(400);
}
function placeMarker(location, label) {
var marker = new google.maps.Marker({
position: location,
map: mapCanvas,
labelContent : label
});
div_hide();
}
function setZoomLimit(map, mapTypeId){
//Gets MapTypeRegistry
var mapTypeRegistry = map.mapTypes;
//Gets the specified MapType
var mapType = mapTypeRegistry.get(mapTypeId);
//Sets limits to MapType
mapType.maxZoom = 15; //It doesn't work with SATELLITE and HYBRID maptypes.
mapType.minZoom = 15;
}
function CSVToArray(strData, strDelimiter ){
// Check to see if the delimiter is defined. If not,
// then default to comma.
strDelimiter = (strDelimiter || ";");
// Create a regular expression to parse the CSV values.
var objPattern = new RegExp(
(
// Delimiters.
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
// Quoted fields.
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
// Standard fields.
"([^\"\\" + strDelimiter + "\\r\\n]*))"
), "gi");
// Create an array to hold our data. Give the array
// a default empty first row.
var arrData = [[]];
// Create an array to hold our individual pattern
// matching groups.
var arrMatches = null;
// Keep looping over the regular expression matches
// until we can no longer find a match.
while (arrMatches = objPattern.exec( strData ))
{
// Get the delimiter that was found.
var strMatchedDelimiter = arrMatches[ 1 ];
// Check to see if the given delimiter has a length
// (is not the start of string) and if it matches
// field delimiter. If id does not, then we know
// that this delimiter is a row delimiter.
if (strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter))
{
// Since we have reached a new row of data,
// add an empty row to our data array.
arrData.push( [] );
}
// Now that we have our delimiter out of the way,
// let's check to see which kind of value we
// captured (quoted or unquoted).
if (arrMatches[ 2 ]){
// We found a quoted value. When we capture
// this value, unescape any double quotes.
var strMatchedValue = arrMatches[ 2 ].replace(
new RegExp( "\"\"", "g" ),
"\""
);
} else
{
// We found a non-quoted value.
var strMatchedValue = arrMatches[ 3 ];
}
// Now that we have our value string, let's add
// it to the data array.
arrData[ arrData.length - 1 ].push( strMatchedValue );
}
// Return the parsed data.
return( arrData );
}
google.maps.event.addDomListener(window, "load", initialize);
</script>
<body>
CSS
/* Author : iMomen
Website: www.iMomen.com
E-mail : Coder#iMomen.com
*/
#mapContainer {
height: 100%;
width: 100%;
margin-left: 0px;
margin-right: 0px;
margin-bottom: 0px;
margin-top: 0px;
position: relative;
}
#map {
height: 100%;
}
.gm-style-mtc {
display: none;
}
.gmnoprint {
display: none;
}
#abc {
width:100%;
height:100%;
top:0;
left:0;
display:none;
position:fixed;
background-color: rgba(0,0,0, .5);
overflow:auto;
}
div#popupContact {
width: 350px; /*can be in percentage also.*/
margin: 0;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
}
div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
html, body {
height:100%;
width: 100%;
margin-left: 0px;
margin-right: 0px;
margin-bottom: 0px;
margin-top: 0px;
overflow:hidden;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a {
color:#FF3679;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.container {
width: 350px;
margin-left: auto;
margin-right: auto;
}
.reg_section {
padding:0;
margin: 10px 0;
border-bottom: 1px dotted #eee;
}
.reg_section h3 {
font-size: 13px;
margin: 5px 0;
color: #C4A2A2;
}
/* Form */
.register {
text-align: center;
position: relative;
padding: 20px 20px 20px 20px;
background: #fff;
border-radius: 3px;
}
.register:before {
content: '';
position: absolute;
top: -8px;
right: -8px;
bottom: -8px;
left: -8px;
z-index: -1;
background:rgba(255, 173, 200, 0.08);
border-radius:7px;
-webkit-border-radius: 7px;
}
.register h1 {
margin: -20px -20px 0;
line-height: 40px;
font-size: 15px;
font-weight: bold;
color:#694551;
text-align: center;
border-bottom:1px solid #EDEDED;
border-radius: 3px 3px 0 0;
-webkit-box-shadow: 0 1px #f5f5f5;
-moz-box-shadow: 0 1px #f5f5f5;
box-shadow: 0 1px #f5f5f5;
}
.register input[type=text], .register input[type=password] ,.register select,.register textarea {
width: 278px;
}
.register p.terms {
float: left;
line-height: 31px;
}
.register p.terms label {
font-size: 12px;
color: #777;
cursor: pointer;
}
.register p.terms input {
position: relative;
bottom: 1px;
margin-right: 4px;
vertical-align: middle;
}
.register-help {
margin: 20px 0;
font-size: 11px;
text-align: center;
color:#FFFFFF;
}
.register-help a {
color:#FF3679;
text-shadow:0 1px #1E0E13;
}
:-moz-placeholder {
color: #404040 !important;
font-size: 13px;
}
::-webkit-input-placeholder {
color: #ccc;
font-size: 13px;
}
input {
font-family:"Trebuchet MS",tahoma;
font-size: 14px;
}
input[type=text], input[type=password] ,.register select,.register textarea {
margin: 5px;
padding: 0 10px;
height: 34px;
color: #404040;
background: #fff;
border-width: 1px;
border-style: solid;
border-color: #c4c4c4 #d1d1d1 #d4d4d4;
border-radius:3px;
--webkit-border-radius: 5px;
outline:3px solid rgba(200, 105, 137, 0.09);
-moz-outline-radius:7px;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12);
-moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12);
margin:10px 0;
}
input[type=text]:focus, input[type=password]:focus{
border-color:#FFF7F9;
outline-color:rgba(254, 225, 235, 0.7);
outline-offset: 0;
}
input[type=button] {
padding:0 0px;
height: 29px;
width: 100px;
font-size: 12px;
font-weight: bold;
color:#FFFFFF;
text-shadow:0 1px #4D1124;
border-width: 1px;
border-style: solid;
border-color:#693647;
outline: none;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
background-color: #7D0F33;
}
input[type=button]:active {
background: #7D0F33;
-webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.2);
-moz-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.2);
box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.2);
}
.lt-ie9 input[type=text], .lt-ie9 input[type=password] {
line-height: 34px;
}
.register select {
padding:6px 10px;
width: 300px;
color: #777777;
}
.register textarea {
height: 50px;
padding: 10px;
color: #404040;
}
/* About */
.about {
margin:10px auto;
width: 300px;
text-align: center;
color:#EEA5BD;
font-size: 12px;
}
.about a {
padding: 1px 3px;
margin: 0 -1px;
color: #fff;
text-decoration: none;
text-shadow: 0 -1px rgba(0, 0, 0, 0.2);
border-radius: 2px;
}
.about a:hover {
color:#2F0916;
text-shadow: none;
background: #E83671;
}
.links {
zoom: 1;
}
.links:before, .links:after {
content: "";
display: table;
}
.links:after {
clear: both;
}
.links a {
padding: 6px 0;
float: left;
width: 50%;
font-size: 14px;
}
.gm-style-iw {
width: 350px !important;
top: 15px !important;
left: 0px !important;
background-color: #fff;
border-radius: 2px 2px 10px 10px;
}
#iw-container {
margin-bottom: 10px;
}
#iw-container .iw-title {
font-family: 'Open Sans Condensed', sans-serif;
font-size: 22px;
font-weight: 400;
padding: 10px;
background-color: #7D0F33;
color: white;
margin: 0;
border-radius: 2px 2px 0 0;
}
#iw-container .iw-content {
font-size: 13px;
line-height: 18px;
font-weight: 400;
margin-right: 1px;
padding: 15px 5px 20px 15px;
max-height: 140px;
overflow-y: auto;
overflow-x: hidden;
}
.iw-subTitle {
font-size: 16px;
font-weight: 700;
padding: 5px 0;
}
.iw-bottom-gradient {
position: absolute;
width: 326px;
height: 25px;
bottom: 10px;
right: 18px;
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
}
I think you should store the marker object inside an array of object. Ex:
var arrayOfMarkers = [];
for (var i = 0; i < data.length; i++) {
// Create a lat/long object readable by Google
var myLatlng = new google.maps.LatLng(parseFloat(data[i][0]), parseFloat(data[i][1]));
// Generate a marker from the lat/long object and add it to the map
var marker = new google.maps.Marker({
position: myLatlng,
map: mapCanvas,
title: data[i][2],
description: data[i][3]
});
arrayOfMarkers.push(marker);
}
Then use the arrayOfMarkers to iterate the event listener for each Info Windows
[Updated - Add Ground Overlay after user clicks the marker]
Please see the demo here : http://codepen.io/dannypranoto/pen/PNdvzb
All you need to do is set up a new function for creating a new Ground Overlay with parameters of imageBound
this.instance = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(40.740, -74.18),
zoom: 13,
});
this.addGroundOverlay = function(data) {
var instance = this.instance;
var groundOverlay = new google.maps.GroundOverlay(
'http://i.stack.imgur.com/0mgx2.jpg',data);
groundOverlay.setMap(instance);
}
Then call the function inside the google.maps.event.addListener(marker, ...)
this.addMarker = function(data) {
var Map = this;
var instance = this.instance;
var content = String.format(this.contentTemplate, data.image_url, data.name, data.summary);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(data.latitude, data.longitude),
title: data.name
});
marker.setMap(instance);
google.maps.event.addListener(marker, 'click', function() {
var imageBound = {
north: 40.773941,
south: 40.712216,
east: -74.12544,
west: -74.22655
}
Map.addGroundOverlay(imageBound);
});
}

Isotope - combination buttons and UI slider not working

I am trying to get Isotope plugin to filter with both cobination buttons and a UI slider but not sure how to go about doing it.
Can any one help me to acheve this.
Here is a link to my problem code pen test case
<h1>Isotope - combination filters</h1>
<div class="filters">
<div class="ui-group">
<h3>Color</h3>
<div class="button-group js-radio-button-group" data-filter-group="color">
<button class="button is-checked" data-filter="">any</button>
<button class="button" data-filter=".red">red</button>
<button class="button" data-filter=".blue">blue</button>
<button class="button" data-filter=".yellow">yellow</button>
</div>
</div>
<div class="ui-group">
<h3>Size</h3>
<div class="button-group js-radio-button-group" data-filter-group="size">
<button class="button is-checked" data-filter="">any</button>
<button class="button" data-filter=".small">small</button>
<button class="button" data-filter=".wide">wide</button>
<button class="button" data-filter=".big">big</button>
<button class="button" data-filter=".tall">tall</button>
</div>
</div>
<div class="ui-group">
<h3>Shape</h3>
<div class="button-group js-radio-button-group" data-filter-group="shape">
<button class="button is-checked" data-filter="">any</button>
<button class="button" data-filter=".round">round</button>
<button class="button" data-filter=".square">square</button>
</div>
</div>
<div class="sliders" data-filter-group="features">
<div class="noUi-target noUi-ltr noUi-horizontal noUi-background" id="slider-range"></div>
<span class="val" id="slider-range-value"></span>
</div>
</div>
<div class="grid">
<div class="color-shape small round red">180.00</div>
<div class="color-shape small round blue">195.00</div>
<div class="color-shape small round yellow">202.00</div>
<div class="color-shape small square red">235.00</div>
<div class="color-shape small square blue">240.00</div>
<div class="color-shape small square yellow">250.00</div>
<div class="color-shape wide round red">255.00</div>
<div class="color-shape wide round blue">275.00</div>
<div class="color-shape wide round yellow">285.00</div>
<div class="color-shape wide square red">290.00</div>
<div class="color-shape wide square blue">295.00</div>
<div class="color-shape wide square yellow">300.00</div>
<div class="color-shape big round red">300.00</div>
<div class="color-shape big round blue">300.00</div>
<div class="color-shape big round yellow">300.00</div>
<div class="color-shape big square red">300.00</div>
<div class="color-shape big square blue">180.00</div>
<div class="color-shape big square yellow">180.00</div>
<div class="color-shape tall round red">180.00</div>
<div class="color-shape tall round blue">180.00</div>
<div class="color-shape tall round yellow">255.00</div>
<div class="color-shape tall square red">255.00</div>
<div class="color-shape tall square blue">255.00</div>
<div class="color-shape tall square yellow">255.00</div>
</div>
$( function() {
// filter functions
var filterFns = {
greaterThan50: function() {
var number = $(this).find('.number').text();
return parseInt( number, 10 ) > 50.00;
},
even: function() {
var number = $(this).find('.number').text();
return parseInt( number, 10 ) % 2 === 0;
}
};
// init Isotope
var $container = $('.isotope').isotope({
itemSelector: '.color-shape',
filter: function() {
var isMatched = true;
var $this = $(this);
for ( var prop in filters ) {
var filter = filters[ prop ];
// use function if it matches
filter = filterFns[ filter ] || filter;
// test each filter
if ( filter ) {
isMatched = isMatched && $(this).is( filter );
}
// break if not matched
if ( !isMatched ) {
break;
}
}
return isMatched;
}
});
// store filter for each group
var filters = {};
$('#filters').on( 'click', '.button', function() {
var $this = $(this);
// get group key
var $buttonGroup = $this.parents('.button-group');
var filterGroup = $buttonGroup.attr('data-filter-group');
// set filter for group
filters[ filterGroup ] = $this.attr('data-filter');
// arrange, and use filter fn
$container.isotope('arrange');
});
// change is-checked class on buttons
$('.button-group').each( function( i, buttonGroup ) {
var $buttonGroup = $( buttonGroup );
$buttonGroup.on( 'click', 'button', function() {
$buttonGroup.find('.is-checked').removeClass('is-checked');
$( this ).addClass('is-checked');
});
});
});
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-family: sans-serif;
}
/* ---- button ---- */
.button {
display: inline-block;
padding: 0.5em 1.0em;
background: #EEE;
border: none;
border-radius: 7px;
background-image: linear-gradient( to bottom, hsla(0, 0%, 0%, 0), hsla(0, 0%, 0%, 0.2) );
color: #222;
font-family: sans-serif;
font-size: 16px;
text-shadow: 0 1px white;
cursor: pointer;
}
.button:hover {
background-color: #8CF;
text-shadow: 0 1px hsla(0, 0%, 100%, 0.5);
color: #222;
}
.button:active,
.button.is-checked {
background-color: #28F;
}
.button.is-checked {
color: white;
text-shadow: 0 -1px hsla(0, 0%, 0%, 0.8);
}
.button:active {
box-shadow: inset 0 1px 10px hsla(0, 0%, 0%, 0.8);
}
/* ---- button-group ---- */
.button-group:after {
content: '';
display: block;
clear: both;
}
.button-group .button {
float: left;
border-radius: 0;
margin-left: 0;
margin-right: 1px;
}
.button-group .button:first-child { border-radius: 0.5em 0 0 0.5em; }
.button-group .button:last-child { border-radius: 0 0.5em 0.5em 0; }
/* ---- isotope ---- */
.grid {
background: #EEE;
max-width: 1200px;
}
/* clear fix */
.grid:after {
content: '';
display: block;
clear: both;
}
/* ui group */
.ui-group {
display: inline-block;
}
.ui-group h3 {
display: inline-block;
vertical-align: top;
line-height: 32px;
margin-right: 0.2em;
font-size: 16px;
}
.ui-group .button-group {
display: inline-block;
margin-right: 20px;
}
/* color-shape */
.color-shape {
width: 70px;
height: 70px;
margin: 5px;
float: left;
}
.color-shape.round {
border-radius: 35px;
}
.color-shape.big.round {
border-radius: 75px;
}
.color-shape.red { background: red; }
.color-shape.blue { background: blue; }
.color-shape.yellow { background: yellow; }
.color-shape.wide, .color-shape.big { width: 150px; }
.color-shape.tall, .color-shape.big { height: 150px; }
/* Functional styling for range slider;
* These styles are required for noUiSlider to function.
* You don't need to change these rules to apply your design.
*/
.noUi-target,
.noUi-target * {
-webkit-touch-callout: none;
-webkit-user-select: none;
-ms-touch-action: none;
touch-action: none;
-ms-user-select: none;
-moz-user-select: none;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.noUi-target {
position: relative;
direction: ltr;
width: 62%;
margin-left: 20px;
}
.noUi-base {
width: 100%;
height: 100%;
position: relative;
z-index: 1; /* Fix 401 */
}
.noUi-origin {
position: absolute;
right: 0;
top: 0;
left: 0;
bottom: 0;
}
.noUi-handle {
position: relative;
z-index: 1;
}
.noUi-stacking .noUi-handle {
/* This class is applied to the lower origin when
its values is > 50%. */
z-index: 10;
}
.noUi-state-tap .noUi-origin {
-webkit-transition: left 0.3s, top 0.3s;
transition: left 0.3s, top 0.3s;
}
.noUi-state-drag * {
cursor: inherit !important;
}
/* Painting and performance;
* Browsers can paint handles in their own layer.
*/
.noUi-base {
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
/* Slider size and handle placement;
*/
.noUi-horizontal {
height: 18px;
}
.noUi-horizontal .noUi-handle {
width: 35px;
height: 26px;
left: -17px;
top: -5px;
}
.noUi-vertical {
width: 18px;
}
.noUi-vertical .noUi-handle {
width: 35px;
height: 26px;
left: -6px;
top: -5px;
}
/* Styling;
*/
.noUi-background {
background: #EEE linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.2)) repeat scroll 0% 0%;
box-shadow: inset 0 1px 1px #f0f0f0;
}
.noUi-connect {
background: #3FB8AF;
box-shadow: inset 0 0 3px rgba(51,51,51,0.45);
-webkit-transition: background 450ms;
transition: background 450ms;
}
.noUi-origin {
border-radius: 2px;
}
.noUi-target {
border-radius: 8px;
border: 1px solid #D3D3D3;
box-shadow: inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;
}
.noUi-target.noUi-connect {
box-shadow: inset 0 0 3px rgba(51,51,51,0.45), 0 3px 6px -5px #BBB;
}
/* Handles and cursors;
*/
.noUi-draggable {
cursor: w-resize;
}
.noUi-vertical .noUi-draggable {
cursor: n-resize;
}
.noUi-handle {
border-radius: 8px;
background: #7D64B1;
cursor: grab;
}
.noUi-active {
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.8) inset;
cursor: grabbing;
}
/* Handle stripes;
*/
.noUi-handle:before,
.noUi-handle:after {
content: "";
display: block;
position: absolute;
height: 14px;
width: 1px;
background: #E8E7E6;
left: 14px;
top: 6px;
}
.noUi-handle:after {
left: 19px;
}
.noUi-vertical .noUi-handle:before,
.noUi-vertical .noUi-handle:after {
width: 14px;
height: 1px;
left: 6px;
top: 14px;
}
.noUi-vertical .noUi-handle:after {
top: 17px;
}
/* Disabled state;
*/
[disabled].noUi-connect,
[disabled] .noUi-connect {
background: #B8B8B8;
}
[disabled].noUi-origin,
[disabled] .noUi-handle {
cursor: not-allowed;
}
.val{
margin: 9px 0px 0px;
width: 8%;
display: block;
}
.color-shape{
text-indent:-9999px;
}
If any one can help it would be much appreciated.
Let’s give it a try. See my demo on CodePen
The trick is to use a filter function for Isotope. Rather than changing the filter, we can change the values used in the filter logic. For this demo, we have two values: the buttonFilter and the sliderValue. I’ve set the filter function to check if the item matches the buttonFilter AND has a text value that is greater than or equal to the sliderValue.
// external js: isotope.pkgd.js
$(document).ready( function() {
var sliderValue = 180;
// create the slider;
var rangeSlider = document.getElementById('slider-range');
noUiSlider.create(rangeSlider, {
start: [ 180 ],
range: {
'min': [ 180 ],
'max': [ 300 ]
}
});
// create the slider range value;
var rangeSliderValueElement = document.getElementById('slider-range-value');
rangeSlider.noUiSlider.on('update', function( values, handle ) {
rangeSliderValueElement.innerHTML = values[handle] + " cm";
});
// store filter for each group
var buttonFilters = {};
var buttonFilter = '*';
// init Isotope
var $grid = $('.grid').isotope({
itemSelector: '.color-shape',
// use filter function
filter: function() {
var $this = $(this);
var isMinSize = parseFloat( $this.text() ) >= sliderValue;
return $this.is( buttonFilter ) && isMinSize;
}
});
$('.filters').on( 'click', '.button', function() {
var $this = $(this);
// get group key
var $buttonGroup = $this.parents('.button-group');
var filterGroup = $buttonGroup.attr('data-filter-group');
// set filter for group
buttonFilters[ filterGroup ] = $this.attr('data-filter');
// combine filters
buttonFilter = concatValues( buttonFilters ) || '*';
console.log( buttonFilter )
// set filter for Isotope
$grid.isotope();
});
// filter isotope on slider set
rangeSlider.noUiSlider.on( 'set', function( textValues, handle, values ) {
sliderValue = values[ handle ];
$grid.isotope();
});
// change is-checked class on buttons
$('.button-group').each( function( i, buttonGroup ) {
var $buttonGroup = $( buttonGroup );
$buttonGroup.on( 'click', 'button', function() {
$buttonGroup.find('.is-checked').removeClass('is-checked');
$( this ).addClass('is-checked');
});
});
});
// flatten object by concatting values
function concatValues( obj ) {
var value = '';
for ( var prop in obj ) {
value += obj[ prop ];
}
return value;
}

IE7 Modal dialog - Positioning wrong?

Update
I found the actual issue.
In my code I am referencing the height of the overlay,
In all browsers except IE7 this is the same as the window size, however in IE7 this is the document size.
So I changed it to reference the window size and it works :).
So my question now is, Why does IE7 do this, and am I correct is assuming IE7 is the foul ball here?
Original
I am creating a modal dialog script (for my own use).
The code works perfectly in.
Google chrome,
Firefox,
IE8+
However in IE7 The positioning is all wrong.
Example
These are the positioning values I get in IE9 vs IE7 (keep in mind that the values are smaller than a normal window as i have the dev tools open.)
IE7
left: 367px;
top: 1409px;
IE9
left: 369.5px;
top: 122.5px;
What do I need to do to fix this?
The CSS
Note that this css has some strange rules such as the body tag for testing purposes only.
Note that I am aware that rgba, box-shadow etc does not work in css3 supportless browsers,
I will fix this when the dialog functions properly.
body {
padding: 0;
margin: 0;
color: #fff;
height: 3000px;
}
#modal-overlay {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 9999;
display: none;
}
#modal-dialog {
display: none;
background: #000;
border-bottom: 1px solid #141414;
border-right: 1px solid #141414;
border-top: 1px solid #121212;
border-left: 1px solid #121212;
position: absolute;
z-index: 99999;
-webkit-box-shadow: 3px 3px 10px #000000;
-moz-box-shadow: 3px 3px 10px #000000;
box-shadow: 3px 3px 10px #000000;
}
#modal-element{
margin-top: 16px;
overflow-x: hidden;
overflow-y: auto;
}
#test, #test2 {
display: none;
width: 800px;
padding: 5px;
}
#test2 {
width: 600px;
}
#modal-close {
position: absolute;
background-image: url('close.png');
width: 16px;
height: 16px;
top: -5px;
right: -5px;
cursor: pointer;
}
#modal-title {
position: absolute;
top: -10px;
left: 5px;
color: #fff;
font-size: 16px;
font-weight: bold;
}
#modal-close:hover {
-webkit-box-shadow: inset -1px -1px 10px rgba(0,0,0,0.8);
-moz-box-shadow: inset -1px -1px 10px rgba(0,0,0,0.8);
box-shadow: inset -1px -1px 10px rgba(0,0,0,0.8);
}
#modal-close:active {
-webkit-box-shadow: inset -5px -5px 10px rgba(0,0,0,0.8);
-moz-box-shadow: inset -5px -5px 10px rgba(0,0,0,0.8);
box-shadow: inset -5px -5px 10px rgba(0,0,0,0.8);
}
The Javascript
(function($) {
$.widget("hailwood.modal", {
options: {
width: null,
height: null,
title: '',
closeOnEscape: true,
modal: true
},
self: {},
_create: function() {
//setup our elements
var self = this;
this.body = $('body');
this.content = self.element;
this.place = $('<div id="modal-place" style="display:none;"></div>');
this.dialog = $('<div id="modal-dialog"><div id="modal-element"></div></div>');
this.stuff = $('#modal-element', this.dialog);
this.overlay = $('<div id="modal-overlay"></div>');
this.title = $('<div id="modal-title">' + this.options.title + '</div>');
this.closeButton = $('<div id="modal-close"></div>');
//shove the placeholder element in
this.content.after(this.place);
//capture width and height
this.orig_width = (this.options.width === null ? this.content.outerWidth(true) : this.options.width);
this.orig_height = (this.options.height === null ? this.content.outerHeight(true) : this.options.height);
//insert elements into the dom
this.body.prepend(
this.overlay.prepend(
this.dialog.prepend(
this.stuff.prepend(this.content)
)
.prepend(this.closeButton)
.prepend(this.title)));
//make the content visible
this.content.show();
this.refresh(this);
//show the overlay and dialog
this.overlay.fadeIn('medium', function(){
self.dialog.show('slide', {direction: 'down'}, 'medium');
});
//setup the resize handler
$(window).resize(function() {
self.refresh();
});
this.closeButton.click(function() {
self.close();
});
if (this.options.closeOnEscape)
$(document).bind('keyup.hailwood.modal', function(e){
if (e.keyCode == 27)
self.close();
});
//setup close handler
this.self = this;
},
close: function() {
this.destroy();
},
refresh: function() {
var self = this;
if (self.overlay.length == 0 || self.dialog.length == 0)
return false;
self.height = self.orig_height;
self.width = self.orig_width;
//make an adjustment to the height if it is bigger than the overlay
var s1 = self.height;
self.height = (self.height > self.overlay.height() ? self.overlay.height() - 20 : self.height);
var diff = (s1 === self.height ? 0 : 16);
//set the dialog height and width
self.dialog.height(self.height);
self.dialog.width(self.width);
self.stuff.height(self.height -diff);
self.stuff.width(self.width);
//position the dialog
self.left = (self.overlay.width() / 2) - (self.dialog.outerWidth() / 2);
self.top = (self.overlay.height() / 2) - (self.dialog.outerHeight() / 2);
self.dialog.css({left : self.left, top : self.top});
},
destroy: function() {
var self = this;
self.dialog.hide('slide', {direction: 'down'} ,'medium', function() {
self.place.after(self.content.hide());
self.place.remove();
self.dialog.remove();
$(window).unbind('.hailwood.modal');
$(document).unbind('hailwood.modal');
self.overlay.fadeOut('medium', function() {
self.overlay.remove();
});
});
$.Widget.prototype.destroy.call(this);
}
});
/*
* Remember what I said in the first comment?
* we pass in jQuery here so it gets aliased as $
*/
})(jQuery);
Try removing this line:
body {
height: 3000px;
}
Didn't affect FF when I tested, and I really don't see a use for it anyways.
It's always best to remove unnecessary code when you're trying to get CSS stuff to work so you can nail down the source of the problem, unless you think that box-shadow might be related to your positioning problem.

Categories