2
\$\begingroup\$

I wrote a jQuery function to show a popup that can be draggable have multiple buttons etc.

Demo

How can I improve this code? I want to try keeping it light and simple but at the same time make it as versatile as possible for all the sorts of popups I might need in future projects.

/*Popup function*/
function popup(config) {

    /*Default config*/
    var title = config["title"];
    var html = config["html"];
    var buttons = config["buttons"];
    var popupClassBase = "popup";
    var popupClass = config["class"] || popupClassBase;
    var popupWrapperClass = config["wrapperClass"] || popupClassBase+"_wrapper";
    var popupOverlayClass = config["overlayClass"] || popupClassBase+"_overlay";
    var popupTitleClass = config["titleClass"] || popupClassBase+"_title";
    var popupContentWrapperClass = config["contentWrapperClass"] || popupClassBase+"_content";
    var popupButtonsWrapperClass = config["buttonsWrapperClass"] || popupClassBase+"_buttons";
    var popupOverflowXClass = config["overflowXClass"] || popupClassBase+"_overflow_x";
    var popupOverflowYClass = config["overflowYClass"] || popupClassBase+"_overflow_y";
    var popupScrollTopClass = config["scrollTopClass"] || popupClassBase+"_scroll_top";
    var popupScrollBottomClass = config["scrollBottomClass"] || popupClassBase+"_scroll_bottom";
    var popupCloseButtonWrapperClass = config["closeButtonWrapperClass"] || popupClassBase+"_close";
    var popupCloseButtonHTML = config["closeButtonHTML"] || "<svg fill=\"#000000\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/></svg>";
    var popupFadeTime = config["fadeTime"] == undefined ? 200:config["fadeTime"];
    var overlay = config["overlay"] == undefined || config["overlay"] ? true:false;
    var overlayClose = config["overlayClose"] ? true:false;
    var draggable = config["draggable"] == undefined || !config["draggable"] ? false:true;
    var closeButton = config["closeButton"] == undefined || !config["closeButton"] ? false:true;
    var position = config["position"] || "center";
    var offsetX = config["offset"] == undefined ? 0:config["offset"]["x"] == undefined ? 0:config["offset"]["x"];
    var offsetY = config["offset"] == undefined ? 0:config["offset"]["y"] == undefined ? 0:config["offset"]["y"];
    var stickToBottom = config["stickToBottom"] == undefined || config["stickToBottom"] ? true:false;

    /*Function*/
    var popup_html = "<div class=\""+popupWrapperClass+"\"><form class=\""+popupClass+"\"><div class=\""+popupTitleClass+"\">"+title+"</div><div class=\""+popupContentWrapperClass+"\">"+html+"</div><div class=\""+popupButtonsWrapperClass+"\">"+getButtons()+"</div><div class=\""+popupCloseButtonWrapperClass+"\">"+popupCloseButtonHTML+"</div></form></div>";
    var popup = $(popup_html);
    popup.css({"opacity": 0, "width": 0, "height": 0});
    var form = popup.children("form");
    form.css("position", "relative");
    var top;
    var dragging = false;
    var fX;
    var fX;
    var y;
    var x;
    var overflow_x;
    var overflow_y;
    function freeze() {
        top = $("html").scrollTop();
        if($("html").css("position") != "fixed" && overlay) {
            $("html").css({"position": "fixed", "top": -top});
        }
    }
    function unfreeze() {
        if($("html").css("position") == "fixed" && !$("."+popupWrapperClass+"[data-overlay]").length) {
            $("html").css("position", "static");
            $("html").scrollTop(-parseInt($("html").css("top")));
            $("html").css("top", 0);
        }
    }
    function open() {
        $("body").append(popup);
        popup.before("<div class=\""+popupOverlayClass+"\"></div>");
        popup.prev("."+popupOverlayClass).css({"position": "fixed", "top": 0, "left": 0, "bottom": 0, "right": 0});
        setDepth();
        setOverlay();
        setCloseButton();
        setDraggable();
        setPosition();
        setOffset();
        overflow();
        scrollTop();
        popup.fadeTo(popupFadeTime, 1);
    }
    function close() {
        form.children(".title").off("mousedown touchstart");
        form.children("."+popupContentWrapperClass).off("scroll");
        popup.off("click mousedown touchstart mousemove touchmove mouseup touchend");
        $(window).off("resize", function() {
            onResize()
        });
        popup.fadeOut(popupFadeTime, function() {
            popup.remove();
            unfreeze();
        });
        popup.prev("."+popupOverlayClass).fadeOut(200, function() {
            popup.prev("."+popupOverlayClass).remove();
        });
    }
    function setOverlay() {
        if(overlay) {
            popup.attr("data-overlay", true).prev("."+popupOverlayClass).show();
            popup.css("z-index");
            popup.prev("."+popupOverlayClass).css("z-index", popup.css("z-index"));
            freeze();
        } else {
            popup.removeAttr("data-overlay").prev("."+popupOverlayClass).hide();
            unfreeze();
        }
    }
    function setDraggable() {
        if(draggable) {
            form.children("."+popupTitleClass).css("cursor", "move");
            if(position == "bottom" && stickToBottom) {
                stickToBottom = false;
                setPosition();
            }
        } else {
            form.children("."+popupTitleClass).css("cursor", "inherit");
        }
    }
    function setCloseButton() {
        if(closeButton) {
            form.children("."+popupCloseButtonWrapperClass).show();
        } else {
            form.children("."+popupCloseButtonWrapperClass).hide();
        }
    }
    function setPosition() {
        switch(position) {
            case "center":
                popup.css({"position": "fixed", "top": "50%", "left": "50%", "bottom": "auto", "right": "auto"});
                form.css({"position": "relative", "top": -form.outerHeight()/2, "left": -form.outerWidth()/2, "bottom": "auto"});
                break;
            case "top":
                popup.css({"position": "fixed", "top": 0, "left": "50%", "bottom": "auto", "right": "auto"});
                form.css({"position": "relative", "top": 0, "left": -form.outerWidth()/2, "bottom": "auto"});
                break;
            case "left":
                popup.css({"position": "fixed", "top": "50%", "left": "0", "bottom": "auto", "right": "auto"});
                form.css({"position": "relative", "top": -form.outerHeight()/2, "left": 0, "bottom": "auto"});
                break;
            case "bottom":
                popup.css({"position": "fixed", "top": "auto", "left": "50%", "bottom": 0, "right": "auto"});
                if(stickToBottom && !draggable) {
                    form.css({"position": "absolute", "top": "auto", "left": -form.outerWidth()/2, "bottom": 0});
                } else {
                    form.css({"position": "relative", "top": -form.outerHeight(), "left": -form.outerWidth()/2, "bottom": "auto"});
                }
                break;
            case "right":
                popup.css({"position": "fixed", "top": "50%", "left": "auto", "bottom": 0, "right": 0});
                form.css({"position": "relative", "top": -form.outerHeight()/2, "left": -form.outerWidth(), "bottom": "auto"});
        }
    }
    function boundary() {
        //Bottom
        if($(window).height() - form.offset().top - form.outerHeight() + $("html").scrollTop() < 0) {
            form.offset({top: $(window).height() - form.outerHeight() + $("html").scrollTop()});
        }
        //Right
        if($(window).width() - form.offset().left - form.outerWidth() < 0) {
            form.offset({left: $(window).width() - form.outerWidth()});
        }
        //Top
        if(form.offset().top - $("html").scrollTop() < 0 && (draggable || position != "bottom")) {
            form.offset({top: $("html").scrollTop()});
        }
        //Left
        if(form.offset().left < 0) {
            form.offset({left: 0});
        }
    }
    function overflow() {
        popup.removeClass(popupOverflowXClass+" "+popupOverflowYClass);
        overflow_x = form.outerWidth() > $(window).width() ? true:false;
        overflow_y = form.outerHeight() > $(window).height() ? true:false;
        if(overflow_x) {
            popup.addClass(popupOverflowXClass);
        }
        if(overflow_y) {
            popup.addClass(popupOverflowYClass);
        }
    }
    function scrollTop() {
        var scrollContent = form.children("."+popupContentWrapperClass);
        //Top
        if(!scrollContent.scrollTop()) {
            popup.addClass(popupScrollTopClass);
        } else {
            popup.removeClass(popupScrollTopClass);
        }
        //Bottom
        if(!(scrollContent.prop("scrollHeight") - scrollContent.height() - scrollContent.scrollTop())) {
            popup.addClass(popupScrollBottomClass);
        } else {
            popup.removeClass(popupScrollBottomClass);
        }
    }
    function setDepth() {
        var depths = [9999];
        $("."+popupWrapperClass).each(function() {
            depths.push(parseInt($(this).css("z-index")));
        });
        var max_depth = Math.max.apply(Math, depths)+1;
        popup.css("z-index", max_depth);
    }
    function sortDepth() {
        var current_depth = popup.css("z-index");
        var depths = [9999];
        $("."+popupWrapperClass).each(function() {
            depths.push(parseInt($(this).css("z-index")));
        });
        var max_depth = Math.max.apply(Math, depths);
        $("."+popupWrapperClass).each(function() {
            var depth = parseInt($(this).css("z-index"));
            if(depth > current_depth) {
                $(this).css("z-index", depth -1);
            }
        });
        popup.css("z-index", max_depth);
    }
    function setOffset(fOffsetX, fOffsetY) {
        fOffsetX = fOffsetX == undefined ? offsetX:fOffsetX;
        fOffsetY = fOffsetY == undefined ? offsetY:fOffsetY;
        fY = form.offset().top;
        fX = form.offset().left;
        form.offset({
            top: fY - fOffsetY,
            left: fX + fOffsetX
        });
        boundary();
    }
    function getOffset() {
        var getOffset = {};
        switch(position) {
            case "center":
            case "left":
            case "right":
                getOffset["y"] = popup.offset().top - form.offset().top - form.outerHeight()/2;
                break;
            case "top":
                getOffset["y"] = popup.offset().top - form.offset().top;
                break;
            case "bottom":
                getOffset["y"] = popup.offset().top - form.offset().top - form.outerHeight();
        }
        switch(position) {
            case "center":
            case "top":
            case "bottom":
                getOffset["x"] = form.offset().left - popup.offset().left + form.outerWidth()/2;
                break;
            case "left":
                getOffset["x"] = form.offset().left - popup.offset().left;
                break;
            case "right":
                getOffset["x"] = form.offset().left - popup.offset().left + form.outerWidth();
        }
        getOffset["y"] = Math.round(getOffset["y"]);
        getOffset["x"] = Math.floor(getOffset["x"]);
        return getOffset;
    }
    function getButtons() {
        var buttons_html = "";
        for(var x = 0; x < buttons.length; x++) {
            var bClass = buttons[x]["class"] ? " class="+buttons[x]["class"]:"";
            var bCheckForm = buttons[x]["checkForm"] ? " data-checkform=true":"";
            var bClose = buttons[x]["close"] === false ? " data-close="+buttons[x]["close"]:"";
            var bValue = buttons[x]["value"] !== undefined  ? " data-value="+buttons[x]["value"]:"";
            var bText = buttons[x]["text"] || "";
            buttons_html += "<button"+bClass+bClose+bCheckForm+bValue+">"+bText+"</button>";
        }
        return buttons_html;
    }
    function debounce(func, wait, immediate) {
        var timeout;
        return function() {
            var context = this, args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };
    function onResize() {
        boundary();
        overflow();
        scrollTop();
    }
    this.open = function(f) {
        var r = $.Deferred();
        open();
        var closed = false;
        popup.on("click", "."+popupButtonsWrapperClass+" button", function(e) {
            e.preventDefault();
            var value = $(this).data("value");
            var checkForm = $(this).data("checkform");
            var autoClose = $(this).data("close");
            if(!form[0].checkValidity() && checkForm) {
                $('<input type="submit">').hide().appendTo(form).click().remove();
            } else {
                if(!closed) {
                    r.notify(value, form);
                }
                if(autoClose !== false) {
                    close();
                    closed = true;
                }
            }
        });
        popup.on("click", "."+popupCloseButtonWrapperClass, function(e) {
            e.preventDefault();
            close();
        });
        form.children("."+popupContentWrapperClass).on("scroll", function() {
            scrollTop();
        });
        $(window).on("resize", function() {
            onResize()
        });
        form.children("."+popupTitleClass).on("mousedown touchstart", function(e) {
            if(draggable) {
                dragging = true;
                fY = form.offset().top;
                fX = form.offset().left;
                y = e.pageY || e.originalEvent.touches[0].pageY;
                x = e.pageX || e.originalEvent.touches[0].pageX;
                form.css("user-select", "none");
            }
        });
        popup.on("mousemove touchmove", function(e) {
            if(dragging && draggable) {
                mY = e.pageY == undefined ? e.originalEvent.touches[0].pageY:e.pageY;
                mX = e.pageX == undefined ? e.originalEvent.touches[0].pageX:e.pageX;
                form.offset({
                    top: fY + mY - y,
                    left: fX + mX - x
                });
                boundary();
            }
        });
        popup.on("mouseup touchend", function(e) {
            if(draggable) {
                dragging = false;
                form.css("user-select", "inherit");
            }
        });
        popup.on("mousedown touchstart", function() {
            if(draggable) {
                sortDepth();
            }
        });
        popup.prev("."+popupOverlayClass).on("click", function() {
            if(overlayClose) {
                close();
            }
        });
        return r.progress(f);
    };
    this.close = function() {
        close();
        return this;
    };
    this.addClass = function(fClass) {
        $(popup).addClass(fClass);
        return this;
    };
    this.removeClass = function(fClass) {
        $(popup).removeClass(fClass);
        return this;
    };
    this.title = function(fTitle) {
        if(fTitle == undefined) {
            return title;
        } else {
            form.children("."+popupTitleClass).html(fTitle);
            title = fTitle;
            return this;
        }
    };
    this.html = function(fHTML) {
        if(fHTML == undefined) {
            return html;
        } else {
            form.children("."+popupContentWrapperClass).html(fHTML);
            html = fHTML;
            return this;
        }
    };
    this.buttons = function(fButtons) {
        if(fButtons == undefined) {
            return buttons;
        } else {
            buttons = fButtons;
            form.children("."+popupButtonsWrapperClass).html(getButtons());
            return this;
        }
    };
    this.overlay = function(fOverlay) {
        if(fOverlay == undefined) {
            return overlay;
        } else {
            overlay = fOverlay ? true:false;
            setOverlay();
            return this;
        }
    };
    this.draggable = function(fDraggable) {
        if(fDraggable == undefined) {
            return popupFadeTime;
        } else {
            draggable = fDraggable ? true:false;
            setDraggable();
            return this;
        }
    };
    this.closeButton = function(fCloseButton) {
        if(fCloseButton == undefined) {
            return closeButton;
        } else {
            closebutton = fCloseButton ? true:false;
            setCloseButton();
            return this;
        }
    }
    this.class = function(fClass) {
        if(fClass == undefined) {
            return popupClass;
        } else {
            form.removeClass(popupClass).addClass(fClass);
            popupClass = fClass;
            return this;
        }
    };
    this.wrapperClass = function(fClass) {
        if(fClass == undefined) {
            return popupWrapperClass;
        } else {
            popup.removeClass(popupWrapperClass).addClass(fClass);
            popupWrapperClass = fClass;
            return this;
        }
    };
    this.overlayClass = function(fClass) {
        if(fClass == undefined) {
            return popupOverlayClass;
        } else {
            popup.prev("."+popupOverlayClass).removeClass(popupOverlayClass).addClass(fClass);
            popupOverlayClass = fClass;
            return this;
        }
    };
    this.titleClass = function(fClass) {
        if(fClass == undefined) {
            return popupTitleClass;
        } else {
            form.children("."+popupTitleClass).removeClass(popupTitleClass).addClass(fClass);
            popupTitleClass = fClass;
            return this;
        }
    };
    this.contentWrapperClass = function(fClass) {
        if(fClass == undefined) {
            return popupContentWrapperClass;
        } else {
            form.children("."+popupContentWrapperClass).removeClass(popupContentWrapperClass).addClass(fClass);
            popupContentWrapperClass = fClass;
            return this;
        }
    };
    this.buttonsWrapperClass = function(fClass) {
        if(fClass == undefined) {
            return popupButtonsWrapperClass;
        } else {
            form.children("."+popupButtonsWrapperClass).removeClass(popupButtonsWrapperClass).addClass(fClass);
            popupButtonsWrapperClass = fClass;
            return this;
        }
    };
    this.contentWrapperClass = function(fClass) {
        if(fClass == undefined) {
            return popupContentWrapperClass;
        } else {
            form.children("."+popupContentWrapperClass).removeClass(popupContentWrapperClass).addClass(fClass);
            popupContentWrapperClass = fClass;
            return this;
        }
    };
    this.overflowXClass = function(fClass) {
        if(fClass == undefined) {
            return popupOverflowXClass;
        } else {
            form.children("."+popupOverflowXClass).removeClass(popupOverflowXClass).addClass(fClass);
            popupOverflowXClass = fClass;
            return this;
        }
    };
    this.overflowYClass = function(fClass) {
        if(fClass == undefined) {
            return popupOverflowYClass;
        } else {
            form.children("."+popupOverflowYClass).removeClass(popupOverflowYClass).addClass(fClass);
            popupOverflowYClass = fClass;
            return this;
        }
    };
    this.scrollTopClass = function(fClass) {
        if(fClass == undefined) {
            return popupScrollTopClass;
        } else {
            form.children("."+popupScrollTopClass).removeClass(popupScrollTopClass).addClass(fClass);
            popupScrollTopClass = fClass;
            return this;
        }
    };
    this.scrollBottomClass = function(fClass) {
        if(fClass == undefined) {
            return popupScrollBottomClass;
        } else {
            form.children("."+popupScrollBottomClass).removeClass(popupScrollBottomClass).addClass(fClass);
            popupScrollBottomClass = fClass;
            return this;
        }
    };
    this.closeButtonWrapperClass = function(fClass) {
        if(fClass == undefined) {
            return popupCloseButtonWrapperClass;
        } else {
            form.children("."+popupCloseButtonWrapperClass).removeClass(popupCloseButtonWrapperClass).addClass(fClass);
            popupCloseButtonWrapperClass = fClass;
            return this;
        }
    };
    this.closeButtonHTML = function(fCloseButtonHTML) {
        if(fCloseButtonHTML == undefined) {
            return popupCloseButtonHTML;
        } else {
            form.children("."+popupCloseButtonWrapperClass).html(fCloseButtonHTML);
            popupCloseButtonHTML = fCloseButtonHTML;
            return this;
        }
    };
    this.fadeTime = function(fFadeTime) {
        if(fFadeTime == undefined) {
            return popupFadeTime;
        } else {
            popupFadeTime = fFadeTime;
            return this;
        }
    };
    this.position = function(fPosition) {
        if(fPosition == undefined) {
            return position;
        } else {
            position = fPosition;
            setPosition();
            offsetX = 0;
            offsetY = 0;
            return this;
        }
    };
    this.offset = function(fOffset) {
        if(fOffset == undefined) {
            return getOffset();
        } else {
            offsetX = fOffset["x"] == undefined ? 0:fOffset["x"] + offsetX;
            offsetY = fOffset["y"] == undefined ? 0:fOffset["y"] + offsetY;
            setOffset(fOffset["x"], fOffset["y"]);
            return this;
        }
    };
    this.overlayClose = function(fOverlayClose) {
        if(fOverlayClose == undefined) {
            return overlayClose;
        } else {
            overlayClose = fOverlayClose ? true:false;
            setPosition();
            return this;
        }
    };
    this.stickToBottom = function(fStickToBottom) {
        if(fStickToBottom == undefined) {
            return stickToBottom;
        } else {
            stickToBottom = fStickToBottom ? true:false;
            offsetX = 0;
            offsetY = 0;
            //Twice, first to undo sticking to bottom and second to move it to original position
            setPosition();
            setPosition();
        }
    }
}

Available options:

Property                 Default value             Example value

title                    ""                         "<h2>Hello World</h2>"
html                     ""                         "<p>Sudo make me a sandwich?</p>"
buttons                  []                         [{
                                                        text: "Cancel",
                                                        value: false
                                                    }, {
                                                        text: "Ok",
                                                        value: true,
                                                        checkForm: true
                                                    }]
class                    "popup"                    "example"
wrapperClass             "popup_wrapper"            "example_wrapper"
overlayClass             "popup_overlay"            "example_overlay"
titleClass               "popup_title"              "example_title"
contentWrapperClass      "popup_content"            "example_content"
buttonsWrapperClass      "popup_buttons"            "example_buttons"
overflowXClass           "popup_overflow_x"         "example_overflow_x"
overflowYClass           "popup_overflow_y"         "example_overflow_y"
scrollTopClass           "popup_scroll_top"         "example_scroll_top"
scrollBottomClass        "popup_scroll_bottom"      "example_scroll_bottom"
closeButtonWrapperClass  "popup_close"              "example_close"
closeButtonHTML          "<svg>*snip*</svg>"        "Close [x]"
fadeTime                 200                        1000
overlay                  true                       false
overlayClose             false                      true
draggable                false                      true
closeButton              false                      true
position                 "center"                   "top"
                                                    "left"
                                                    "bottom"
                                                    "right"
                                                    "center"
offset                   [{                         [{
                             x: 0,                      y: 120,
                             y: 0                   }]
                         }]
stickToBottom            true                       false

Available button options:

Property                 Default value             Example value

text                     ""                        "Ok"
value                                              true
class                                              "example_button"
close                    true                      false
checkForm                false                     true
\$\endgroup\$
  • \$\begingroup\$ Sorry, but your post is off-topic for two reasons: (1) all code to be reviewed must be in the post itself, and (2) broken code is off-topic. \$\endgroup\$ – SirPython Jan 12 '16 at 1:13
  • \$\begingroup\$ 1) added the code into the post....2)It's not broken code, it's code that has a small bug in around 5 lines that does not affect the functionality of the overall code whatsoever. And Code is also not broken when it's missing features that aren't required for it to work. \$\endgroup\$ – seahorsepip Jan 12 '16 at 1:18
  • 1
    \$\begingroup\$ Thanks for adding the code! I wasn't calling your code broken because of the missing features; I was calling it broken because you mention that you have a bug. \$\endgroup\$ – SirPython Jan 12 '16 at 1:19
  • \$\begingroup\$ @seahorsepip Does the above code work as intended? \$\endgroup\$ – Phrancis Jan 12 '16 at 1:21
  • \$\begingroup\$ It's just the function overflow() that doesn't work they way I want it to yet but it doesn't need to work the way i want it to for the current features. \$\endgroup\$ – seahorsepip Jan 12 '16 at 1:23
