我正在构建这个简单的插件,只是构建一个表:
; (function ($, window, document, undefined) {
// Create the defaults once
var pluginName = "tableBuilder",
defaults = {
};
// The actual plugin constructor
function Plugin(element, options) {
this.element = element;
// jQuery has an extend method that merges the
// contents of two or more objects, storing the
// result in the first object. The first object
// is generally empty because we don't want to alter
// the default options for future instances of the plugin
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
String.prototype.format = function (values) {
var regex = /\{([\w-.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g;
var getValue = function (key) {
var value = values,
arr, type;
if (values == null || typeof values === 'undefined') return null;
if (key.indexOf('.')) {
arr = key.split('.');
while (arr.length && value) {
value = value[arr.shift()];
}
} else {
value = val && val[key] || values[key];
}
type = typeof value;
return type === 'string' || type === 'number' ? value : null;
};
return this.replace(regex, function (match) {
//match will look like {sample-match}
//key will be 'sample-match';
var key = match.substr(1, match.length - 2);
var value = getValue(key);
return value != null ? value : match;
});
};
Plugin.prototype = {
init: function () {
// Place initialization logic here
// You already have access to the DOM element and
// the options via the instance, e.g. this.element
// and this.options
// you can add more functions like the one below and
// call them like so: this.yourOtherFunction(this.element, this.options).
this.cycle();
},
cycle: function() {
var self = this;
self.buildRow();
self.display();
},
buildRow: function () {
var self = this;
self.rows = [];
$.each(self.options.json, function (i, item) {
self.rows.push(self.options.rowTemplate.format(item));
});
console.log(self.rows);
},
display: function (el, options) {
var self = this;
$(self.element).html(self.rows.join());
}
};
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName,
new Plugin(this, options));
}
});
};
})(jQuery, window, document);
我是通过按钮点击事件来调用它的:
var row = "<tr data-id=\"{Id}\"><td>{FileName}</td><td>{Metadata.FileSize}</td><td></td><td><button type=\"button\" class=\"close\" data-id=\"{Id}\" aria-hidden=\"true\">×</button></td></tr>"
$("#assets").on("click", ".glyphicon", function () {
var $asset = $(this).parent();
var $actionBar = $("#action-bar");
var $selected = $("#selected-asset");
var $table = $(".table");
var currentSelected = parseInt($selected.text());
var assetId = parseInt($asset.attr("id"))
if ($asset.hasClass("active")) {
$selected.text(currentSelected - 1);
activeItems = $.grep(activeItems, function (obj) {
return obj.Id != assetId
});
$asset.removeClass("active");
if (activeItems.length <= 0) {
$actionBar.hide();
}
} else {
$selected.text(currentSelected + 1);
var asset = $.grep(assets, function (obj) {
return obj.Id == assetId
});
activeItems.push(asset[0]);
$asset.addClass("active");
$actionBar.show();
}
$("#assets-table").tableBuilder({
json: activeItems,
rowTemplate: row
});
});
现在,当我第一次点击添加时,会创建表格。但是之后的每次点击都没有。我在 buildRows 函数上放了一个 console.log ,只调用一次,这是预期的,因为我们只在该元素上实例化插件。
因此,我需要添加一个可供客户端使用的刷新功能或添加/删除功能。
任何人都可以帮我一把吗?
答案 0 :(得分:1)
好的,所以我对上一个答案印象不深。 在此视频的帮助下:
Head first into plugin development
我能够确定所有函数实际上都是插件实例的一部分。 所以,这是我的新插件:)
String.prototype.format = function (values) {
var regex = /\{([\w-.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g;
var getValue = function (key) {
var value = values,
arr, type;
if (values == null || typeof values === 'undefined') return null;
if (key.indexOf('.')) {
arr = key.split('.');
while (arr.length && value) {
value = value[arr.shift()];
}
} else {
value = val && val[key] || values[key];
}
type = typeof value;
return type === 'string' || type === 'number' ? value : null;
};
return this.replace(regex, function (match) {
//match will look like {sample-match}
//key will be 'sample-match';
var key = match.substr(1, match.length - 2);
var value = getValue(key);
return value != null ? value : match;
});
};
; (function ($, window, document, undefined) {
var pluginName = "tableBuilder",
defaults = {
};
function Plugin(element, options) {
this.element = element;
this.$element = $(element);
this.rows = [];
this.rowTemplate = (typeof options === "string") ? options : options.rowTemplate;
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function () {
this.cycle();
},
cycle: function () {
var self = this;
if (self.options.json != null) {
self.buildRow();
self.display();
}
if (typeof self.options.onComplete === "function") {
self.options.onComplete.apply(self.element, arguments);
}
},
buildRow: function () {
var self = this;
$.each(self.options.json, function (i, item) {
self.rows.push(self.rowTemplate.format(item));
});
},
display: function (el, options) {
this.$element.html(this.rows.join());
},
add: function (row) {
console.log("moo");
this.rows.push(this.options.rowTemplate.format(row));
this.display();
},
remove: function(row) {
var match = this.options.rowTemplate.format(row);
this.rows = $.grep(this.rows, function (obj) {
return obj != match;
});
this.display();
}
};
$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName,
new Plugin(this, options));
}
});
};
})(jQuery, window, document);
现在,我需要访问的功能是 add()和 remove(),所以如果你看一下这些行:
$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName,
new Plugin(this, options));
}
});
};
他们实际上是将实例传递给$ .data数组,这允许我用一行代码调用我的实例:
$("#assets-table").data("plugin_tableBuilder")
因此,我可以调用属于该实例的任何函数,如下所示:
$("#assets-table").data("plugin_tableBuilder").add(asset[0]); // Add a row to our widget
我希望这有助于其他人:D
/ r3plica
答案 1 :(得分:0)
我将自己回答:) 基本上我认为这不是处理我的小部件的最佳方式,因此我使用widget factory boilerplate来解决我的问题。我将点击事件修改为:
$("#assets").on("click", ".glyphicon", function () {
var $asset = $(this).parent(); // Get our asset element
var $actionBar = $("#action-bar"); // Get the action bar
var $selected = $("#selected-asset");// Get our selected asset counter
var currentSelected = parseInt($selected.text()); // Get our current counter value
var assetId = parseInt($asset.attr("id")); // Get the asset id
var asset = $.grep(assets, function (obj) { // Find our asset from our array
return obj.Id == assetId;
});
if ($asset.hasClass("active")) { // If our asset is already selected, then we must unselect it
$selected.text(currentSelected - 1); // First, decrease our counter
tableWidget.tableBuilder("remove", asset[0]); // Then call our widget and remove the current asset from the table
activeItems = $.grep(activeItems, function (obj) { // Repopulate our array of active assets
return obj != asset;
});
$asset.removeClass("active"); // And remove the active class from our element
if (activeItems.length <= 0) { // Finally, if this is the only selected asset
$actionBar.hide(); // Hide our actionbar
}
} else { // Else, we are selecting an asset
$selected.text(currentSelected + 1); // Increase our counter
tableWidget.tableBuilder("add", asset[0]); // Add a row to our widget
activeItems.push(asset[0]); // Add the asset to our array of active assets
$asset.addClass("active"); // Add our active alss to our element
$actionBar.show(); // And show our actionbar
}
});
我在页面上实例化了我的插件,如下所示:
var row = "<tr data-id=\"{Id}\"><td>{FileName}</td><td>{Metadata.FileSize}</td><td></td><td><button type=\"button\" class=\"close\" data-id=\"{Id}\" aria-hidden=\"true\">×</button></td></tr>"
var tableWidget;
$(function () {
tableWidget = $("#assets-table").tableBuilder({
rowTemplate: row
});
});
然后,我的剧本改写为:
/*!
* jQuery UI Widget-factory plugin boilerplate (for 1.8/9+)
* Author: @addyosmani
* Further changes: @peolanha
* Licensed under the MIT license
*/
String.prototype.format = function (values) {
var regex = /\{([\w-.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g;
var getValue = function (key) {
var value = values,
arr, type;
if (values == null || typeof values === 'undefined') return null;
if (key.indexOf('.')) {
arr = key.split('.');
while (arr.length && value) {
value = value[arr.shift()];
}
} else {
value = val && val[key] || values[key];
}
type = typeof value;
return type === 'string' || type === 'number' ? value : null;
};
return this.replace(regex, function (match) {
//match will look like {sample-match}
//key will be 'sample-match';
var key = match.substr(1, match.length - 2);
var value = getValue(key);
return value != null ? value : match;
});
};
; (function ($, window, document, undefined) {
// define your widget under a namespace of your choice
// with additional parameters e.g.
// $.widget( "namespace.widgetname", (optional) - an
// existing widget prototype to inherit from, an object
// literal to become the widget's prototype );
$.widget("skipstone.tableBuilder", {
//Options to be used as defaults
options: {
json: null,
rowTemplate: null
},
//Setup widget (eg. element creation, apply theming
// , bind events etc.)
_create: function () {
// _create will automatically run the first time
// this widget is called. Put the initial widget
// setup code here, then you can access the element
// on which the widget was called via this.element.
// The options defined above can be accessed
// via this.options this.element.addStuff();
this.rows = [];
if (this.options.json != null) {
this._buildRow();
this._display();
}
},
_buildRow: function () {
var self = this;
$.each(self.options.json, function (i, item) {
self.rows.push(self.options.rowTemplate.format(item));
});
},
_display: function (el, options) {
$(this.element).html(this.rows.join());
},
add: function (row) {
this.rows.push(this.options.rowTemplate.format(row));
this._display();
},
remove: function(row) {
var match = this.options.rowTemplate.format(row);
this.rows = $.grep(this.rows, function (obj) {
return obj != match;
});
this._display();
},
// Destroy an instantiated plugin and clean up
// modifications the widget has made to the DOM
destroy: function () {
// this.element.removeStuff();
// For UI 1.8, destroy must be invoked from the
// base widget
$.Widget.prototype.destroy.call(this);
// For UI 1.9, define _destroy instead and don't
// worry about
// calling the base widget
}
});
})(jQuery, window, document);
这是如何解决我的问题。您可以看到我通过调用
添加行tableWidget.tableBuilder("add", asset[0]);
并通过调用
删除项目tableWidget.tableBuilder("remove", asset[0]);
我真的希望帮助别人:D
干杯, r3plica