First, let's see how easy it is to support multiple options . A common solution is to create your constructor in a "configuration" object instead of simple string or number arguments. Use this form instead:
var Tooltip = function(selector, options) { this.targetElement = document.querySelectorAll(selector); this.options = options; ... }; var box = new Tooltip(".box", { color: "red" });
Note that instead of passing a single value, we pass an object containing this single value. But this object could potentially have many configuration options, not just one! For example, you can go through:
var box = new Tooltip(".box", { backgroundColor: "red", textColor: "white", fontSize: 12, animated: true, animationSpeed: 1000 });
When you need to access any of these parameters, your code can simply use the link to the options object: for example, instead of this.bcolor
you can use this.options.backgroundColor
. Here is your code above, expanded with some additional parameters:
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, how will you handle several parameters; but what about the default values for each? To do this, you first need to determine what the default values ββlook like:
Tooltip.prototype.defaultOptions = { backgroundColor: "#FF9", textColor: "black", fontSize: 12, animated: false, animationSpeed: 1000 };
And then your constructor can rotate over 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 with typeof
for an undefined
value is true only if the value does not exist, so this for-loop loop copies any values ββfrom defaultOptions
to options
if they don't already exist in options
. It is beautiful and extensible: as soon as you add a new value to defaultOptions
, the loop will copy it to options
, regardless of what the callers called before.
And, more importantly, the for loop is all that jQuery.extend
does under the hood: copying values ββfrom one object to another. (The jQuery solution is a little more elegant, but I simplified the situation to make it more obvious what is happening.)
But what if you want the default behavior in some places? For example, if you do not define a specific font size, perhaps you just want it to inherit from the parent element or document, and not be bound to it with defaultOptions
.
If you want this behavior to βnot be assigned unless it was provided,β the same basic template above may work, but you need to change the default settings a bit, and then add a condition when you're applying this option. See 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"; ... } }
Hope you have enough for you to work.
Variations of this ( Object.extend
versus undefined
templates) are used universally in JavaScript and jQuery and the entire host of other libraries are widely used. If you follow the same basic design as you, you will be in a very good company.