I am trying to generate docFiles on my webapp. First i was thinking of using some tool in the Frontend like Markswindolls 'jquery.wordexport.js' tool. But since there are not much functions like setting Header or Footer or aligning, I started to work with 'phpword'.
My Problem now is, that the docFile is saved on the server. Is there any possibility of sending the file via ajax to the Frontend so the User can get the File after pushing on my 'download as .doc' button?
Any other recommendations are welcome too.
jquery:
$('#word-button').on('click', function() {
$.ajax({
type: "POST",
url: "phpWORD/gendocx.php",
success: function (msg, string, jpXHR) {
console.log('AJAX SUCCESS');
},
complete : function(data, textStatus, jqXHR){
console.log('AJAX COMPLETE');
},
error: function(xhr, desc, err) {
console.log(xhr);
console.log("Details: " + desc + "\nError:" + err);
}
});
})
gendocx.php:
<?php
require_once 'PHPWord.php';
$PHPWord = new PHPWord();
$section = $PHPWord->createSection();
// Create a new PHPWord Object
$PHPWord = new PHPWord();
// Every element you want to append to the word document is placed in a section. So you need a section:
$section = $PHPWord->createSection();
// After creating a section, you can append elements:
$section->addText('Hello world!');
// You can directly style your text by giving the addText function an array:
$section->addText('Hello world! I am formatted.', array('name'=>'Tahoma', 'size'=>16, 'bold'=>true));
// If you often need the same style again you can create a user defined style to the word document
// and give the addText function the name of the style:
$PHPWord->addFontStyle('myOwnStyle', array('name'=>'Verdana', 'size'=>14, 'color'=>'1B2232'));
$section->addText('Hello world! I am formatted by a user defined style', 'myOwnStyle');
// You can also putthe appended element to local object an call functions like this:
$myTextElement = $section->addText('Hello me!');
// At least write the document to webspace:
$objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
$objWriter->save('helloWorld.docx');
?>
This is what I use for PHP Excel, sorry about fragmentation, but this is from a large service file:
$this->generateXls();
$this->writeToVariable();
if ($response instanceof Response) {
$this->setHeaders($response->getHeaders());
}
$response->setContent($this->getXlsContent());
This is where the file content is stored to a variable instead of a file:
protected function writeToVariable()
{
ob_start();
$this->getWriter()->save('php://output');
$xlsContent = ob_get_clean();
$this->setXlsContent($xlsContent);
}
And just set the headers before returning your response
protected function setHeaders(Headers $headers)
{
$headers->addHeaderLine('Content-Type', $this->getFileMimeType());
$headers->addHeaderLine('Content-Disposition', "attachment; filename=\"{$this->getFullFileName()}\"");
$headers->addHeaderLine('Accept-Ranges', 'bytes');
$headers->addHeaderLine('Content-Length', strlen($this->getXlsContent()));
}
This is done in zf2 so headers are injected in to response object but in your case just add them to whatever generates your output.
Oh, btw, mime type for excel looks like this:
$this->setFileMimeType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
So try to find the one for the ms word format you want to output, that is in this format.
For a simplified non-OO approch:
$writer = \PHPExcel_IOFactory::createWriter($this->getWorkbook(), $type);
//<---GENERATE YOUR DOCUMENT HERE
ob_start();
$writer->save('php://output');
$document = ob_get_clean();
//<---SET OUTPUT HEADERS LIKE FOR ANY OTHER FILE TYPE HERE
echo $document;
die;
Related
I need to update a span element with a value from an update PHP function (that performs mySQL queries), triggered after a button click. I used jQuery/Ajax to achieve this, via a function in another file.
Apparently PHP logs in this case require the following form:
echo '<script> console.log("My message"); </script>';
So I put these in my PHP function file, which looks like the following:
if(isset($_POST['myAction'])) {
if ($_POST['myAction'] == "right_action") {
echo '<script> console.log("ENTERED"); </script>';
update(...)
...
}
}
function init()
{
...
echo '<script> console.log("Successfully connected to database"); </script>';
return ...;
}
function fetch(...) {
init();
...
echo '<script> console.log("Database fetch successful"); </script>';
echo '<script> console.log(' . result . '); </script>'; // equals 49
return ...;
}
function update(...) {
init();
...
echo '<script> console.log("Database update successful"); </script>';
return fetch(...);
}
On the one hand, the logs appear properly while the PHP is executing.
However it seems that the return value of the update PHP function, from the perspective of the Ajax function, contains all the logs. Here is the Ajax function:
$.ajax({
method: "POST",
url: "my_php_file.php",
data: { myAction: 'myAction',
(params) },
success: function(result) {
console.log("Success at Ajax transfer-to-PHP");
console.log("RESULT: " + result);
spanElement.load(result);
},
error: function(error) {
console.log("Error at Ajax transfer-to-PHP: " + error);
}
});
And the Ajax log:
RESULT
<script> console.log("ENTERED"); </script><script> console.log("Successfully connected to database"); </script><script> console.log("Database update successful"); </script><script> console.log("Successfully connected to database"); </script><script> console.log("Database fetch successful"); </script><script> console.log(49); </script>
The same behavior happens when I print in Ajax the content of the span element, initially filled with the result from the fetch PHP function. It prints all the logs; but then it does print the value (while the update mechanic above doesn't even).
I think you are approaching this very unusually, and making things quite hard for yourself. I've never seen PHP returning Javascript to do console.log() before. I'm sure it works, and maybe it really suits what you need, but it seems very Rube Goldberg-ish to me.
If you want to generate logs of what your PHP is doing, just do it in PHP on the server. You can then monitor your application log on the server.
If you want a response from your PHP that your browser can handle and use to update your page, just return the response as text, or better yet as JSON, so you can include eg a status as well as a message. If you really want to pass log messages back to the browser, you could structure the response to include a log element which will be logged to the console, along with a message element to display to the user. You might want to include a status or success element, which is true or false.
There are thousands of examples here on SO, here's a highly ranked one, here's a simpler one, but searching for anything like "php ajax example" will turn up plenty more for inspiration.
As to why your result includes multiple msgs, just trace through what your PHP is doing - each step echoes a message, one after the other. They're all part of the content returned to your Javascript.
I see one bug in your Javascript - .load() loads content from the specified URL. You've already loaded content with your .ajax(), and result is not a URL, so that isn't doing what you expect and won't work.
Here's some clunky pseudo-code which skips over some specifics but gives you a general idea. If you want to keep a running log of each step as you are currently, you'll have to pass your $response array around to/from your functions, or if this is a PHP class make it a class property to avoid that. If you just log to the server you can avoid that, since you only need the final result of your update().
$response = [];
if(isset($_POST['myAction'])) {
if ($_POST['myAction'] == "right_action") {
// If you really want to return log msgs to the browser
$response['log'][] = 'ENTERED';
// More appropriate might be to just log them in PHP. How you do that is
// up to you, eg if you are using a library or just your own simple fopen(),
// fwrite() etc. Though you might not want this level of detail after initial
// development.
// myLogger('Entered');
// In this pseudo-code you'll have to include $response as parameter passed
// to your functions so they can update it, and they'll have to return it
update(...)
...
}
}
// Return your response as JSON which is easy for JS to work with
header('Content-Type: application/json');
echo json_encode($response);
function init()
{
...
$response['log'][] = 'Successfully connected to database';
// myLogger('Successfully connected to database')
return ...;
}
function fetch(...) {
init();
...
$response['log'][] = 'Database fetch successful';
$response['message'] = $result;
// myLogger('Database fetch successful')
return ...;
}
function update(...) {
init();
...
$response['log'][] = 'Database update successful';
// myLogger('Database update successful')
return fetch(...);
}
Then your Javascrtipt can do something like:
$.ajax({
method: "POST",
url: "my_php_file.php",
data: {
myAction: 'myAction',
(params)
},
success: function(result) {
console.log("Success at Ajax transfer-to-PHP");
// Log your log msgs
console.log("RESULT:");
console.dir(result.log);
// .load() will load the specified remote content, similar to .ajax()
// spanElement.load(result);
// You can use .html() or .text() to update your span
// https://api.jquery.com/html/
spanElement.html(result.message);
},
error: function(error) {
console.log("Error at Ajax transfer-to-PHP: " + error);
}
});
I am completely stuck since two hours and definitely need your help. Disclaimer: I am not a coder - just a guy who is trying to mock up an idea.
So my page is actually working fine but I thought about moving content from a modal-popup to an actual sub-page. Meaning: If a user clicks on a button, some data points from the current page are being collected and passed to another view which shall be rendered using the data points as input.
EDIT: For clarification: The button is on /results.php where data is generated dynamically. The method should take some data points from here and generate a new view and render it at /buy.php or maybe at /buy/custom.php
My thoughts:
Normal redirect without parameters: Internal Link
Updating page-content without redirect but with parameters: Ajax
So combining my thoughts -> use ajax and return a new fresh view.
What I tried:
$("body").on("click", ".fa-shopping-cart", function() {
var $para1 = $(this).attr("data1");
var $para2 = $(this).attr("data2");
var $para3 = $(this).attr("data3");
var $para4 = $(this).attr("data4");
$.ajax({
url: "buy",
data: {
a: $para1,
b: $para2,
c: $para3,
d: $para4
},
beforeSend: function (xhr) {
var token = $('meta[name="csrf_token"]').attr('content');
if (token) {
return xhr.setRequestHeader('X-CSRF-TOKEN', token);
}
},
type: "post",
success: function(response){
console.log(response);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(JSON.stringify(jqXHR));
console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
}
});});
Routing:
Route::post('/buy', 'PageRouting#buy');
Controller:
public function buy()
{
$para1= $_POST['a'];
$para2 = $_POST['b'];
$para3 = $_POST['c'];
$para4 = $_POST['d'];
// some magic to output $data
return view('pages.buy', compact("data"));
}
buy.blade.php exists and displays $data with help of an foreach-loop.
So, when I first clicked the button the obvious happend:
The view ('pages.buy') is logged / displayed in my console in plain html and not rendered in the browser.
Now I am sitting here since two hours and I have no clue whatsoever. I read some blog post saying that you cannot redirect within an ajax-call. Unfortunately the post did not gave any hint on how to do it instead.
Can someone help me?
All best
If you want to replace entire document with the response you have to use document.write but it's not the best thing to do. Why don't you use normal form submit if you need to return a view?
success: function(response){
document.write(response);
},
P.S. if you want also to change the url, use the history manipulation functions.
https://developer.mozilla.org/en-US/docs/Web/API/History_API
in your buy method -
public function buy ()
{
....//some stuff to get $data
$html = view('pages.buy', compact("data"))->render();
return response()->json([
'success' => true,
'html' => $html
])
}
in your ajax success function
success: function(response){
if(response.success)
{
$('#elementId').html(reponse.html) // or whatever you need
}
},
I use the Jquery .sortable() function to let the site admin re-order some list elements on the start page on a Drupal 7 site. Then I want the admin to be able to save the node to keep this new sort order. In order to do this I added a Save button with js on the client side. When clicked on I have this so far:
$('a.save').on('click', function () {
// get the current nid
var nid = Drupal.settings.mymodule.currentNid;
var data = [];
// copy the re-ordered html list
data['body'] = $('.field-name-body').clone()
$.ajax({
// after reading the ajax api documentation I am more than confused about the url to use
url: '??',
type: 'post',
dataType: "html",
data: {
nid: nid,
body: data['body'].html()
},
success: function(data) {
if (data == false) {
alert('Not saved, access denied.');
} else {
alert('Changes saved');
}
}
});
So in the normal world I would write a php script that saves the data in the node with the specified node id. And the url should point to that script... But I am stuck in the Drupal 7 documentation on how to do this... All examples i can find describes how to pull html from the server side to the client side, but I want to copy html from the client side and save it in the specfied node on the server side. Should I write a function to recieve the ajax request in a custom module? Can anyone point me in the right direction?
PARTIALLY SOLVED:
I finally found the solution about the url which became like this:
url: Drupal.settings.mymodule.ajaxUrl + "/" + nid,
I have now written a custom module where I successfully can save content in a certain node field with this code:
function save_node_init() {
drupal_add_js(array('save_node' => array('ajaxUrl' => url('save_node/ajax'))), 'setting');
drupal_add_js(drupal_get_path('module', 'save_node') . '/save_node.js');
}
function save_nod_menu() {
$items['save_node/ajax/%'] = array(
'page callback' => 'save_node_ajax_callback',
'access callback' => 'user_access',
'access arguments' => array('administer users'),
);
return $items;
}
function save_node_ajax_callback() {
$html = isset($_POST['body']) ? $_POST['body'] : null;
$nid = isset($_POST['nid']) ? $_POST['nid'] : null;
$node = node_load($nid);
$node->body['und'][0]['value'] = $html;
node_save($node);
//ajax_deliver($html);
drupal_exit();
}
As you can see I put the html in the body of the node and then saves it. My final problem is now that I don't want to replace the whole content in the body field. Just the ul and its list elements. Any suggestions would be much appreciated!
I have a page that I have edited after load and what I want to do is get the pages current HTML and pass that off to a PHP script.
I first passed document.documentElement.innerHTML but that ended up including a bunch of computed style garbage at the top which I did not want. After googling around I found I could use ajax to get a copy of the current file on the server and then replace the edited part afterwards.
I can get the copy of the file using this:
var url = window.location.pathname;
var filename = url.substring(url.lastIndexOf('/')+1);
$.ajax({
url: filename,
async: false, // asynchronous request? (synchronous requests are discouraged...)
cache: false, // with this, you can force the browser to not make cache of the retrieved data
dataType: "text", // jQuery will infer this, but you can set explicitly
success: function( data, textStatus, jqXHR ) {
origPage = data; // can be a global variable too...
// process the content...
}
});
Which works fine and gets me the html I expected and see when viewing the page in notepad.
The next step is what I cannot figure out. All I want to do is swap out the innerHTML of a div with an id of 'editor' with what the current value is, so I have tried this:
origPage.getElementById('editor').innerHTML = e.html;
But I get the error "TypeError: undefined is not a function". I must be doing something simple wrong I feel but I don't know the proper formatting to do this. I have tried the following variations:
alert($(origPage).getElementById('editor').innerHTML);
//Different attempt
var newHtml = $.parseHTML( origPage );
alert($(newHtml).getElementById('editor').innerHTML);
//Different attempt
alert($(origPage).html().getElementById('editor').innerHTML);
But I always get "TypeError: undefined is not a function" or "TypeError: Cannot read property 'getElementById' of undefined". How can I do this properly?
EDIT:
Complete page html below:
<!DOCTYPE html>
<html>
<body>
<div id="editor">
<h1>This is editable.</h1>
<p>Click me to start editing.</p>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript" src="snapeditor.js"></script>
<script type="text/javascript">
var editor = new SnapEditor.InPlace("editor", {onSave: function (e) {
var isSuccess = true;
//var origPage = e.html;
var origPage;
var url = window.location.pathname;
var filename = url.substring(url.lastIndexOf('/')+1);
// Actually perform the save and update isSuccess.
// Javascript:
$.ajax({
url: filename,
async: false, // asynchronous request? (synchronous requests are discouraged...)
cache: false, // with this, you can force the browser to not make cache of the retrieved data
dataType: "text", // jQuery will infer this, but you can set explicitly
success: function( data, textStatus, jqXHR ) {
origPage = data; // can be a global variable too...
// process the content...
}
});
//origPage shows expected html as this point
//alert($(origPage).getElementById('editor').innerHTML);
//alert($(origPage).html().getElementById('editor').innerHTML);
$(origPage).getElementById('editor').innerHTML = e.html;//fails here
alert(origPage);
//alert(newHtml.getElementById('editor').innerHTML);
$.ajax({
data: {html: origPage, docName: 'example1.html'},
url: 'savePage.php',
method: 'POST', // or GET
success: function(msg) {
alert(msg);
isSuccess = true;
}
});
return isSuccess || "Error";
},
onUnsavedChanges: function (e) {
if(confirm("Save changes?")) {
if(e.api.execAction("save")){
//location.reload();
}
} else {
e.api.execAction("discard");
}
}});
</script>
</body>
</html>
It seems that you get the user's changes in a variable - you called the var e.html. That is not a good variable name, BTW. If you can, change it to something like htmlEdited
Question: If you add the command alert(e.html); what do you get? Do you see the HTML after user edits?
If yes, then what you need to do is send that variable to a PHP file, which will receive the data and stick it into the database.
Code to send the data:
javascript/jQuery:
alert(e.html); //you should see the user-edited HTML
$.ajax({
type: 'post',
url: 'another_php_file.php',
data: 'userStuff=' + e.html, //var_name = var_contents
success: function(d){
window.location.href = ''; //redisplay this page
}
});
another_php_file.php:
<?php
$user_edits = $_POST['userStuff']; //note exact same name as data statement above
mysql_query("UPDATE `your_table_name` SET `your_col_name` = '$user_edits' ") or die(mysql_error());
echo 'All donarino';
The AJAX javascript code will send the var contents to a PHP file called another_php_file.php.
The data is received as $user_edits, and then inserted into your MySQL db
Finally, I presume that if you redisplay that page it will once again grab the contents of the #editor div from the database?
This is where you haven't provided enough information, and why I wanted to see all your code.
ARE you populating that div from the database? If not, then how do you expect the page to be updated after refreshing the page?
You would benefit from doing some tutorials at phpacademy.org or a thenewboston.com. Do these two (free) courses and you'll be an expert:
https://phpacademy.org/videos/php-and-mysql-with-mysqli
https://phpacademy.org/videos/oop-loginregister-system
If all you need to do is insert the contents of e.html to replace the #editor div, then try this:
$('#editor').html(e.html);
HOWEVER, you need an event to trigger that code. Are you able to do this?
alert(e.html);
If so, then put the first bit of code at that same spot. If not, we need more information about when your code receives that variable -- that is where you put the $('#editor').html(e.html); statement.
I'm making an web that is a single-page website interacting with the server through Ajax in CodeIgniter. The general coding is of the following type:
controller (user.php):
public function get_user_content() {
$id = $this->input->post('id');
$hits = $this->user_model->user_data($id);
$s = '';
foreach ($hits as $hit) {
$s .= $hit->name;
$s .= $hit->age;
}
echo $s;
}
model(user_model.php):
function user_data($id) {
//do sql operation
return $query->result();
}
view:
...
...
Click here for user details
...
...
javascript:
('.user-data').click(get_user_data);
....
....
function get_user_data(response) {
return $.ajax({
type: "POST",
url: "<?php echo base_url();?>index.php/user/get_user_content",
data: { id: this.id },
success: function(response) {
$("#somediv").append(response);
$(".someclass").click(another_function);
},
error: function(error) {
alert("Error");
}
});
}
So, looking at the above javascript, there are separate functions for all actions that send some data to the server and the particular html content is updated via Ajax.
I had the following questions (I'm just new to this stuff):
1. Is there any better way of doing ajax in javascript than my implementation.
2. I'm not using the concept of views in CodeIgniter. I just `echo` results through my controller functions that gets embedded in javascript. This is because I want dynamic update in my app. It is a single page and there is no concept of new-page/new-tab. Is there any better way?
I'm not aware of any open-source projects that might make it easier/more optimized.
For making code more simplified, readable & with great coding standard answer will be yes for both to improve your javascript code & way you are getting a response from the Ajax call.
Improve Javascript :
You might have one common js included in you header portion, if not create & include one. This common jar contains only common functions throughout the application. Create one function with the name may be like sendAjaxRequest() in that common.js. This function will have some parameters like divId (refresh div id), url(post url), options(array of options) & function will look like this:
function sendAjaxRequest(strDivId, strRequestUrl, options) {
options = options || {};
var defaultOptions = {url: strRequestUrl, type: 'POST', beforeSend: function(request,options){showLoadingImage(strDivId);}, success: function(html){$('#'+strDivId).html(html); removeLoadingImage(strDivId); }};
options = $.extend({},defaultOptions,options);
$.ajax(options);
}
Call this function from where ever required on application.
like
('.user-data').click( function() { sendAjaxRequest('somediv', url,{data: { id: this.id }}) });
Benefit : This method is very useful in the future when you want to keep google analytics on ajax call also or want to track your ajax calls. It is always good to have common functions.
Resposnse from ajax call: You can load views in Controller->function in case of ajax call also, nothing need to change or configure for this. Use of this way is always good practice to maintain standardness & readablity in the code.
Note : Here in this case you might worry about using a second action on load of your first Ajax call, for this standard way is to write second action on load of view of that particular Ajax call view (Write second click code in that particular view only) like
('.someclass').click( function() { sendAjaxRequest('someOtherDiv', otherUrl,{data: { id: this.id }}) });
In short at the end user divide & conquer rule (Divide an html page into blocks & create the huge page) to create good applications. Its really fantastic way, as I am using this way in my codings overall.
1- There is other ways to do ajax calls , being better or not is based on your needs, This post clears this point
2- your way is good, still you could use some enhancements to your functions to be a complete web-services same as handling errors - in case - and to return the output data as json allowing you to control it from your JavaScript function for a better handling & representation.
3- from what i understood you're getting data for single user each time ,in this case using $query->row() would be make your life easier extracting the data than using $query->result() , but in case you are getting multiple records you could loop it withing your JavaScript function.
here's another approach to your example with little enhancements that might be helpful :
controller (user.php):
public function get_user_content($id) {
$output -> hit = $this -> user_model -> user_data($id);
if (!$output -> hit) {
$output -> msg = "NORECORDS";
} else {
$output -> msg = "SUCCESS";
}
echo json_encode($output);
}
model(user_model.php):
function user_data($id) {
//do sql operation
return $query -> row();
}
JavaScript :
function get_user_data(response) {
$.get("<?php echo base_url();?>index.php/user/get_user_content/" + this.id, function(data) {
if (data.msg != 'SUCCESS') {
alert(data.msg);
return;
}
var hit = data.hit;
$("#somediv").append("Name: " + hit.name + "Age: " + hit.age);
$(".someclass").click(another_function);
}, "json");
}
First Answer:
The ajax request seems fine, you can add dataType option also to expect particular type of response,
As you are using post you can use jquery.post as an alternative
Example
$.post( "<?php echo base_url();?>index.php/user/get_user_content", function(data) {
alert( "success" );
}, 'html') // here specify the datatype
.fail(function() {
alert( "error" );
})
You can also use done callback instead of success
Second answer:
Controller
public function get_user_content() {
$id = $this->input->post('id');
$hits = $this->user_model->user_data($id);
$user_array = array();
foreach ($hits as $hit) {
$temp_array = array();
$temp_array = array('name' => $hit->name);
$temp_array = array('age' => $hit->age);
$user_array = array($temp_array);
}
$this->load->view('user', $user_array);
}
Modal
Remains the same
View (user.php)
example say user.php
<?php
echo "<div class='somediv'>";
if (sizeof($user_array)) {
for ($row = 0; $row < sizeof($user_array); $row++ ) {
echo "User Details: Name - " . $user_array[$row]['name'] . ", Age - " . $user_array[$row]['age'];
echo "<br/>";
}
} else {
Click here for user details
}
echo "</div>";
?>
Javascript
$('.user-data').on('click' function () { // better to use event delegation as content is loaded dynamically
get_user_data();
});
function get_user_data() {
$.post( "<?php echo base_url();?>index.php/user/get_user_content", function(data) {
alert( "success" );
$("#somediv").append(data);
$(".someclass").click(another_function);
}, 'html') // here specify the datatype
.fail(function() {
alert( "error" );
});
}
Reference
stackoverflow.com/questions/18471627/codeigniter-load-a-view-using-post-and-ajax