7
\$\begingroup\$

All those variable declarations at the start of your code are... not good, shall we say. Messy. Each time, all you seem to be doing is checking for existence, and assigning a default if not. That sounds to me like the perfect use case for a defaults object.

var defaults = {
    'title': 'default_title',
    'offsetX': 0,
    'offsetY': 0
    // Add all your other defaults here.
}

Then, you could have a function (let's say getValuesOrDefaults()) that iterates over each item in the passed config, and adds it to an object containing the value of the config parameter, or the default if it doesn't exist. Such a method could look like this:

function getValuesOrDefaults(defaults, values) {
    var keys = Object.keys(defaults);
    var config = {};
    for(var i = 0; i < keys.length; i++) {
        if(values[keys[i]]) {
            config[keys[i]] = values[keys[i]];
        }
        else {
            config[keys[i]] = defaults[keys[i]];
        }
    }
    return config;
}

Now you replace that massive variable-definition block with a call to that method, and when you want to access config values you simply use object access object[key] on the assigned result.

\$\endgroup\$
  • 2
    \$\begingroup\$ Welcome to Code Review! Great work on your first answer! \$\endgroup\$ – Quill Jan 13 '16 at 12:50
  • 2
    \$\begingroup\$ jQuery has a function .extend that does exactly that. \$\endgroup\$ – RoToRa Jan 13 '16 at 13:55
1
\$\begingroup\$

Note: This is not a complete review. I did not have the time to look at everything, but this should help you a bit.

Code duplication

You have some duplicate code in setDepth and sortDepth. Consider moving the code of calculating maxDepth to it's own function and calling that in both other functions.

Styling

I notice that you have a variable popup containing a jquery object. You might want to consider using a convention where variables containing jquery objects start with a $, while normal variables start with regular characters.

Some variables are written with underscores (like_so), while others are written using something like camelCase (likeSo). Choose one, and stick to it.

I noticed a case of an subtraction disguised as a negative number ($(this).css("z-index", depth -1);). Please write it as depth - 1 if you use whitespace around operators or depth-1 if you don't.

Speaking of which: You sometimes use whitespace around operators, and you sometimes do not. (e.g. var max_depth = Math.max.apply(Math, depths)+1;)

Under /*Function*/ (what is that supposed to mean anyway?) you have several variable declarations. I always recommend doing these at the top before any other code. In this series of declarations you mix in calls. I recommend moving those calls down.

Prototype

Javascript has a great future called the prototype chain. An object inherits anything from that prototype. The great thing is: If you put methods there, they are not duplicated every time you make a new object via new popup(). So... move those functions and define them as:

Popup.prototype.makeSandwich = function( type ) {
  return false;
}

Documentation

Your code is missing documentation on how to use various methods.

\$\endgroup\$
  • \$\begingroup\$ Good idea about prototype, can I still put the functions inside popup() or somehow keep them out of the main scope? \$\endgroup\$ – seahorsepip Jan 13 '16 at 15:09
  • \$\begingroup\$ Found something: stackoverflow.com/a/4229290/1008823 Gonna try that out and see if it works. \$\endgroup\$ – seahorsepip Jan 13 '16 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.