I'm using Code Igniter and the Googlemaps library. This library generates a lot of Javascript code dynamically, including the contents of the InfoWindows for each new marker, but I'd like to keep that in a separate template file, like a regular View.
I have this Javascript code (from Googlemaps' library):
var lat = marker.getPosition().lat();
var long = marker.getPosition().lng();
var windowContent = "";
if( _new ) {
var newIW = new google.maps.InfoWindow( { content: windowContent } );
What I want to do is to load windowContent from a template file. I have already succeeded in dynamically generating a form for this variable and using lat and long variables defined just above, but how can I achieve this in Code Igniter? I can't use load->view because I'm not in a Controller's context. And I cannot use include() or readfile() either because of CI's security constraints.
Any hints?
Using pure javascript, get the lat and long, make a url with the lat and long in the query string, and use xhr to do the ajax call.
var lat = marker.getPosition().lat();
var long = marker.getPosition().lng();
var xhr;
var url = "http://myurl.to/script.php?lat="+lat+"&lng="+long;
if(typeof XMLHttpRequest !== 'undefined')
xhr = new XMLHttpRequest();
else {
//Get IE XHR object
var versions = ["MSXML2.XmlHttp.5.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.2.0",
"Microsoft.XmlHttp"];
for(var i = 0, len = versions.length; i < len; i++) {
try {
xhr = new ActiveXObject(versions[i]);
break;
}
catch(e){}
}
}
xhr.onreadystatechange = function(){
//This function is called every so often with status updates
//It is complete when status is 200 and readystate is 4
if(xhr.status == 200 && xhr.readyState === 4) {
//Returned data from the script is in xhr.responseText
var windowContent = xhr.responseText;
//Create the info window
var newIW = new google.maps.InfoWindow( { content: windowContent } );
//Pass newIW to whatever other function to use it somewhere
}
};
xhr.open('GET', url, true);
xhr.send();
if using a library like jQuery it would be like
var lat = marker.getPosition().lat();
var long = marker.getPosition().lng();
var url = "http://myurl.to/script.php";
jQuery.ajax({
"url":url,
"data":{ //Get and Post data variables get put here
"lat":lat,
"lng":long
},
"dataType":"html", //The type of document you are getting, assuming html
//Could be json xml etc
"success":function(data) { //This is the callback when ajax is done and successful
//Returned data from the script is in data
var windowContent = data;
//Create the info window
var newIW = new google.maps.InfoWindow( { content: windowContent } );
//Pass newIW to whatever other function to use it somewhere
}
});
Related
Trying to parse the input JSON from the Woocommerce Webhook to Google Spreadsheet via Google App Script.
Used this one :
function doPost(request) {
var json = request.postData.getDataAsString();
var obj = JSON.parse(json);
// getting some of the Woocommerce data just as an example
// Hook was fired after order.created
var id = obj.order.id;
var orderNumber = obj.order.order_number;
var payMethod = obj.order.payment_details.method_title;
// write data in a document, not useful, but straightforward for testing
var doc = DocumentApp.openById('myDocumentId');
doc.appendParagraph("Id: " + id);
doc.appendParagraph("orderNumber: " + orderNumber);
doc.appendParagraph("payMethod: " + payMethod);
}
But receive nothing into the Google Sheets.
And with this one:
function doPost(request) {
var content = JSON.parse(request.postData.contents);
var row = [];
for (var elem in content) {
row.push(content[elem]);
}
var ss = SpreadsheetApp.openById("SHEET ID")
var sheet = ss.getSheetByName("Sheet1");
sheet.appendRow(row);
var result = {"result":"ok"};
return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);
}
It's receiving data, but it's not parsed:
Is there anyway to fix this and make the data in sheet viewable?
Thanks in advance.
I have found the answer on my question at https://ru.stackoverflow.com/
thanks to Alexander Ivanov
The main thing why the woocommerce webhook not parsed is that the JSON is not valid when WC send it to the spreadsheet macros.
And sheet posting it as one element {order:{}}
so we need to edit the code like this :
var content = JSON.parse(request.postData.contents)[0];
or like this (in my case):
var content = JSON.parse(request.postData.contents)['order'];
in case we have no idea what data will be received, we may try to determine the value:
function doPost(request) {
var result = {
result: undefined
};
try {
var content = JSON.parse(request.postData.contents);
var row = [];
if (content.hasOwnProperty('order')) {
for (var elem in content['order']) {
row.push(content['order'][elem]);
}
} else {
row.push(request.postData.contents);
}
var ss = SpreadsheetApp.openById('SHEET ID')
var sheet = ss.getSheets()[0];
sheet.appendRow(row);
result.result = 'ok';
} catch (err) {
result.result = 'err';
}
return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);
}
Please read below my scenario…
I have a PHP file wherein I have javascript within it..
<?php
echo ‘<script>’;
echo ‘window.alert(“hi”)’;
echo ‘</script>’;
?>
On execution of this file directly, the content inside the script is executed as expected. But if this same page is being called via ajax from another page, the script part is NOT executed.
Can you please let me know the possible reasons.
(note: I’m in a compulsion to have script within php page).
When you do an AJAX call you just grab the content from that page. JavaScript treats it as a string (not code). You would have to add the content from the page to your DOM in your AJAX callback.
$.get('/alertscript.php', {}, function(results){
$("html").append(results);
});
Make sure you change the code to fit your needs. I'm supposing you use jQuery...
Edited version
load('/alertscript.php', function(xhr) {
var result = xhr.responseText;
// Execute the code
eval( result );
});
function load(url, callback) {
var xhr;
if(typeof XMLHttpRequest !== 'undefined') xhr = new XMLHttpRequest();
else {
var versions = ["MSXML2.XmlHttp.5.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.2.0",
"Microsoft.XmlHttp"]
for(var i = 0, len = versions.length; i < len; i++) {
try {
xhr = new ActiveXObject(versions[i]);
break;
}
catch(e){}
} // end for
}
xhr.onreadystatechange = ensureReadiness;
function ensureReadiness() {
if(xhr.readyState < 4) {
return;
}
if(xhr.status !== 200) {
return;
}
// all is well
if(xhr.readyState === 4) {
callback(xhr);
}
}
xhr.open('GET', url, true);
xhr.send('');
}
I'm new to PHP, but I'm developing in Visual Studio LightSwitch.
I'd like to pass several javascript variables from a data record to a PHP script during a javascript save event.
What are my options?
Your options are limited to ajax, or an image request.
Option 1. AJAX
function success() {
console.log(this.responseText);
}
var ajax = new XMLHttpRequest();
ajax.onload = success;
// myVars is a string containing the values you need to record. In the format
// of ?var=value&var1=value&var2=value
ajax.open("get", "/record.php?" + myVars, true);
ajax.send();
Option 2. Image
var a = document.getElementById('my-button');
a.addEventListener('click', function(e) {
var target = e.target || e.srcElement;
var img = new Image();
// get your variables values and create a url here.
img.src = 'http://myserver.tld/record.php?' + myVars;
});
I use JQuery to pull form data and send an XMLHttpRequest(); I open the request using the POST method. The image and supplementary data are passed to a PHP script that handles, resizes, and saves it to the server. The file name and location of the image are updated in the relevant fields in a MySQL database. On the uploadComplete(evt) I attempt to display the newly uploaded image by calling .load() to populate a div.
80% of the time, the image displays correctly when the content is loaded into the div. 20% of the time, the image is displayed as if the link provided were a broken link. However, if I refresh the page, the image is displayed correctly.
Why does the image sometimes show as a broken link?
How do I stop it from doing this?
* EDIT
function loadFile()
{
var fileURL = $( "#url" ).val();
if(fileURL == "")
{
// Retrieve the FileList object from the referenced element ID
var myFileList = document.getElementById('upload_file').files;
// Grab the first File Object from the FileList
var myFile = myFileList[0];
// Set some variables containing the three attributes of the file
var myFileName = myFile.name;
var myFileSize = myFile.size;
var myFileType = myFile.type;
// Let's upload the complete file object
imageUpdate(myFile);
}
else
{
var newinfo = new Array();
newinfo[0] = "URL";
newinfo[1] = fileURL;
imageUpdate(newinfo);
}
}
function imageUpdate(newinfo)
{
var formData = new FormData(); // data object
// extra
var stylistID = $( "#editThisStylist" ).data('stylistid'); // Grab stlyistID
formData.append("stylistID", stylistID);
// IF URL
if ( newinfo[0] == "URL" ){
formData.append("type", "URL");
formData.append("url", newinfo[1]);
}
// IF LOCAL FILE
else
{
formData.append("type", "FILE");
// Append our file to the formData object
// Notice the first argument "file" and keep it in mind
formData.append('my_uploaded_file', newinfo);
}
// Create our XMLHttpRequest Object
var xhr = new XMLHttpRequest();
xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", transferFailed, false);
xhr.addEventListener("abort", transferCanceled, false);
// Open our connection using the POST method
xhr.open("POST", "u/stylist_avatar.php", true);
// Request headers
//xhr.setRequestHeader("Content-Type", formData.files[0].type);
// Send the file
xhr.send(formData);
}
// While xhr is in progress
function updateProgress(oEvent)
{
if (evt.lengthComputable)
{
//var progressBar = document.getElementById("progressBar");
//var percentComplete = oEvent.loaded / oEvent.total;
//progressBar.value = percentComplete;
}
else
{
// unable to compute progress information since the total size is unkown
}
}
// onComplete
function uploadComplete(evt) {
//alert("The transfer is complete.");
resetForm($('#uploadImageForm'));
var stylistID = $( "#editThisStylist" ).data('stylistid'); // Grab stlyistID
$('#uploadImageModal').modal('toggle');
// Reload right div
$( "#editStylistRight" ).load( "u/stylist_lookup.php", {stylistID: stylistID}, function (){});
// Reload stylist list
var index = 0;
var numRecords = 10;
$( "#stylistTable" ).load( "u/stylist_lookuptable.php", {start: index, end: numRecords}, function (){});
}
function transferFailed(evt) {
alert("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
alert("The transfer has been canceled by the user.");
}
It seems that you are trying to show the new image before the PHP script in fact create and save the new image.
Instead of calling the javascript function that loads the new image on the "uploadComplete", use the "success" param (if you are using jQuery $.ajax function) that call the function that loads the new image.
The "success" function is called only when the server finish processing the request (when the PHP script finish editing and saving the image) and not when the new image params were succesfully sent to the server.
This happens because of image cache,force browser to fetch image evrytime.
use this in uploadcomplete event
var timestamp = new Date();
timestamp = timestamp.getTime();
imageurl+'?t='+timestamp;
I have a database where i'm using php to randomize the information by ID and send it out via xml. My issue is that I only want to grab the xml once and store it for use in at least 2 functions... one function that runs onload to grab the first line of xml, another that will run every time a button is pressed to access the next line of xml until the end. My 2 functions are loadfirst() and loadnext(). loadfirst() works perfectly, but I'm not sure how to pass the xml data to loadnext(). Right now I'm just using loadfirst() on pageload and loadfirst() on button press, but i end up creating new xml from the database each time which causes randomization issues and is incredibly inefficient. Any help would be appreciated.
var places;
var i = 0;
function loadXML(){
downloadUrl("places.php", function(data){
places = data.responseXML;
getFeatured(i);
});
}
function getFeatured(index){
var id = places[index].getAttribute("id");
var name = places[index].getAttribute("name");
var location = places[index].getAttribute("location");
var imgpath = places[index].getAttribute("imgpath");
var tags = places[index].getAttribute("tags");
}
function getPrev() {
i--;
getFeatured(i);
}
function getNext() {
i++;
getFeatured(i);
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
loadnext() will be very similar to loadfirst(), I'm just running into issues with passing the xml data so that i can use it without having to access the database again. Thanks.
Set your xml and i in public scope. Then all you have to do is increment/decrement i and re-read data from XML. Something like this:
var xml;
var xml_idx = 0; // replaces your i counter
function loadXML() {
downloadUrl ("places.php", function(data) {
xml = data.responseXML;
)};
}
function loadItem(index) {
var id = xml[index].getAttribute("id");
var name = xml[index].getAttribute("name");
var location = xml[index].getAttribute("location");
var imgpath = xml[index].getAttribute("imgpath");
var tags = xml[index].getAttribute("tags");
// do something with this data
}
function loadCurrentItem() {
loadItem(xml_idx);
}
function loadNextItem() {
xml_idx++;
loadItem(xml_idx);
}
function loadPreviousItem() {
xml_idx--;
loadItem(xml_idx);
}
// usage
loadXML(); // do this first to populate xml variable
loadItem(xml_idx); // loads first item (i=0)
loadCurrentItem(); // loads i=0
loadNextItem(); // loads i=1
loadNextItem(); // loads i=2
loadPreviousItem(); // loads i=1
If you really want to get fancy (and keep the global namespace cleaner), you could easily make this into a class.
Use global variables (items - items array, iterator - counter) to store data available for all functions.
Try something like this:
items = false;
iterator = 0;
function loadfirst(){
downloadUrl ("places.php", function(data) {
var i = 0;
var xml = data.responseXML;
var places = xml.documentElement.getElementsByTagName("place");
var id = places[i].getAttribute("id");
var name = places[i].getAttribute("name");
var location = places[i].getAttribute("location");
var imgpath = places[i].getAttribute("imgpath");
var tags = places[i].getAttribute("tags");
items = places;
iterator++;
)};
}
function loadnext(){
var i = iterator;
var id = items[i].getAttribute("id");
var name = items[i].getAttribute("name");
var location = items[i].getAttribute("location");
var imgpath = items[i].getAttribute("imgpath");
var tags = items[i].getAttribute("tags");
iterator++;
}
You should wrap all this into a single object to control scope and data state. (Untested code below, which should just illustrate a possible pattern and interface to use.)
function PlacesScroller(url, callback) {
this.url = url;
this.data = null;
this._index = null;
this.length = 0;
var self = this;
downloadURL(this.url, function(result, status) {
if (Math.floor(status/100)===2) {
self.setData(result);
}
if (callback) {
callback(self, result);
}
});
}
PlacesScroller.prototype.setData(xmldom) {
this._index = 0;
// this may require changing; it depends on your xml structure
this.data = [];
var places = xmldom.getElementsByTagName('place');
for (var i=0; i<places.length; i++) {
this.data.push({
id : places[i].getAttribute('id'),
name : places[i].getAttribute('name')
// etc
});
}
}
PlacesScroller.prototype.getPlaceByIndex = function(index) {
if (this.data) {
return this.data[index];
} else {
return null;
}
}
PlacesScroller.prototype.getCurrentFeature = function() {
return this.getPlaceByIndex(this._index);
}
PlacesScroller.prototype.addToIndex(i) {
// This sets the index forward or back
// being careful not to fall off the end of the data
// You can change this to (e.g.) cycle instead
if (this.data===null) {
return null;
}
var newi = i+this._index;
newi = Math.min(newi, this.data.length);
newi = Math.max(0, newi);
this._index = newi;
return this._index;
}
PlacesScroller.prototype.getNextFeature = function() {
this.addToIndex(1);
return this.getCurrentFeature();
}
PlacesScroller.prototype.getPreviousFeature = function() {
this.addToIndex(-1);
return this.getCurrentFeature();
}
Then initialize it and use it like so:
var scroller = new PlacesScroller('places.php', function(scrollerobject, xmlresult){
// put any initialization code for your HTML here, so it can build after
// the scrollerobject gets its data.
// You can also register event handlers here
myNextButton.onclick = function(e){
var placedata = scrollerobject.getNextFeature();
myPictureDisplayingThing.update(placedata);
}
// etc
});