Большинство компиляторов C обеспечивает -o
опция для этого, такая как:
gcc -o gentext gentext.c
cc -o mainprog -Llib -lmymath firstbit.c secondbit.o
xlc -o coredump coredump.c
Я обнаружил, что способ обработки этого пользовательского интерфейса jQuery, кажется, работает лучше всего. Вы создаете свои «дополнительные методы» в качестве строкового аргумента вашего плагина:
$('#elem').autoCompleteEx('addItem', '1');
Затем контекст «this» сохраняется, и вы можете делать что-то в этом направлении:
function addItem() {
// this should be == jquery object when this get called
}
$.fn.autoCompleteEx = function(options) {
if (options === 'addItem') {
return addItem.apply(this, Array.prototype.splice.call(arguments, 1));
}
};
Вот шаблон, с которым я экспериментирую при создании более сложных плагинов виджетов:
(function($){
// configuration, private helper functions and variables
var _defaultConfig = {
/* ... config ... */
},
_version = 1;
// the main controller constructor
$.myplugin = function ( elm, config ) {
// if this contructor wasn't newed, then new it...
if ( this === window ) { return new $.myplugin( elm, config || {} ); }
// store the basics
this.item = $( elm );
this.config = new $.myplugin.config( config );
// don't rerun the plugin if it is already present
if ( this.item.data( 'myplugin' ) ) { return; }
// register this controlset with the element
this.item.data( 'myplugin', this );
// ... more init ...
};
$.myplugin.version = _version;
$.myplugin.config = function ( c ) { $.extend( this, $.myplugin.config, c ); };
$.myplugin.config.prototype = _defaultConfig;
$.myplugin.prototype = {
/* ... "public" methods ... */
};
// expose as a selector plugin
$.fn.myplugin = function ( config ) {
return this.each(function(){
new $.myplugin( this, config );
});
};
})(jQuery);
Я помещаю конфигурацию и версию по умолчанию наверху просто потому, что это наиболее вероятно то, что ищет любой читающий код. В большинстве случаев вы просто хотите исследовать блок настроек.
Это откроет "myplugin" в двух местах в качестве конструктора для "контроллера" виджета.
на $
и как метод сбора на $ .fn
. Как вы можете видеть, метод $. Fn
на самом деле ничего не делает, кроме создания экземпляров новых контроллеров.
Конфигурация - это унаследованный от прототипа объект, где по умолчанию используется прототип. Это дает расширенную гибкость с начальными значениями, поскольку вы можете
назначьте "следующие" значения по умолчанию в $. myplugin.config
или измените значение по умолчанию для каждого запущенного плагина с помощью $. myplugin.config.prototype
. Это требует от вас
всегда назначайте их с помощью $ .extend, иначе вы сломаете систему. Этому может противостоять дополнительный код, но я предпочитаю знать, что делаю. : -)
Экземпляр контроллера привязывается к элементу через метод jQuery data ()
и фактически использует его для проверки того, что он не запускается дважды для одного и того же элемента (хотя вы можете разрешить его перенастройку).
Это дает вам следующий интерфейс к контроллеру:
// init:
$( 'div#myid' ).myplugin();
// call extraMethod on the controller:
$( 'div#myid' ).data('myplugin').extraMethod();
Самым большим недостатком этого подхода является то, что поддерживать контекст «this» при каждом событии немного затруднительно. назначение. Пока контекст для событий не поступит в jQuery, это нужно делать с большим количеством закрытий.
Вот приблизительный пример того, как может выглядеть (неполный и бесполезный) плагин:
(function($){
// configuration, private helper functions and variables
var _defaultConfig = {
openOnHover: true,
closeButton: '<a href="#">Close</a>',
popup: '<div class="wrapper"></div>'
},
_version = 1;
// the main controller constructor
$.myplugin = function ( elm, config ) {
// if this contructor wasn't newed, then new it...
if ( this === window ) { return new $.myplugin( elm, config || {} ); }
this.item = $( elm );
this.config = new $.myplugin.config( config );
if ( this.item.data( 'myplugin' ) ) { return; }
this.item.data( 'myplugin', this );
// register some events
var ev = 'click' + ( this.config.openOnHover ) ? ' hover' : '';
this.item.bind(ev, function (e) {
$( this ).data( 'myplugin' ).openPopup();
});
};
$.myplugin.version = _version;
$.myplugin.config = function ( c ) { $.extend( this, $.myplugin.config, c ); };
$.myplugin.config.prototype = _defaultConfig;
$.myplugin.prototype = {
openPopup: function () {
var C = this.config;
this.pop = $( C.popup ).insertAfter( this.item );
this.pop.text( 'This says nothing' );
var self = this;
$( C.closeButton )
.appendTo( pop )
.bind('click', function () {
self.closePopup(); // closure keeps context
return false;
});
return this; // chaining
},
closePopup: function () {
this.pop.remove();
this.pop = null;
return this; // chaining
}
};
// expose as a selector plugin
$.fn.myplugin = function ( config ) {
return this.each(function(){
new $.myplugin( this, config );
});
};
})(jQuery);
Обратите внимание на функциональность jQuery .data . Он позволяет хранить пары ключ / значение для любого объекта.
Используйте что-то вроде этого:
acx.data("acx-somename", datavalue);
Затем вы можете позже получить его с помощью:
var datavalue = acx.data("acx-somename");
Манипуляция экземпляром! Это то, что вы хотите, верно? Старая добрая мода, манипуляции с экземплярами в реальном времени. Я тоже этого хотел. Я погуглил тот же вопрос и нигде не смог получить хорошего ответа (как и те, что указаны выше), поэтому я понял это. Мне не нравится мое решение, потому что оно кажется обходным способом получить доступ к методам экземпляра и странным для потребителя jquery, но jQuery в первую очередь чертовски странный, но прекрасный. Я написал простой плагин для затухания изображений, но затем, когда мне нужно было сделать с ним больше, я захотел предоставить методы для живого экземпляра, чтобы получить этот результат здесь -> пример , я сделал следующее:
var instanceAccessor = {};
var pluginOptions = {'accessor':instanceAccessor}
$('div').myPlugin(pluginOptions);
Затем внутри плагина я добавляю методы к этому переданному объекту 'accessor', поскольку это объект. Я предоставляю методы внутри плагина следующим образом:
if (pluginOptions.accessor != null && typeof(pluginOptions.accessor) === 'object') {
pluginOptions.accessor.exposedMethod = function (someParam) {
// call some private function here and access private data here
};
}
Затем,
Вот мой взгляд на это:
У меня есть объект в замыкании, который используется для создания экземпляров объектов. Объекты экземпляра прикрепляются к узлу элемента с помощью метода jQuery data (). У этих экземпляров есть общедоступные методы, которые вы можете вызывать по мере необходимости.
(function($)
{
// This is used to create AutoComplete object that are attatched to each element that is matched
// when the plugin is invoked
var AutoCompleteEx = function(options, acx) {
// PRIVATE VARIABLES
var timerID;
var input;
//Give Div Correct Class & Add <ul> w/ input item to it
acx.addClass("autoCompleteEx");
acx.html("<ul><li class=\"input\"><input type=\"text\"/></li></ul>");
//Grab Input As JQ Object
input = $("input", acx);
//Wireup Div
acx.click(function()
{
input.focus().val( input.val() );
});
//Wireup Input
input.keydown(function(e)
{
var kc = e.keyCode;
if(kc == 13) //Enter
{
}
else if(kc == 27) //Esc
{
}
else
{
//Resize TextArea To Input
var width = 50 + (_txtArea.val().length*10);
_txtArea.css("width", width+"px");
}
});
// PUBLIC METHODS
this.setTimerID = function(id) {
timerID = id;
};
this.getTimerID = function() {
return timerID;
};
};
//Attach this new method to jQuery
$.fn.autoCompleteEx = function(options)
{
//Merge Given Options W/ Defaults, But Don't Alter Either
var opts = $.extend({}, $.fn.autoCompleteEx.defaults, options);
//Iterate over the current set of matched elements
return this.each(function()
{
var acx = $(this); //Get JQuery Version Of Element (Should Be Div)
// creating a new AutoCompleteEx object and attach to the element's data, if not already attached
if (!acx.data('autoCompleteEx')) {
acx.data('autoCompleteEx', new AutoCompleteEx(options, acx));
}
}); //End Each JQ Element
}; //End autoCompleteEx()
//Default Settings
$.fn.autoCompleteEx.defaults =
{
minChars: 2,
delay: 300,
maxItems: 1
};
//End Of Closure
})(jQuery);
Вы можете вызывать методы следующим образом:
$("div#someDiv").autoCompleteEx();
$("div#someDiv").data('autoCompleteEx').setTimerID(123);
var timerId = $("div").data('autoCompleteEx').getTimerID();
console.log(timerId); // outputs '123'
А если вы создаете более одного экземпляра:
$("div.someDiv").autoCompleteEx();
$("div.someDiv").eq(0).data('autoCompleteEx').setTimerID(123);
$("div.someDiv").eq(1).data('autoCompleteEx').setTimerID(124);
var firstTimerId = $("div").eq(0).data('autoCompleteEx').getTimerID();
var secondTimerId = $("div").eq(1).data('autoCompleteEx').getTimerID();
console.log(firstTimerId); // outputs '123'
console.log(secondTimerId); // outputs '124'