Мне нужно создать плагин jQuery, который бы возвращал один экземпляр на идентификатор селектора.Плагин должен и будет использоваться только для элементов с идентификатором (невозможно использовать селектор, который соответствует многим элементам), поэтому его следует использовать так:
$('#element-id').myPlugin(options);
- Мне нужно иметь возможностьесть несколько частных методов для плагина, а также несколько открытых методов.Я могу добиться этого, но моя главная проблема заключается в том, что я хочу получать один и тот же экземпляр каждый раз, когда я вызываю $ ('# element-id'). MyPlugin ().
- И я хочу, чтобы какой-то код выполнялся только при первой инициализации плагина для данного идентификатора (конструкции).
- Параметр
options
должен быть предоставлен в первый раздля конструкции, после этого я не хочу, чтобы конструкция выполнялась, так что я могу получить доступ к плагину так же, как $ ('# element-id'). myPlugin () - Плагин должен быть в состоянииработать с несколькими элементами (как правило, до 2) на одной странице (но каждому из них потребуется собственная конфигурация, опять же - они будут инициализированы идентификатором, а не общим селектором класса, например).
- Приведенный выше синтаксис приведен только для примера - я открыт для любых предложений о том, как добиться этого паттерна
У меня достаточно опыта ООП с другим языком, но ограниченное знаниеjavascript, и я действительно запутался в том, как это сделать правильно.
РЕДАКТИРОВАТЬ
Чтобы уточнить - этот плагин представляет собой обертку API GoogleMaps v3 (помощник), чтобы помочь мне получитьизбавиться от дублирования кода, так как я использую карты Google во многих местах, обычно с маркерами.Это текущая библиотека (много кода удалено, осталось увидеть только самые важные методы):
;(function($) {
/**
* csGoogleMapsHelper set function.
* @param options map settings for the google maps helper. Available options are as follows:
* - mapTypeId: constant, http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeId
* - mapTypeControlPosition: constant, http://code.google.com/apis/maps/documentation/javascript/reference.html#ControlPosition
* - mapTypeControlStyle: constant, http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeControlStyle
* - mapCenterLatitude: decimal, -180 to +180 latitude of the map initial center
* - mapCenterLongitude: decimal, -90 to +90 latitude of the map initial center
* - mapDefaultZoomLevel: integer, map zoom level
*
* - clusterEnabled: bool
* - clusterMaxZoom: integer, beyond this zoom level there will be no clustering
*/
$.fn.csGoogleMapsHelper = function(options) {
var id = $(this).attr('id');
var settings = $.extend(true, $.fn.csGoogleMapsHelper.defaults, options);
$.fn.csGoogleMapsHelper.settings[id] = settings;
var mapOptions = {
mapTypeId: settings.mapTypeId,
center: new google.maps.LatLng(settings.mapCenterLatitude, settings.mapCenterLongitude),
zoom: settings.mapDefaultZoomLevel,
mapTypeControlOptions: {
position: settings.mapTypeControlPosition,
style: settings.mapTypeControlStyle
}
};
$.fn.csGoogleMapsHelper.map[id] = new google.maps.Map(document.getElementById(id), mapOptions);
};
/**
*
*
* @param options settings object for the marker, available settings:
*
* - VenueID: int
* - VenueLatitude: decimal
* - VenueLongitude: decimal
* - VenueMapIconImg: optional, url to icon img
* - VenueMapIconWidth: int, icon img width in pixels
* - VenueMapIconHeight: int, icon img height in pixels
*
* - title: string, marker title
* - draggable: bool
*
*/
$.fn.csGoogleMapsHelper.createMarker = function(id, options, pushToMarkersArray) {
var settings = $.fn.csGoogleMapsHelper.settings[id];
markerOptions = {
map: $.fn.csGoogleMapsHelper.map[id],
position: options.position || new google.maps.LatLng(options.VenueLatitude, options.VenueLongitude),
title: options.title,
VenueID: options.VenueID,
draggable: options.draggable
};
if (options.VenueMapIconImg)
markerOptions.icon = new google.maps.MarkerImage(options.VenueMapIconImg, new google.maps.Size(options.VenueMapIconWidth, options.VenueMapIconHeight));
var marker = new google.maps.Marker(markerOptions);
// lets have the VenueID as marker property
if (!marker.VenueID)
marker.VenueID = null;
google.maps.event.addListener(marker, 'click', function() {
$.fn.csGoogleMapsHelper.loadMarkerInfoWindowContent(id, this);
});
if (pushToMarkersArray) {
// let's collect the markers as array in order to be loop them and set event handlers and other common stuff
$.fn.csGoogleMapsHelper.markers.push(marker);
}
return marker;
};
// this loads the marker info window content with ajax
$.fn.csGoogleMapsHelper.loadMarkerInfoWindowContent = function(id, marker) {
var settings = $.fn.csGoogleMapsHelper.settings[id];
var infoWindowContent = null;
if (!marker.infoWindow) {
$.ajax({
async: false,
type: 'GET',
url: settings.mapMarkersInfoWindowAjaxUrl,
data: { 'VenueID': marker.VenueID },
success: function(data) {
var infoWindowContent = data;
infoWindowOptions = { content: infoWindowContent };
marker.infoWindow = new google.maps.InfoWindow(infoWindowOptions);
}
});
}
// close the existing opened info window on the map (if such)
if ($.fn.csGoogleMapsHelper.infoWindow)
$.fn.csGoogleMapsHelper.infoWindow.close();
if (marker.infoWindow) {
$.fn.csGoogleMapsHelper.infoWindow = marker.infoWindow;
marker.infoWindow.open(marker.map, marker);
}
};
$.fn.csGoogleMapsHelper.finalize = function(id) {
var settings = $.fn.csGoogleMapsHelper.settings[id];
if (settings.clusterEnabled) {
var clusterOptions = {
cluster: true,
maxZoom: settings.clusterMaxZoom
};
$.fn.csGoogleMapsHelper.showClustered(id, clusterOptions);
var venue = $.fn.csGoogleMapsHelper.findMarkerByVenueId(settings.selectedVenueId);
if (venue) {
google.maps.event.trigger(venue, 'click');
}
}
$.fn.csGoogleMapsHelper.setVenueEvents(id);
};
// set the common click event to all the venues
$.fn.csGoogleMapsHelper.setVenueEvents = function(id) {
for (var i in $.fn.csGoogleMapsHelper.markers) {
google.maps.event.addListener($.fn.csGoogleMapsHelper.markers[i], 'click', function(event){
$.fn.csGoogleMapsHelper.setVenueInput(id, this);
});
}
};
// show the clustering (grouping of markers)
$.fn.csGoogleMapsHelper.showClustered = function(id, options) {
// show clustered
var clustered = new MarkerClusterer($.fn.csGoogleMapsHelper.map[id], $.fn.csGoogleMapsHelper.markers, options);
return clustered;
};
$.fn.csGoogleMapsHelper.settings = {};
$.fn.csGoogleMapsHelper.map = {};
$.fn.csGoogleMapsHelper.infoWindow = null;
$.fn.csGoogleMapsHelper.markers = [];
})(jQuery);
Это выглядит так (не совсем так, потому что есть PHP-оболочка для автоматизации)это с одним вызовом, но в основном):
$js = "$('#$id').csGoogleMapsHelper($jsOptions);\n";
if ($this->venues !== null) {
foreach ($this->venues as $row) {
$data = GoogleMapsHelper::getVenueMarkerOptionsJs($row);
$js .= "$.fn.csGoogleMapsHelper.createMarker('$id', $data, true);\n";
}
}
$js .= "$.fn.csGoogleMapsHelper.finalize('$id');\n";
echo $js;
Проблемы вышеупомянутой реализации состоят в том, что я не люблю хранить хэш-карту для «настроек» и «карт»
$id
- это идентификатор элемента DIV, где карта инициализирована.Он используется в качестве ключа в .map, а в .settings есть карты, где я храню настройки и экземпляр GoogleMaps MapObject для каждого инициализированного такого GoogleMaps на странице.$jsOptions
и $data
из кода PHP являются объектами JSON.
Теперь мне нужно иметь возможность создать экземпляр GoogleMapsHelper, который содержит свои собственные настройки и объект карты GoogleMaps, чтобы после его инициализации на некоторыхэлемент (по его идентификатору), я могу использовать этот экземпляр повторно.Но если я инициализирую его для N элементов на странице, у каждого из них должна быть своя конфигурация, объект карты и т. Д.
Я не настаиваю на том, чтобы это было реализовано как плагин jQuery! Я настаиваю на том, что он гибкий и расширяемый, потому что я буду использовать его в большом проекте с более чем дюжиной запланированных в настоящее время различных экранов, где он будет использоваться, так что через несколько месяцев изменение его интерфейса использования станет кошмаром для рефакторинга в целомпроект.
Я добавлю награду за это.