1

So I'm building a moch website and I'm adding a image zooming thingy with CSS3 and JavaScript, so first here is my code.

HTML:

<img id="img" onclick="image()" class="contentimgleft" src="test.jpg">

CSS:

.contentimgleft {
    float: left;
    margin: 5px 5px 5px 10px;
    background-color: #888888;
    width: 25%;
    height: 25%;
    -webkit-transition: all .4s linear;
    -moz-transition: all .4s linear;
    -o-transition: all .4s linear;
    -ms-transition: all .4s linear;
    transition: all .4s linear;
}
.contentimgleftl {
    float: left;
    margin: 5px 5px 5px 10px;
    background-color: #888888;
    width: 97%;
    height: 98%;
    -webkit-transition: all .4s linear;
    -moz-transition: all .4s linear;
    -o-transition: all .4s linear;
    -ms-transition: all .4s linear;
    transition: all .4s linear;
}

JS:

function image() {
    if (document.getElementById("img").className.match(/(?:^|\s)contentimgleft(?!\S)/) ) {
        document.getElementById("img").className="contentimgleftl";
    } else {
        document.getElementById("img").className="contentimgleft";
    }
}

Now this works perfectly, until you have more than one image. So what I'm looking for is a better system that achieves the same results. I've tried a couple of things but it keeps coming back to having JavaScript code that works for all the images but zooms each one individually.

.contentimgleft and .contentimgleftl are the same except for the width and height. So I'm hoping there is some way to just change these two styles to individual images with the same JavaScript code?

Also note that the is a class for right floated images as well but I omitted them for simplicity as they are exactly the same.

I tried making a jsfiddle but it didn't like the (/(?:^|\s) bit for some reason.

andyb
  • 43,435
  • 12
  • 121
  • 150
Joel
  • 278
  • 2
  • 5
  • 10

1 Answers1

4

IDs are unique, although there is nothing to stop you using the same ID more than once in a document. However, if you have a duplicate ID then document.getElementById("img") will usually return the first one - see behavior of javascript getElementById() when there are elements with duplicate IDs in HTML DOM?. So your code will only ever be manipulating the first id="img" element, no matter which one is clicked.

So you should remove the id attribute or have different id attribute values for each image. I doubt that you really need an id so in my example below they have been removed.

If the id is removed, there needs to be a way of making the image() function work on the img that is clicked. JavaScript has (at its core) the concept of scope which we can use to make each function execute on the correct image.

One way to do that is passing the argument this to the onclick function to access the HTML element that is handling the event - see How does the "this" keyword work?

HTML

<img onclick="image(this)" class="contentimgleft" src="http://lorempixel.com/50/50/abstract/1"/>
<img onclick="image(this)" class="contentimgleft" src="http://lorempixel.com/50/50/abstract/2"/>

JavaScript

function image(img) {
    if (img.className.match(/(?:^|\s)contentimgleft(?!\S)/)) {
        img.className = "contentimgleftl";
    } else {
        img.className = "contentimgleft";
    }
}

see demo

To answer the CSS question, yes you can declare the duplicate properties once and depending how you do it, you might need to change the way the JavaScript is matching class names.

If all the <img> elements require the same style, simply use

img {
    float: left;
    margin: 5px 5px 5px 10px;
    background-color: #888888;
    width: 25%;
    height: 25%;
    -webkit-transition: all .4s linear;
    -moz-transition: all .4s linear;
    -o-transition: all .4s linear;
    -ms-transition: all .4s linear;
    transition: all .4s linear;
}
.contentimgleftl {
    width: 97%;
    height: 98%;
}

But if you want, you can use another CSS class for the common properties, for example

.zoomable {
    float: left;
    margin: 5px 5px 5px 10px;
    background-color: #888888;
    width: 25%;
    height: 25%;
    -webkit-transition: all .4s linear;
    -moz-transition: all .4s linear;
    -o-transition: all .4s linear;
    -ms-transition: all .4s linear;
    transition: all .4s linear;
}
.contentimgleftl {
    width: 97%;
    height: 98%;
}

with the following change to the HTML

<img onclick="image(this)" class="zoomable" src=""/>

However, the JavaScript would need changing to add or remove the contentimgleftl class rather than replace the img's className, because if you just replace it, you will lose all the .zoomable style.

"hasClass" with javascript?, How do I add a class to a given element?, Remove CSS class from element with JavaScript (no jQuery) might be useful if you decide to use that approach.

Community
  • 1
  • 1
andyb
  • 43,435
  • 12
  • 121
  • 150
  • Thanks a bunch, changing my code as we speak! Cant say i completly understand the argument "this" but it works perfectly. – Joel Feb 25 '14 at 01:50
  • http://www.quirksmode.org/js/this.html#link4 might help explain the `this` keyword in this scenario - "If you want to use this for accessing the HTML element that is handling the event, you must make sure that the this keyword is actually written into the `onclick` property" – andyb Feb 25 '14 at 08:46