1

Fiddle (Uses JQuery) - http://jsbin.com/ponikasa/1/edit

I know JQuery is Javascript, but for the sake of an argument how do you write the following in pure Javascript without the need for a js library like JQuery?

$(document).ready(function() {
  $('.preview-site').on('click', function(){
    window.open('javascript:document.write("'+ $('.workflow').val() +'")', 'Opened Page', 'width=660, height=440');
    return false;
  });
});

I tried this, but doesn't work.
Any help is greatly appreciated.

window.onload = function() {
  var preview = document.getElementsByClassName("preview-site"),
      code = document.getElementsByClassName("workflow")[0].value;

  preview.onClick = function() {
    window.open('javascript:document.write("'+ code = +'")', 'Opened Page', 'width=660, height=440');
    return false;
  }
}
2
  • firstly code is an array so it should be code[0].value Commented Mar 17, 2014 at 0:06
  • 4
    No point in editing/fixing code after each comment... Commented Mar 17, 2014 at 0:16

2 Answers 2

5

Well to write in javascript you would do the following

document.addEventListener('DOMContentLoaded', function() {
  var previewSite = this.querySelectorAll('.preview-site');

  var handler = function() {
    var workflow = document.querySelector('.workflow')
    window.open('javascript: document.write(' + workflow.value + ')', 'Opened Page', 'width=660, height=440')
    return false;
  };

  for( var i = 0; i < previewSite.length; i++) {
    previewSite[i].addEventListener('click', handler);    
  }
});

The problem you had is getElementsByClassName returns a collection, so you cannot use value or onclick on the collection.

I use querySelectorAll because it's easier and has almost better support that getElementsByClassName

I don't usually answer questions like this, but I am highly supportive of anyone that uses jQuery that want's to actually learn javascript it's self

also, in your question, you have onClick, for the event handler you want onclick

For one minor performance improvement you could move workflow out of handler, that way it won't fetch it on every click, only do this if you don't intend to add dynamic .workflow

Yeah, and also. (as pointed out in comments) window.onload is not the same as document ready, window.onload will wait for images & media to be fully loaded, so use DOMContentLoaded

Sign up to request clarification or add additional context in comments.

1 Comment

Sorry been doing a bit of reading. Anyway JSLint said to not make functions inside of loops. I removed the loop to satisfy JSBin - jsbin.com/ponikasa/2/edit The page is opened, but the value is not being embedded as the html of the new dom. Can you explain why this is?
3

One of the things jQuery selectors do is try to abstract the "array" when calling functions and assigning handlers. Consider something like this:

$('.preview-site').on('click', function(){
    // code
});

This code doesn't just assign the click handler. On a lower level than that presented by the jQuery interface, this iterates the array of .preview-site elements and assigns the click handlers to each element. Sometimes it's one element, sometimes it's many. (Sometimes it's none.) jQuery makes the interface the same regardless of the count.

Without it, you need to handle that difference explicitly. These values are arrays:

var preview = document.getElementsByClassName("preview-site"),
    code = document.getElementsByClassName("workflow");

Even if each one only finds a single element by that class name, the result from document.getElementsByClassName() is an array. So even if the array has only one element, it's still an array. And you can't assign a handler to an array, you need to assign it to each element in the array. Potentially something like this:

for (var i = 0; i < preview.length; i++) {
    preview[i].addEventListener('click', function() {
        window.open('javascript:document.write("'+ code[i].value[0] +'")', 'Opened Page', 'width=660, height=440');
        return false;
    }
}

Naturally, you'd probably want to put in some checks to ensure that the two arrays are the same length before assuming that for each preview element there exists a code element. But the principle is the same. You just need to account for the enumeration of the array manually.

3 Comments

use object.addEventListener instead of object.click for a better 1:1 and a sidenote: same should be done for the window.ready : use addEventListener instead.
Good point, I hadn't even thought to address the rest of the code. Just the main point about the array iteration. I've updated the answer, though I'm sure there are additional improvements that can be made. Thanks!
@Connor I too was not looking close enough or giving a proper translation. I just saw that OP went from $(document).ready to window.onload which isn't really the same thing (but you showed that in your post, so +1)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.