简体   繁体   English

创建一个jQuery插件实例

[英]Create an instance of a jQuery plugin

I have several pages which I wish to allow the the user to inline edit many fields and update the server DB. 我有几个页面,我希望允许用户内联编辑许多字段并更新服务器数据库。 To implement this, my intent is to create a jQuery plugin which I can do the typical passing of the configuration options and uses ajax to save the results. 为了实现这一点,我的目的是创建一个jQuery插件,我可以通过它典型地传递配置选项,并使用ajax保存结果。

(function($){
    var methods = {
        init    : function (options) {return this.each(function () {/* ... */});},
        method1 : function ()        {return this.each(function () {/* ... */});},
        method2 : function ()        {return this.each(function () {/* ... */});}
    };

    $.fn.myEditPlugin= function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));   //Line 10
        } else if (typeof method === 'object' || ! method) {
            return methods.init.apply(this, arguments);                                     //Line 12
        } else {
            $.error('Method ' +  method + ' does not exist on jQuery.myEditPlugin');
        }    
    };
    }(jQuery)
);

For each individual page, there are several options which are common to all (ie the url endpoint, the record's primary key, etc) and I would rather not duplicate each when applying the plugin. 对于每个单独的页面,都有几个共有的选项(即url端点,记录的主键等),我宁愿在应用插件时也不重复每个选项。

Originally, I was just going to define a function on each page which takes some input and applies the common options to each. 最初,我只是在每个页面上定义一个函数,该函数需要一些输入并将通用选项应用于每个页面。

function wrapEdit(e,options) {
  options.url='/page1/etc';
  options.pk=document.getElementById('pk').value;
  return $(e).myEditPlugin(options);
}
wrapEdit('.someclass',{foo:123});

It doesn't seem all that professional to me, so in my obsessive quest, thought I would make a class which I could pass the common options to and it would apply the plugin. 对我来说,这似乎并不那么专业,所以在我的痴迷追求中,我以为我将创建一个可以将通用选项传递给它的类,然后将其应用于该插件。

class WrapEdit(options)
{
  constructor(options) {
    this.options = options;
  }
  this.applyIndividualOptions=function(e, options) {
     return $(e).myEditPlugin(Object.assign({}, this->options, options));
  }
}

var wrapEdit=new WrapEdit({url: '/page1/etc', pk: document.getElementById('pk').value});
wrapEdit.applyIndividualOptions('.someclass',{foo:123});

Better, but not very jQueryish as I will be passing the select element instead of directly applying the plugin to elements typical of jQuery. 更好,但不是jQueryish,因为我将传递select元素,而不是直接将插件应用于jQuery的典型元素。

Is it possible to create an instance of a jQuery plugin which keeps previously defined data? 是否可以创建一个jQuery插件实例来保留先前定义的数据? Maybe something like the following: 也许像下面这样:

$.myEditPlugin({url: '/page1/etc', pk: document.getElementById('pk').value});
$('.someclass').myEditPlugin({foo:123});  //Will also pass previously defined url and pk to myEditPlugin

Or maybe best to create a custom jQuery plugin per page which just adds the extra options and initiates the real plugin... 或者最好是每页创建一个自定义jQuery插件,它仅添加额外的选项并启动真正的插件...

$.fn.myEditPluginInstance = function(options) {
    return this.myEditPlugin(Object.assign({url: '/page1/etc', pk: document.getElementById('pk').value}, options));    
};

Creating a function to be called against a jquery collection 创建一个要针对jQuery集合调用的函数

The basic idea is to define a new property (function) in jQuery.fn , before any call to your plugin is made (In other words, any code related to the application is executed). 基本思想是在对插件进行任何调用之前(即执行与应用程序相关的任何代码)在jQuery.fn定义一个新的属性(函数)。 You can use an "Immediately Invoked Function Expressions" (aka IIFEs) to fence your plugin API in. Then you have to loop over the collection and execute any code your plugin needs to apply on the collection items. 您可以使用“立即调用的函数表达式”(即IIFE)来屏蔽您的插件API。然后,您必须遍历集合并执行您的插件需要应用于集合项的任何代码。

Basic skeleton : 基本骨架

(function ($) {
    // Enclosed scope (IIFE)
    // You can define private API/variables in here
    // …

    // Once your plugin API is ready, you have to apply the magic to each item
    // in the collection in some ways. You must add a property to jQuery.fn object.
    $.fn.myAwesomePlugin = function(Opt) {
      var defaultConfig = {option1: 'someValue' /*, …*/};

      // Eval supplied Opt object (Validate, reject, etc.)
      // If all goes well, eventually merge the object with defaults.
      $.extend(defaultConfig, Opt);

      // Apply the magic against each item in the jQuery collection
      // (Your plugin may not need to use "each" function though)
      // Return the jQuery collection anyway to keep chaining possible.
      // Once again, this is not required, your plugin may return something else depending on the options passed earlier for instance.
      return this.each(function(el, idx) {
        // Your plugin magic applied to collection items…
      });
    }

})(jQuery);

You should be able to call your plugin $('someSelector').myAwesomePlugin(); 您应该能够调用您的插件$('someSelector').myAwesomePlugin(); right after the declaration. 声明之后。

Simple implementation example : 简单的实现示例

 (function ($) { let required = {url: null, pk: null} // Function to be executed upon first call to the plugin , populateCommons = () => { let ep = $('#someNode').data('endpoint') , pk = document.querySelector('#pk') ; // Basic tests to alert in case the page // doesn't comply with the plugin requirements if( typeof ep !== 'string' || !/^\\/[az]+/.test(ep) || !pk) { throw ` "myEditPlugin" init phase error: Detected endpoint: '${ep}' Is PK value found: ${!!pk} `; } [required.url, required.pk] = [ep, +pk.value]; }; $.fn.myEditPlugin = function(Opt) { let allOpts; // First call will trigger the retrival of common data // that should be available as static data somewhere every page source. !required.url && populateCommons(); allOpts = $.extend({}, Opt, required); return this.each(function(el, idx) { // Your logic here, request console.log("Payload is", allOpts); }); } })(jQuery); function debounce(fn, time) { debounce.timer && (clearTimeout(debounce.timer)); debounce.timer = setTimeout(() => (fn(), debounce.timer = null), time); } $('[type="text"]').keydown(function(e){ debounce(() => this.value && $(this).myEditPlugin({foo:this.value, bar: 'Contextual value'}), 2000); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input id="pk" type="hidden" value="5"> <div id="someNode" data-endpoint="/api/endpoint"> Editing the below input will trigger the plug-in code </div> <input type="text" title="Edit me"/> 

Related documentation here 相关文档在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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