/**
* @module WPGMZA
* @summary This is the core Javascript module. Some code exists in ../core.js, the functionality there will slowly be handed over to this module.
*/
(function($) {
var core = {
maps: [],
events: null,
settings: null,
loadingHTML: '<div class="wpgmza-preloader"><div class="wpgmza-loader">...</div></div>',
/**
* @function guid
* @summary Utility function returns a GUID
* @static
* @return {string} The GUID
*/
guid: function() { // Public Domain/MIT
var d = new Date().getTime();
if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
d += performance.now(); //use high-precision timer if available
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
},
/**
* @function hexOpacityToRGBA
* @summary Takes a hex string and opacity value and converts it to Openlayers RGBA format
* @param {string} colour The hex color string
* @param {number} opacity The opacity from 0.0 - 1.0
* @static
* @return {array} RGBA where color components are 0 - 255 and opacity is 0.0 - 1.0
*/
hexOpacityToRGBA: function(colour, opacity)
{
hex = parseInt(colour.replace(/^#/, ""), 16);
return [
(hex & 0xFF0000) >> 16,
(hex & 0xFF00) >> 8,
hex & 0xFF,
parseFloat(opacity)
];
},
latLngRegexp: /^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/,
/**
* @function isLatLngString
* @summary Utility function returns true is string is a latitude and longitude
* @param str {string} The string to attempt to parse as coordinates
* @static
* @return {array} the matched latitude and longitude or null if no match
*/
isLatLngString: function(str)
{
if(typeof str != "string")
return null;
// Remove outer brackets
if(str.match(/^\(.+\)$/))
str = str.replace(/^\(|\)$/, "");
var m = str.match(WPGMZA.latLngRegexp);
if(!m)
return null;
return {
lat: parseFloat(m[1]),
lng: parseFloat(m[3])
};
},
/**
* @function stringToLatLng
* @summary Utility function returns a latLng literal given a valid latLng string
* @param str {string} The string to attempt to parse as coordinates
* @static
* @return {object} LatLng literal
*/
stringToLatLng: function(str)
{
var result = WPGMZA.isLatLngString(str);
if(!result)
throw new Error("Not a valid latLng");
return result;
},
/**
* @function getImageDimensions
* @summary Utility function to get the dimensions of an image, caches results for best performance
* @param src {string} Image source URL
* @param callback {function} Callback to recieve image dimensions
* @static
* @return {void}
*/
imageDimensionsCache: {},
getImageDimensions: function(src, callback)
{
if(WPGMZA.imageDimensionsCache[src])
{
callback(WPGMZA.imageDimensionsCache[src]);
return;
}
var img = document.createElement("img");
img.onload = function(event) {
var result = {
width: image.width,
height: image.height
};
WPGMZA.imageDimensionsCache[src] = result;
callback(result);
};
img.src = src;
},
/**
* @function isDeveloperMode
* @summary Returns true if developer mode is set
* @static
* @return {boolean} True if developer mode is on
*/
isDeveloperMode: function()
{
return this.developer_mode || (window.Cookies && window.Cookies.get("wpgmza-developer-mode"));
},
/**
* @function isProVersion
* @summary Returns true if the Pro add-on is active
* @static
* @return {boolean} True if the Pro add-on is active
*/
isProVersion: function()
{
return (this._isProVersion == "1");
},
/**
* @function openMediaDialog
* @summary Opens the WP media dialog and returns the result to a callback
* @param {function} callback Callback to recieve the attachment ID as the first parameter and URL as the second
* @static
* @return {void}
*/
openMediaDialog: function(callback) {
// Media upload
var file_frame;
// If the media frame already exists, reopen it.
if ( file_frame ) {
// Set the post ID to what we want
file_frame.uploader.uploader.param( 'post_id', set_to_post_id );
// Open frame
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frames.file_frame = wp.media({
title: 'Select a image to upload',
button: {
text: 'Use this image',
},
multiple: false // Set to true to allow multiple files to be selected
});
// When an image is selected, run a callback.
file_frame.on( 'select', function() {
// We set multiple to false so only get one image from the uploader
attachment = file_frame.state().get('selection').first().toJSON();
callback(attachment.id, attachment.url);
});
// Finally, open the modal
file_frame.open();
},
/**
* @function getCurrentPosition
* @summary This function will get the users position, it first attempts to get
* high accuracy position (mobile with GPS sensors etc.), if that fails
* (desktops will time out) then it tries again without high accuracy
* enabled
* @static
* @return {object} The users position as a LatLng literal
*/
getCurrentPosition: function(callback)
{
if(!navigator.geolocation)
{
console.warn("No geolocation available on this device");
return;
}
var options = {
enableHighAccuracy: true
};
navigator.geolocation.getCurrentPosition(function(position) {
callback(position);
},
function(error) {
options.enableHighAccuracy = false;
navigator.geolocation.getCurrentPosition(function(position) {
callback(position);
},
function(error) {
console.warn(error.code, error.message);
},
options);
},
options);
},
/**
* @function runCatchableTask
* @summary Runs a catchable task and displays a friendly error if the function throws an error
* @param {function} callback The function to run
* @param {HTMLElement} friendlyErrorContainer The container element to hold the error
* @static
* @return {void}
*/
runCatchableTask: function(callback, friendlyErrorContainer) {
if(WPGMZA.isDeveloperMode())
callback();
else
try{
callback();
}catch(e) {
var friendlyError = new WPGMZA.FriendlyError(e);
$(friendlyErrorContainer).html("");
$(friendlyErrorContainer).append(friendlyError.element);
$(friendlyErrorContainer).show();
}
},
/**
* @function assertInstanceOf
* @summary
* This function is for checking inheritence has been setup correctly.
* For objects that have engine and Pro specific classes, it will automatically
* add the engine and pro prefix to the supplied string and if such an object
* exists it will test against that name rather than the un-prefix argument
* supplied.
*
* For example, if we are running the Pro addon with Google maps as the engine,
* if you supply Marker as the instance name the function will check to see
* if instance is an instance of GoogleProMarker
* @param {object} instance The object to check
* @param {string} instanceName The class name as a string which this object should be an instance of
* @static
* @return {void}
*/
assertInstanceOf: function(instance, instanceName) {
var engine, fullInstanceName, assert;
var pro = WPGMZA.isProVersion() ? "Pro" : "";
switch(WPGMZA.settings.engine)
{
case "google-maps":
engine = "Google";
break;
default:
engine = "OL";
break;
}
if(WPGMZA[engine + pro + instanceName])
fullInstanceName = engine + pro + instanceName;
else if(WPGMZA[pro + instanceName])
fullInstanceName = pro + instanceName;
else if(WPGMZA[engine + instanceName])
fullInstanceName = engine + instanceName;
else
fullInstanceName = instanceName;
assert = instance instanceof WPGMZA[fullInstanceName];
if(!assert)
throw new Error("Object must be an instance of " + fullInstanceName + " (did you call a constructor directly, rather than createInstance?)");
},
/**
* @function getMapByID
* @param {mixed} id The ID of the map to retrieve
* @static
* @return {object} The map object, or null if no such map exists
*/
getMapByID: function(id) {
for(var i = 0; i < WPGMZA.maps.length; i++) {
if(WPGMZA.maps[i].id == id)
return WPGMZA.maps[i];
}
return null;
},
/**
* @function isGoogleAutocompleteSupported
* @summary Shorthand function to determine if the Places Autocomplete is available
* @static
* @return {boolean}
*/
isGoogleAutocompleteSupported: function() {
return typeof google === 'object' && typeof google.maps === 'object' && typeof google.maps.places === 'object' && typeof google.maps.places.Autocomplete === 'function';
}
};
if(window.WPGMZA)
window.WPGMZA = $.extend(window.WPGMZA, core);
else
window.WPGMZA = core;
for(var key in WPGMZA_localized_data)
{
var value = WPGMZA_localized_data[key];
WPGMZA[key] = value;
}
/*for(var key in WPGMZA_localized_data)
WPGMZA[key] = WPGMZA_localized_data[key];
$(document).ready(function(event) {
// Datatables to throw errors
if($.fn.dataTable)
$.fn.dataTable.ext.errMode = 'throw';
// Combined script warning
if($("script[src*='wp-google-maps.combined.js'], script[src*='wp-google-maps-pro.combined.js']").length)
console.warn("Minified script is out of date, using combined script instead.");
// Check for multiple jQuery versions
var elements = $("script").filter(function() {
return this.src.match(/(^|\/)jquery\.(min\.)?js(\?|$)/i);
});
if(elements.length > 1)
console.warn("Multiple jQuery versions detected: ", elements);
// Disable map edit page preloader in developer more
if(WPGMZA.isDeveloperMode())
$("#wpgmza-map-edit-page form.wpgmza").show();
// Shortcode boxes
$(".wpgmza_copy_shortcode").on("click", function() {
var temp = $("<input>");
var temp2 = $('<div id="wpgmza_tmp" style="display: none;" width:100%; text-align:center;"/>');
$(document.body).append(temp);
temp.val($(this).val()).select();
document.execCommand("copy");
temp.remove();
$(this).after(temp2);
$(temp2).html(
$("[data-shortcode-copy-string]").attr("data-shortcode-copy-string")
);
$(temp2).fadeIn();
setTimeout(function() {
$(temp2).fadeOut();
}, 1000);
setTimeout(function() {
$(temp2).remove();
}, 1500);
});
// Fancy switches
// $("form.wpgmza .cmn-toggle").each(function(index, el) {
//
// $(el).wrap("<div class='switch'/>");
// $(el).after("<label for=""/>")
//
// });
$("form.wpgmza").on("click", ".switch label", function(event) {
var input = $(this).prev(".cmn-toggle");
if(input.prop("disabled"))
return;
var val = !input.prop("checked");
input.prop("checked", val);
if(val)
input.attr("checked", "checked");
else
input.removeAttr("checked");
input.trigger("change");
});
// Geolocation warnings
if(window.location.protocol != 'https:')
{
var warning = '<span class="notice notice-warning">' + WPGMZA.localized_strings.unsecure_geolocation + "</span>";
$(".wpgmza-geolocation-setting").after(
$(warning)
);
}
// Switch off thanks for feedback message
document.cookie = "wpgmza_feedback_thanks=false; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
});*/
})(jQuery);