I need to build a jQuery plugin that will return one instance per selector id. The plugin should and will be used only for elements with id (it is impossible to use a selector that matches many elements), so it should be used as follows:
$('#element-id').myPlugin(options);
- I need to have several private methods for the plugin, as well as several public methods. I can achieve this, but my main problem is that I want to get the exact same instance every time I call $ ('# element-id'). MyPlugin ().
- And I want to have some code that should only be executed the first time the plugin is initialized for a given ID (construct).
- The
options parameter must be provided for the first time, for the construct, after which I do not want the construct to be executed so that I can access the plugin in the same way as $ ('# element-id'). MyPlugin () - The plugin should be able to work with several elements (usually up to two) on one page (but each of them will require its own configuration, again - they will be initialized by identifier, and not for the usual class selector for example).
- The above syntax, for example, is open to any suggestions on how to achieve this pattern.
I have quite some OOP experience with another language, but limited knowledge of javascript, and I'm really confused about how everything is correct.
EDIT
To develop - this plugin is a GoogleMaps v3 API (helper) API to help me get rid of code duplication, as in many places I use Google maps, usually with markers. This is the current library (lots of code removed, only the most important methods left):
;(function($) { $.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); }; $.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);
This is similar to this (in fact, it is not, because there is a PHP shell for automation with a single call, but mostly):
$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;
The problems of the above implementation are that I don’t like to save the hash map for “settings” and “maps”
$id is the identifier of the DIV element where the card is initialized. It is used as a key in .map and .settings has maps, where I store settings and a MapMobject GoogleMaps instance for each initialized such GoogleMaps on the page. $jsOptions and $data from PHP code are JSON objects.
Now I need to create an instance of GoogleMapsHelper, which contains its own settings and a GoogleMaps map object, so that after I initialize it on a specific element (by its identifier), I can reuse this instance. But if I initialize it to N elements on the page, each of them should have its own configuration, map object, etc.
I am not saying that this is implemented as a jQuery plugin! . I insist that it is flexible and extensible, because I will use it in a large project with more than a dozen currently planned different screens, where it will be used in a few months, changing the usage interface will be a nightmare to refactor the whole project .
I will add generosity for this.