JS:创建我的插件的新唯一实例

时间:2017-06-26 12:53:12

标签: javascript

我已经创建了一个JavaScript插件,我想有可能多次使用它,但是,如果将其称为页面两次,就像下面一样,它似乎不会创建一个新实例:< / p>

var lightbox = new MarvLightbox({ 
    imagesContainer: 'detail-hdr__detail-images',
    limit: 11
  });
  var lightbox2 = new MarvLightbox({ 
    imagesContainer: 'image-grid-2',
    galleryFolder: 2,
    mobileFolder: 0
  });

以下代码似乎返回相同的值,因此,例如,如果我单击图像以在c对象中设置state值,那么它的实例已更改{ {1}}和lightbox2

lightbox

我试图从我的插件中删除任何不需要的代码。但我基本上做的是: 1.编译容器中的图像列表。 2.从JSON字符串生成HTML。 3.将点击事件分配给图像,然后单击它们时打开灯箱并更改图像等。

MarvLightbox.prototype.current = function() {
    console.log(state);
  };

正如我上面所说,虽然(function() { var instance = null, container; // Constructor this.MarvLightbox = function() { instance = this; // Create global variables this.images_count = -1; this.active = false; this.error = false; this.debug = false; // Define option defaults var defaults = { activeClass: 'marvLightbox', appendTo: '#wrapper', imagesContainer: null, thumbClass: null, lightboxId: 'marvLightbox', galleryFolder: null, mobileFolder: null, showAlt: true, showMax: true, limit: null, html: '{ "div": { "id": "{lightboxId}", "0": { "div": { "class": "{lightboxId}__container", "data-click": "EventClose", "0": { "div": { "class": "{lightboxId}__controls {lightboxId}__controls--top", "0": { "div": { "class": "{lightboxId}__eschint", "content": "Press <span>ESC</span> to close" } }, "1": { "div": { "class": "{lightboxId}__close", "data-click": "EventClose" } } } }, "1": { "div": { "class": "{lightboxId}__image", "0": { "img": { "src": "", "class": "responsive-img image", "data-click": "EventRight" } } } }, "2": { "div": { "class": "{lightboxId}__controls {lightboxId}__controls--bottom", "3": { "div": { "class": "{lightboxId}__left", "data-click": "EventLeft", "data-hover": "EventClass(#{lightboxId}, toggle: left)" } }, "4": { "div": { "class": "{lightboxId}__right", "data-click": "EventRight", "data-hover": "EventClass(#{lightboxId}, toggle: right)" } }, "5": { "div": { "class": "{lightboxId}__alt" } }, "6": { "div": { "class": "{lightboxId}__num" } } } } } } } }' }; // Create options by extending defaults with the passed in arugments if (arguments[0] && typeof arguments[0] === "object") { this.options = extendDefaults(defaults, arguments[0]); } this.options.html = this.options.html.replace(/\{(lightboxId)}/g, this.options.lightboxId); // this.options.limit = this.options.limit + 1; // Check if debugging is enabled (function() { var args = document.querySelectorAll('[data-external-arg]'); if(args.length > 0 && args[0].src.indexOf('marv.lightbox') !== -1) { if (args[0].dataset.externalArg === 'debug') instance.debug = true; } }()); // Initialise plugin this.init(); }; // Debugging messages var debug = function(code, arg) { var args = function(n) { if (arg === undefined) { return '[arg undefined]'; } if (arg[n] === undefined) { return '[arg undefined]'; } else { return arg[n]; } }; var messages = function(code, argument) { return [ 'marv.lightbox(debug): Debugging mode is on, make sure you turn this off before you launch', 'marv.lightbox(debug): HTMLElement(' + args(0) + ') with the name of ' + args(1) + ' has been detected', 'marv.lightbox(debug): Found '+ arg + ' image/s within your Lightbox container ', 'marv.lightbox(debug): ' + args(0) + ' key pressed, changing current (' + args(1) + '), number of images (' + args(2) + ')', 'marv.lightbox(debug): Current is set to null, closing lightbox', 'marv.lightbox(debug): Inserting Lightbox within HTMLElement(' + args(1) + '), using ' + args(0), 'marv.lightbox(debug): 1 image found, don\'t add previous/next arrows, don\'t show numbers either', 'marv.lightbox(debug): showAlt set to false, don\'t display alt text', 'marv.lightbox(debug): showMax set to false, don\'t display numbers below alt text', 'marv.lightbox(debug): Reverting to mobile version (' + instance.options.mobileFolder + ') of images', 'marv.lightbox(debug): Over-riding to ' + instance.options.galleryFolder + ' version of images' ][code]; }; if (instance.debug === true) console.log(messages(code, arg)); }; // Error messages var error = function(code, arg) { var args = function(n) { if (arg === undefined) { return '[arg undefined]'; } if (arg[n] === undefined) { return '[arg undefined]'; } else { return arg[n]; } }; var messages = function(code, argument) { return [ 'marv.lightbox(error): I need to know which images to use... add { imagesContainer: "id/class" } to the plugin initialization', 'marv.lightbox(error): The HTML structure provided appears to have an error: ' + arg, 'marv.lightbox(error): Issue compiling list of images, speak to Dev, error: ' + arg, 'marv.lightbox(error): Your going to need some images for this to work... make sure they have the class: ' + instance.options.thumbClass, 'marv.lightbox(error): I was unable to find an element which matches ' + instance.options.imagesContainer + ', please double check this', 'marv.lightbox(error): I was unable to find a container with the name of ' + args[0], 'marv.lightbox(error): EventListener with arguments passed, had an issue seperating arguments, check formatting', 'marv.lightbox(error): Unable to apply class event to element, please check your attribute', 'marv.lightbox(error): You have attempted to over-ride the images folder with a size that doesn\'t exist, please choose a size between 0 and ' + arg ][code]; }; console.log(messages(code, arg)); }; var imageSizes = function(e) { var sizes = [ '344x258', 'full', 'large1' ]; if (sizes[e] !== undefined) { return sizes[e]; } error(8, sizes.length); }; // Initilise the plugin MarvLightbox.prototype.init = function() { if (this.options.imagesContainer === null) { error(0); return; } container = (instance.options.imagesContainer).objectType(); if (container === null || container === undefined) { error(4); return; } debug(0); setupLightbox(); }; // Generate HTML from JSON function buildHTML(json) { "use strict"; var handleAttribute = function(element, attribute, value) { if (value instanceof HTMLElement) { return element.appendChild(value); } switch (attribute) { case 'class': case 'src': case 'id': case 'data-click': case 'data-hover': return element.setAttribute(attribute, value); case 'content': element.innerHTML = value; return; // other keys... default: console.log(element.tagName, attribute, value); } }; var htmlReviver = function(key, value) { // parse as element if (isNaN(key) && typeof value === 'object') { var element = document.createElement(key); var subValue; for (var attribute in value) { handleAttribute(element, attribute, value[attribute]); } return element; // move element from { index: { tagName: Element } } to { index: Element } } else if (!isNaN(key)) { return value[Object.keys(value)[0]]; // leave property alone } else { return value; } }; try { var htmlObject = JSON.parse(json, htmlReviver); return htmlObject; } catch (e) { error(1, e); } } // Manage item change var images_compiled; var state = { c: null, altValue: null, maxValue: null, get current() { return this.c; }, get max() { return this.maxValue; }, get alt() { return this.altValue; }, set max(e) { this.maxValue = e; }, set alt(e) { this.altValue = e; }, set current(e) { if (this.c !== null) { // Remove class from current (images_compiled[this.c].target).classList.remove('expand'); } if (e === null) { debug(4); // Collapse Lightbox if (document.getElementById(instance.options.lightboxId)) { (images_compiled[this.c].target).classList.remove('expand'); document.getElementsByTagName('body')[0].classList.remove(instance.options.activeClass); (document.getElementById(instance.options.lightboxId).parentNode).removeChild(document.getElementById(instance.options.lightboxId)); } this.c = e; return; } // Change current element, update lightbox this.c = e; var lightbox = document.getElementById(instance.options.lightboxId), res; // Check lightbox exists, if so change the image src if (lightbox) { var image = images_compiled[e].image.src; if (instance.options.galleryFolder !== null) { var filter = image.match(/([^\/]*)/g).filter(Boolean); image = image.replace(filter[filter.length - 2], imageSizes(instance.options.galleryFolder)); } lightbox.getElementsByTagName('img')[0].src = image; if (instance.options.showAlt) { debug(7); lightbox.getElementsByClassName(instance.options.lightboxId + '__alt')[0].innerHTML = images_compiled[e].alt; } if (instance.options.showMax && this.max > 1) { debug(8); lightbox.getElementsByClassName(instance.options.lightboxId + '__num')[0].innerHTML = (images_compiled[e].index + 1) + '/' + this.max; } } else { res = generateExpand(images_compiled[e]); } // Add active class if (res) { (images_compiled[e].target).classList.add('expand'); document.getElementsByTagName('body')[0].classList.add(instance.options.lightboxId); } } }; // Setup light box function setupLightbox() { var images; images = container.getElementsByTagName('img'); if (instance.options.limit !== null) { var tmp = []; for (var i = 0, length = images.length; i < length; i++) { if (i < instance.options.limit) { tmp.push(images[i]); } } images = tmp; } if (images.length < 1 || images === undefined) { error(3); return; } try { images_compiled = Array.from(images, function(el) { // Generate array of objects containing image information instance.images_count++; return { target: function() { if (el.parentElement.nodeName === 'A') { return el.parentElement; } return el; }(), index: instance.images_count, alt: ((el.alt) ? el.alt : ''), image: function() { // If class put on an A link then find the image if (el.tagName === 'A') { return el.getElementsByTagName('img')[0]; } else { return el; } }() }; }); } catch(e) { // Issue with generating array error(2, e); } debug(2, images_compiled.length); // Add image click event images_compiled.forEach(function(el) { if (el !== null) { var elm = el.target; elm.addEventListener('click', function(e) { if (elm.nodeName === 'A') { e.preventDefault(); } instance.active = true; if (state.current === el.index) { state.current = null; return; } state.current = el.index; state.alt = el.alt; }); } }); state.max = images_compiled.length; } function generateExpand(img) { // Generate lightbox HTML and append var html = buildHTML(instance.options.html); instance.events = { EventClose: function(evt) { if (evt !== undefined) { evt.stopPropagation(); } instance.active = false; state.current = null; }, EventLeft: function(evt) { if (evt !== undefined) { evt.stopPropagation(); } if (state.current !== 0 && state.max > 1) { state.current = state.current - 1; } else { state.current = instance.images_count; } }, EventRight: function(evt) { if (evt !== undefined) { evt.stopPropagation(); } if (state.current !== instance.images_count && state.max > 1) { state.current = state.current + 1; } else { state.current = 0; } }, EventClass: function(evt) { var arg = (evt.dataset.hover).replace(/ /g,''), args = (arg.match(/[^(]*/g).filter(Boolean))[1].match(/(?:([^,()]+)?)+/g).filter(Boolean), target = args[0].objectType(), action = args[1].match(/^(.*):(.*)/).filter(Boolean); switch(action[1]) { case 'add': // Add class target.classList.add(action[2]); break; case 'remove': // Remove class target.classList.remove(action[2]); break; case 'toggle': target.classList.add(action[2]); evt.addEventListener('mouseout', function() { target.classList.remove(action[2]); }); break; default: // Error error(7); break; } } }; // Lightbox is active instance.active = true; // Assign event listeners Array.prototype.forEach.call(html.querySelectorAll('[data-click]'), function (e) { e.addEventListener('click', instance.events[eventName(e.dataset.click)]); }); Array.prototype.forEach.call(html.querySelectorAll('[data-hover]'), function (e) { e.addEventListener('mouseover', function() { instance.events[eventName(e.dataset.hover)](e); }); }); // Insert lightbox into website var appendTo = (instance.options.appendTo).objectType(); if (appendTo === null || (instance.options.appendTo).objectType() === undefined) { error(5, [instance.options.appendTo]); return false; } debug(5, ['id', instance.options.imagesContainer]); appendTo.insertBefore(html, appendTo.firstChild); return true; } MarvLightbox.prototype.current = function() { console.log(state); }; }()); 对象似乎在两个实例之间共享,但它应该是唯一的。

1 个答案:

答案 0 :(得分:0)

问题在于实例我认为:

var instance = null;
MarvLightbox = function() {
  instance = this;

因此,无论何时创建新的Lightbox,实例都会指向它。这也适用于异步回调函数,它们都指向最后一个而不是当前实例。您可以在本地范围实例:

var instance=this;

同样适用于州:

MarvLightbox.prototype.current = function() {
  console.log(this.state); //make it an objects property, not global
};