Wednesday, March 15, 2017

Make default settings for vanilla js plugin

Leave a Comment

Tried to build a simple tooltip plugin in plain javascript.

I digged jquery extend but it s a bit complicated for me.

I tried to make and put bcolor as default setting in my code and i think i'ts not a good way when we want to put more than 1 defaults.

JSFIDDLE

How can i make default settings in my plugin?

var Tooltip = function(selector, bcolor) {   this.targetElement = document.querySelectorAll(selector);   this.bcolor = bcolor;   if (this.bcolor == null || typeof this.bcolor !== "string") {     this.bcolor = "#333";   }    if (this.targetElement == null) {     console.log("Ooops, error!")   }    return this; }  Tooltip.prototype.tooltip = function() {   for (var i = 0; i < this.targetElement.length; i++) {      var text = this.targetElement[i].getAttribute("data-tooltip");      this.targetElement[i].style.position = "relative";      var span = document.createElement("span");     this.targetElement[i].appendChild(span);     span.style.position = "absolute";     span.style.top = "-25px";     span.style.left = "-20px";     span.style.padding = "4px"     span.style.borderRadius = "5px";     span.style.backgroundColor = this.bcolor;     span.style.color = "#fff";     span.innerHTML = text;   } }  var box = new Tooltip(".box", "red"); box.tooltip(); 

1 Answers

Answers 1

First, let's look at how to easily support multiple options. A common solution to this is to have your constructor take in a "configuration" object instead of just simple string or number arguments. Consider using this form instead:

var Tooltip = function(selector, options) {     this.targetElement = document.querySelectorAll(selector);     this.options = options;     ... };  var box = new Tooltip(".box", { color: "red" }); 

Notice that instead of passing a single value, we pass in an object that contains that single value. But that object can potentially have many configuration options in it — not just one! For example, you could pass in:

var box = new Tooltip(".box", {     backgroundColor: "red",     textColor: "white",     fontSize: 12,     animated: true,     animationSpeed: 1000 }); 

When you need to access any of those options, your code can simply use the reference to the options object: For example, instead of this.bcolor, you might use this.options.backgroundColor. Here's your code above, extended with some more options:

Tooltip.prototype.tooltip = function() {    for (var i = 0; i < this.targetElement.length; i++) {        ...        span.style.backgroundColor = this.options.backgroundColor;        span.style.color = this.options.textColor;        span.style.fontSize = this.options.fontSize + "px";        ...    } } 

So that's how you'd handle multiple options; but what about default values for each? To do that, you'd want to first define somewhere what the default values look like:

Tooltip.prototype.defaultOptions = {     backgroundColor: "#FF9",     textColor: "black",     fontSize: 12,     animated: false,     animationSpeed: 1000 }; 

And then your constructor could spin over the defaultOptions, using its values to fill in any missing "holes" in the provided options object:

var Tooltip = function(selector, options) {     this.targetElement = document.querySelectorAll(selector);     this.options = options;      for (var optionName in this.defaultOptions) {         if (typeof this.options[optionName] === 'undefined')             this.options[optionName] = this.defaultOptions[optionName];     }     ... }; 

A test against a typeof for the value of undefined is true only if the value doesn't exist, so this for-loop copies any values from defaultOptions to options, as long as they don't already exist in options. It's nice and extensible: As soon as you add a new value to defaultOptions, the loop will copy it into options, no matter what the callers were passing before.

And, more importantly, that for loop is really all that jQuery.extend is doing under the hood: Copying values from one object to another. (The jQuery solution is a little bit more elegant, but I simplified things here to make it more obvious what's going on.)


But what if you want default behavior in some places? For example, if you don't define a specific font size, maybe you just want it to inherit from the parent element or the document rather than having it be assigned to something from defaultOptions.

If you want that kind of "don't-assign-it-unless-provided" behavior, the same basic pattern above can work, but you need to tweak the default options a little, and then add a condition when you're applying the option. Consider how this example differs from what I showed above:

// Notice that we specifically leave out fontSize here in the defaults. Tooltip.prototype.defaultOptions = {     backgroundColor: "#FF9",     textColor: "black",     animated: false,     animationSpeed: 1000 };  Tooltip.prototype.tooltip = function() {    for (var i = 0; i < this.targetElement.length; i++) {        ...        span.style.backgroundColor = this.options.backgroundColor;        span.style.color = this.options.textColor;         // Now, we only assign the fontSize if it was provided by the user.        if (typeof this.options.fontSize !== 'undefined')            span.style.fontSize = this.options.fontSize + "px";        ...    } } 

This hopefully should be enough for you to work with.


Variations on this (the Object.extend pattern and testing against undefined) are used all over the place in JavaScript, and are heavily used by jQuery and a whole host of other libraries. If you follow the same basic design they do, you'll be in very good company.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment