简体   繁体   中英

dynamically call function javascript

What I want to do is to separate all my JavaScript from the page, so it works for all with disabled JavaScript, but also be able to compile it using closure compiler's advanced compiling (http://closure-compiler.appspot.com/home).

Here is how I started:

From...

<a href="javascript:doMultiple('download', 'release');">Create archive</a>

to...

<a class="javascript doMultiple download release" href="ca.php">CreateArchive</a>

Then I loop all objects to find what have the class javascript first, etc: (links is an array of the a tags)

for (i = 0; i < links.length; i = i + 1) {
    if (links[i].className.substr(0, 10) === "javascript") {
        jsArray = links[i].className.split(" ");
        links[i].style.display = "inline";
        if (links[i].addEventListener) {
            links[i].addEventListener("click", window[jsArray[1]], false);
        } else {
            links[i].onclick = window[jsArray[1]];
        }
        links[i].href = "#";
    }
}

With this method javascript compressors will remove the function doMultiple because it's unused because it dosnt know I have a class with that...

And my question is, how can I solve this, and if I can't, can I somehow get rid of the window[jsArray[1]] and do solve that in another way? Because I think that is not the best way to do it.

A class can also be:

<a class="javascript popUp register.php 350 300" href="register.php">Register</a>

So I want to use this method for adding all JavaScript dynamically.

Best regards,
Johan Svensson

You shouldn't need to make things complicated. It's better to attach an event to your DOM element.

I would highly suggest you to use a JavaScript framework like jQuery, or even you can achieve this using plain JavaScript.

For instance

<a href="#" id="createArchive" class="remove otherClass">Create archive</a>

OR

<a href="#" id="createArchive" class="release otherClass">Create archive</a>

And for JavaScript:

var element = document.getElementById("createArchive");

var handler = function() {
        // this line will execute only on IE
        // you need an if-else case to test
        // against the browser other than IE
        // and use this.class.split
        var classes = this.className.split(' ');

        doMultiple('download', classes[0]);
        // or anything you want to on this click event
};

if (element && element.attachEvent) {
    // This is for IE
    element.attachEvent("onclick", handler);
}
else if (element && element.addEventListener) {
    // This is for rest of the world
    element.addEventListener("click", handler, false);
}

And if you use jQuery, life is simple

$("#createArchive").bind("click", function() {
    doMultiple('download', 'release');
});

That's it, and also mind that there's no JavaScript code in your HTML.

Question 2

For Google Closure Compiler, you have to use exclude the function that you don't want to be compiled/minified.

You should have a .JS file which will contain the function names to be excluded.

Your exclude.js should contain the signature of the functions like:

function doMultiple() { }
function popUp() { }

And run this from your command line to compile using closure compiler

java -jar .\compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js input_script_file.js --js_output_file=compiled.min.js --externs exclude.js

Hope this help. Please feel free to ask any question

First of all, use var keyword for local variables . The variable jsArray is global, because you did not precede it with var keyword, which is basically wrong (it should not be global in this case).

Second, you can pass additional data by using data- attributes of tags . So the following:

<a class="javascript popUp register.php 350 300" href="register.php">Register</a>

can be changed to the more meaningful:

<a data-window-type="popUp" data-popup-height="350" data-popup-width="300" href="register.php">Register</a>

So you have all the data previously stored within class attribute (unless it was redundant). Accessing it is as simple, as accessing any other tag attribute.

When it comes to your current code, I believe it is over-complicated and I am not sure what you wanted to achieve. Just follow the above rules and your code may be a lot simpler.

I'm glad that someone is trying to get rid of "javascript:" calls from links. :-D

It's fairly simple. Dividing it into "hierarchical" steps, this is what you gotta do:

  1. Loop through the links which have the class name you specified;
  2. Bind them to an event listener that will trigger whatever the action is.

As an initial note, you should think of a better approach to handle this. Simply "converting" a JavaScript call to that isn't something good because it will 1) require ugly hacks to accomplish what you want and 2) still go against the content semantics: classes names are content too; they're not intended to serve as behavior or styling.

After you think of a better approach -- I'm sure you'll find one easily --, you'll basically do what's you're already doing; it just needs some JavaScript love:

First, define the action.

function the_action(event)
{
    // Prevents the browser of following the link's href.
    // "javascript:void(0)" or "#" are for dumbs. ;-)
    event.preventDefault();

    // You can reuse the original href!
    // (like any other attribute or element property)
    // "this" is the DOM element.
    var link_url = this.getAttribute('href');

    alert('lol!');
}

Now, a better way to loop through those links and adding the listener:

var selector = 'a.foobar'
  , links = document.querySelectorAll(selector);

i = links.length; while(i--)
{
    links[i].addEventListener('click', the_action, false);
}

Note that I am defining the function before the loop because if I put it inside the addEventListener call, it'll create a new Function object for each element in the list.

Note also that, in the above snippets, I used code available only in modern browsers. If you have to support IE, I recommend you to get a simple JavaScript library that will "standardize" things. About this, you can choose jQuery -- I dislike it, but that's for another long conversation --, Mootools, Mandoo and others. It's about philosophy/taste. :-)

Picking a library will make your code cleaner, too. Just keep it good!

Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM