I have posted about this already, but I think my question was poorly explained. I have multiple divs with class of "popupEdit".
I want to be able to target these using getElementsByClassName.....the result being a popup with some input field. See the code below.
I know that getElementsByClassName returns an array of all the elements with the class EditQuestion, but I have failed to write a function that works to use this array. My lack of skill (I'm a newbie).
Could someone give me the solution so I have something I can study. Apologies for asking directly for the answer...I have tried numerous things without success.
Many thanks

HTML

   <button class="EditQuestion">Edit</button>
   <div class="overlay2"></div>
   <div class="popupEdit">
   <h2>Edit Question, some input box here..</h2>
   <button class="CloseBtn2">Close</button>
   </div> 

JS

     window.onload = function () {

        document.getElementsByClassName("EditQuestion").onclick = function () {
         var overlay2 = document.getElementsByClassName("overlay2");
         var popupEdit = document.getElementsByClassName("popupEdit");
         overlay2.style.display = "block";
         popupEdit.style.display = "block";
       };

       document.getElementsByClassName("CloseBtn2").onclick = function () {
         var overlay2 = document.getElementsByClassName("overlay2");
         var popupEdit = document.getElementsByClassName("popupEdit");
         overlay2.style.display = "none";
       popupEdit.style.display = "none";
       };
     };

CSS

      button.EditQuestion{
       padding: 0;
       border: none;
       background: none;
       color:#A8A8A8;
       font-weight: bold;
      }

      button.CloseBtn2 {
       padding: 0;
       border: none;
       background: none;
       position:absolute;
       right:10px;
       top:5px;
      }

      .popupEdit {
        display:none;
        position:fixed;
        left:40%;        
        top:30%;         
        width:600px;     
        height:150px;
        margin-top:-75px;
        margin-left:-150px;
        background:#FFFFFF;
        border:1px solid #000;
        z-index:100000;      
      }

    .overlay2 {
      display:none;    
      position:fixed;  
      left:0px;        
      top:0px;         
      width:100%;      
      height:100%;     
      background:#000; 
      opacity:0.5;     
      z-index:99999;   
    }

Edited version - I have tried to use querySelectorAll as suggested by TJ Crowder....the querySelector works, but when I add in the for loop and change to querySelectorAll it fails....any suggestions

 window.onload = function () {

 document.querySelectorAll(".EditQuestion").onclick = function () {
 var overlay2 = document.querySelectorAll(".overlay2");
 var popupEdit = document.querySelectorAll(".popupEdit");
 var index;
        for (index = 0; index < overlay2.length; ++index) {
        overlay2[index].style.display = "none";
        popupEdit[index].style.display = "block";
    }
 };

 document.querySelectorAll(".CloseBtn2").onclick = function () {
     var overlay2 = document.querySelectorAll(".overlay2");
     var popupEdit = document.querySelectorAll(".popupEdit");
     var index;
        for (index = 0; index < overlay2.length; ++index) {
        overlay2[index].style.display = "none";
        popupEdit[index].style.display = "block";
    }
};

};

有帮助吗?

解决方案

getElementsByClassName (on the browsers where it exists) returns a list, not a single element. So this line and similar:

overlay2.style.display = "none";

...fails, because the list doesn't have a style property.

If you just want to handle the first match, you can grab it via [0]:

overlay2[0].style.display = "none";

(That will fail if there are no matches, though.) Or, since getElementsByClassName isn't as well-supported as querySelector, you might prefer:

overlay2 = document.querySelector(".overlay2"); // Gives you the first match; note the dot
overlay2.style.display = "none";

Or if you want to loop through all of them, you need a loop:

var index;
for (index = 0; index < overlay2.length; ++index) {
    overlay2[index].style.display = "none";
}

To get the list for that loop, either use getElementsByClassName as you are currently (but it won't work on IE8), or use querySelectorAll (which will):

overlay2 = document.querySelectorAll(".overlay2"); // Gives you a list

Could you show me how you would incorporate this loop into the JS function.

I don't think you want a loop; you just want to handle the specific overlay and popup related to the button, right?

I'd probably change the HTML slightly so that each group has a group div or similar around it:

<div class="question"><!-- Wrapper div for each question -->
    <button class="EditQuestion">Edit</button>
    <div class="overlay2" style="display: none"></div><!-- Note I've hidden ... -->
    <div class="popupEdit" style="display: none">     <!-- ...these by default -->
        <h2>Edit Question, some input box here..</h2>
        <button class="CloseBtn2">Close</button>
    </div> 
</div>

...and use event delegation:

var container = document.getElementById("questions");
hookEvent(container, "click", function(event) {
    var button, group, overlay, display;

    // Find the button that was clicked, if any
    button = event.target;
    while (button && (
          button.tagName.toUpperCase() !== "BUTTON" ||
          !button.className.match(/\bEditQuestion\b|\bCloseBtn2\b/)
        )) {
        button = button.parentNode;
    }
    if (button) {
        // One of our desired buttons was clicked, find the parent
        group = button.parentNode;
        while (group && !group.className.match(/\bquestion\b/)) {
            group = group.parentNode;
        }
        if (group) {
            overlay = group.querySelector(".overlay2");
            display = overlay.style.display === "block" ? "none" : "block";
            overlay.style.display = display;
            group.querySelector(".popupEdit").style.display = display;
        }
    }
});

...where hookEvent looks something like this:

function hookEvent(element, eventName, handler) {
    if (element.addEventListener) {
        element.addEventListener(eventName, handler, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + eventName, function(event) {
            var e = event || window.event;
            if (!e.target) {
                e.target = e.srcElement;
            }
            handler.call(element, e);
        });
    } else {
        throw "addEventListener or attachEvent required";
    }
}

Live Example | Source

The great thing about event delegation is that since you're handling the event on a container, it doesn't matter how much you add or remove questions in the container, it just keeps working.

A lot of the code above is to deal with IE weirdness, and to handle the event delegation. FWIW, a good DOM library can make that all a LOT simpler for you. Here's a jQuery example:

$("selector for the container").on("click", ".EditButton, .CloseBtn2", function() {
    var button = $(this);
    button.closest('.question').find(".overlay2, .popupEdit").toggle(button.is(".EditButton"));
});

其他提示

getElementsByClassName returns NodeList or HTMLCollection.

 document.getElementsByClassName("EditQuestion")[0].onclick = function () { //<-- get the first (and only?) element from the list

If you want to use getElementsByClassName to get the ,Array of all element with that class then :

It is something like below:

var els = document.getElementsByClassName("myclass");

Array.prototype.forEach.call(els, function(el) {
// Do stuff with the element
console.log(el.tagName);
});

 // Or optionally
[].forEach.call(els, function () {...});

Answered by Tim Down on getElementsByClassName

Below is a sample working code for you to get started — http://jsfiddle.net/vVq7E/1.

Also learn to use the following getElementsByClassName , addEventListener, nextElementSibling, element.style which are used in this code

<div class='modules'>
    <button class='edit'>Edit</button>
    <div class='overlay'>
        <p>Hello!</p>
        <button class='close'>Close</button>
    </div>
</div>
...


window.onload = function init() {
    modules = document.getElementsByClassName('modules');
    len = modules.length;
    var i = 0;
    for (; i < len; i++) {
        modules[i].getElementsByClassName('edit')[0].addEventListener('click', showOverlay);
        modules[i].getElementsByClassName('close')[0].addEventListener('click', hideOverlay);
    }
}

function showOverlay() {
    this.nextElementSibling.style.display = 'block';
}

function hideOverlay() {
    var overlays = document.getElementsByClassName('overlay');
    for (var i = 0; i < len; i++) {
        if (overlays[i].style.display === 'block') {
            overlays[i].style.display = 'none';
            return;
        }    
 }


.modules {
    /*optional!*/
    margin:10px;
}
.overlay {
    position:absolute;
    width:100%;
    height:100%;
    top:0;
    left:0;
    display:none;
    /*optional!*/
    padding:20px;
    /*optional!*/
    background:yellow;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top