Preventing ajax-jquery loaded external file from caching in IE - ajax

I have this jquery script to call an external file. So far so good. The script is working fine, but as always IE makes what he wants. The external file that I load with this script (weather.php) is a file with real-time weather conditions data in it. Whit this script, I can refresh the div inside which is my weather.php file. And obviously I don't want IE to cache the data in this file. I want when someone click on button "REFRESH", the included page to be reloaded with the new data in it. In IE this doesn't happens because of the cache.
How can I change this script to not cache the div's content, or how can I say to my included file (weather.php) to do not cache it self?
This is the script:
function ajax_request() {
$('#column_weather').html('<img src="../images/home/ajax-loader.gif" width="16" height="11" style="vertical-align:middle;"/><b> Loading...</b>');
$('#column_weather').load("../includes/home/weather.php");
}
`
And that's how I call the script:
Refresh`

Put a random variable on your query String
$('#column_weather').load("../includes/home/weather.php?myRand=" + guid());
I would make random var return a guid
function s4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function() guid{
return s4()+s4()+"-"+s4()+"-"+s4()+"-"+s4()+"-"+s4()+s4()+s4();
}

Can't you just have proper caching instructions inside this weather.php file (to say not to cache it)

I would attach the current date and time as a GET parameter. Internet Explorer (and other browsers) view this information as critical to loading the page, just as any function returns a different value with different parameters. The trick is that you don't have to use the parameter. :)
$('#column_weather').load("../includes/home/weather.php?t=" + date());

Adding a random parameter to the end of the query URL will help, but try adding this to the beginning of weather.php:
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');
?>

Related

Laravel 5 flash message flashes again after navigating away and using back button

In my controller im trying to redirect back with a Flash message in laravel 5. This all works great. The problem is no matter how i set it up the flash message always re-appears if i navigate away and then come back by using the browsers 'back button'.
So i have a users list with a delete button next to each user. When i click the delete button it calls my controller method to destroy. I made a little conditional in there that redirects back with an error if i am trying to delete an owner. I tried the following different ways to redirect back but with all i wind up with the same problem that the message shows again after navigating away and coming back via the browsers 'back button'.
1
return Redirect::route('users')->with('error_message', 'Some error msg');
2
Session::flash('error_message', 'Some error msg');
return Redirect::to('users');
In my view i pick it up like this:
#if (Session::has('error_message'))
{{ Session::get('error_message') }}
#endif
So that works good, i get the message. But as soon as for example i click a user in my user list to go to the details page and press the browser 'back button', the message flashes again. I dont get why it keeps flashing that data, i was under the impression that it just flashes one time.
Even if i try to clear it right after displaying (like below), it doesnt matter, it will always re-appear?
{!! Session::forget('error_message') !!}
Step 1 : create one middleware using following command:
php artisan make:middleware PreventBackHistory
Step 2:
replace content of PreventBackHistory.php with following content:
namespace App\Http\Middleware;
use Closure;
class PreventBackHistory {
/* Handle an incoming request.
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
return $response->header('Cache-Control','no-cache, no-store, max-age=0, must-revalidate')
->header('Pragma','no-cache')
->header('Expires','Sun, 02 Jan 1990 00:00:00 GMT');
}
}
step 3: register middleware in kernal.php
'preventBackHistory' => \App\Http\Middleware\PreventBackHistory::class,
step 4: use middleware in your controller's construstor
public function __construct()
{
$this->middleware('preventBackHistory');
$this->middleware('auth');
}
And good to go :)
Generally, when the user clicks the back button in the browser, the browser tries to display the contents of the previous page without reloading it. So it's likely not Laravel flashing to the session again, but the browser trying to help you out by caching the page for you.
For those of you not concerned with back button:
#if (Session::has('error_message'))
{{ Session::get('error_message') }}
{{ Session::forget('error_message') }}
#endif
and if that doesnt make it clear out, try:
#if (Session::has('error_message'))
{{ Session::get('error_message') }}
{{ Session::forget('error_message') }}
{{ Session::save() }}
#endif
You can show flash messages using javascript and use SessionStorage to stop repeating messages. Browser cache doesn't know if browser already shown a message, but we can use SessionStorage to check it before display.
<div id="flash-container"></div>
...
var popupId = "{{ uniqid() }}";
if(sessionStorage) {
// prevent from showing if it exists in a storage (shown);
if(!sessionStorage.getItem('shown-' + popupId)) {
$('#flash-container').append("<div>{{ session('status') }}</div>");
}
sessionStorage.setItem('shown-' + popupId, '1');
}
I've just come across this problem and I think the only way to get around it is to AJAX load your flash messages into the page.
I've not tested this yet but I assume that when the user goes back and the AJAX request fires the previous flash messages will have already been cleared.
Well it seems it was indeed the browser cache and after adding the code to stop cache it was ok and the message disappeared. It still is weird to me that i had to add this code to the controller to stop it from caching:
header('Cache-Control: no-store, private, no-cache, must-revalidate'); header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false);
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Expires: 0', false);
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
header ('Pragma: no-cache');
Or this in the htaccess:
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</IfModule>
But that seemed a bit overkill to me ;)
Right now I am using Laravel8, And I got same problem.
But all solutions are outdated for latest version.
So, here is the solution for those people who are using Laravel8
#if(session('error'))
<div class="alert alert-danger mb-3">
{{ session('error') }}
{{ session()->forget('error') }}
</div>
#endif
session()->forget('error') will remove the session named error.
You can also remove multi session data or flash data.
like this - $request->session()->forget(['done', 'error', 'status']);

Clear the cache before the ajax call

hi everybody i have the following function for ajax call. I need to replace the image with the ajax call image. I need to clear my cache before i call the shownewimage function. Thankyou..
function drawImg(idx)
{
var imp = document.getElementsByName("img_pan");
fn = fnArr[parseInt(idx)];
path = 'designs/' + fn;
$("#img_pan").html('<img id="imgView" src="'+path+'"></img>');
$("#state_info").show();
var url="newimage.php?fn="+path+"&act='getcolors'";
httpRequest("GET", url, shownewimage); // i need to clear cache before the shownewimage function executes.
request.send("");
}
Thing is you can't clear browsers cache from javascript, so what you need to do is to make sure that responses from your server for this newimage.php never get cached.
try this for PHP:
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Expires: 0');
Alternatively you could always generate randomized Url like /newimage-12345677, you'd just need the server to map it to the actual php script.

JavaScript code in view issue in Laravel

I put JavaScript code in a view file name product/js.blade.php, and include it in another view like
{{ HTML::script('product.js') }}
I did it because I want to do something in JavaScript with Laravel function, for example
var $path = '{{ URL::action("CartController#postAjax") }}';
Actually everything is work, but browser throw a warning message, I want to ask how to fix it if possible.
Resource interpreted as Script but transferred with MIME type text/html
Firstly, putting your Javascript code in a Blade view is risky. Javascript might contain strings by accident that are also Blade syntax and you definitely don't want that to be interpreted.
Secondly, this is also the reason for the browser warning message you get:
Laravel thinks your Javascript is a normal webpage, because you've put it into a Blade view, and therefore it's sent with this header...
Content-Type: text/html
If you name your file product.js and instead of putting it in your view folder you drop it into your javascript asset folder, it will have the correct header:
Content-Type: application/javascript
.. and the warning message will be gone.
EDIT:
If you want to pass values to Javascript from Laravel, use this approach:
Insert this into your view:
<script type="text/javascript">
var myPath = '{{ URL::action("CartController#postAjax") }}';
</script>
And then use the variable in your external script.
Just make sure that CartController#postAjax returns the content type of javascript and you should be good to go. Something like this:
#CartController.php
protected function postAjax() {
....
$contents = a whole bunch of javascript code;
$response = Response::make($contents, '200');
$response->header('Content-Type', 'application/javascript');
....
}
I'm not sure if this is what you're asking for, but here is a way to map ajax requests to laravel controller methods pretty easily, without having to mix up your scripts, which is usually not the best way to do things.
I use these kinds of calls to load views via ajax into a dashboard app.The code looks something like this.
AJAX REQUEST (using jquery, but anything you use to send ajax will work)
$.ajax({
//send post ajax request to laravel
type:'post',
//no need for a full URL. Also note that /ajax/ can be /anything/.
url: '/ajax/get-contact-form',
//let's send some data over too.
data: ajaxdata,
//our laravel view is going to come in as html
dataType:'html'
}).done(function(data){
//clear out any html where the form is going to appear, then append the new view.
$('.dashboard-right').empty().append(data);
});
LARAVEL ROUTES.PHP
Route::post('/ajax/get-contact-form', 'YourController#method_you_want');
CONTROLLER
public function method_you_want(){
if (Request::ajax())
{
$data = Input::get('ajaxdata');
return View::make('forms.contact')->with('data', $data);
}
I hope this helps you... This controller method just calls a view, but you can use the same method to access any controller function you might need.
This method returns no errors, and is generally much less risky than putting JS in your views, which are really meant more for page layouts and not any heavy scripting / calculation.
public function getWebServices() {
$content = View::make("_javascript.webService", $data);
return (new Response($content, 200))->header('Content-Type', "text/javascript");
}
return the above in a method of your controller
and write your javascript code in your webService view inside _javascript folder.
Instead of loading get datas via ajax, I create js blade with that specific data and base64_encode it, then in my js code, I decode and use it.

Laravel: strange behavior when I try to serve ajax and non-ajax request on same route (Caching)

I registered a GET route for laravel.dev/test. The corresponding controller for the route would distinguish whether the request is ajax or not.
When I type laravel.dev/test on the browser, Laravel detect that it's not an ajax request and uses return View::make() to generate the page. Then Backbone.js code on the page make an ajax request to laravel.dev/test and Laravel uses return Response::json to return a JSON.
It's all fine until when I try to navigate away from the page and then use the browser button to navigate back to laravel.dev/test that it print out the json as the response, which is not what I expect since I'm not making an ajax request.
Definitely a caching issue. Just to try and get some results, add this to your controller (ajax and non-ajax) to force-disable caching:
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
And see if chrome still fetches from the cache on the back button.
This is not a laravel or backbone, but a chrome issue! Check this out too.
The solution that worked for me is to put
return Response::json($this->data)->header("Vary", "Accept");
Good luck!
This is in Laravel 5.1, but the principle should work for all previous versions as well.
The way I handled it was with two routes pointing to the same method, but with one ending in a .json extension:
get('items', ['as' => 'items', 'uses' => 'ItemsController#index']);
get('items.json', ['as' => 'items', 'uses' => 'ItemsController#index']);
Then inside my index() method:
$data = []; // your collection
if ($this->request->ajax()) {
return response()->json($data); // replace with actual JSON data
}
return view('items.index', compact('data'));
This allows for a dedicated URL for JSON responses, uses the same method and data, and never interferes with my back button.

Open PDF in a new tab using dompdf

Im trying to generate pdf using dompdf, how can I open the pdf in a new tab in a browser? Like, I Click A link for the PDF and it should open in a new tab, not save it automatically. I want to give the user a choice to save the file after seeing it first. how do i do that?
whenever i use $pdf->output at the end of the file, it does not change a thing, the file is still downloaded automatically.
please help. thanks.
Whether a PDF is downloaded or viewed in the browser depends on a couple of factors. One is your browser settings, but we have no control there. The second is how dompdf present the PDF to the browser. You can tell dompdf to offer the PDF for direct viewing using $dompdf->stream('my.pdf',array('Attachment'=>0));.
As far as opening in a new tab. That depends on how you are generating the PDF. But the simplest way it to provide a link with a target attribute.
I have a same problem into my site (http://www.pdfwebcreator.com)
My solution is:
$myfile = fopen($strFileName, "r") or die("Unable to open file!");
$fileSize = filesize($strFileName);
header("HTTP/1.1 200 OK");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=\"temporaryPdf.pdf\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $fileSize);
echo fread($myfile, $fileSize);
}
I don't know if you got, but if you use false in this line:
$dompdf-> stream("pasta/doc/relatorio.pdf", array("Attachment" => false));
You can see the pdf in the browser.
Well that you can do with the ->stream(); at the end of the chain.
Example:
//Routes (web.php in case laravel version >= 5.4)
Route::get('/pdf', 'PdfController#pdfStream')->name('pdfStream');
//PdfController.php
public function pdfStream(Request $request) {
$data["info"] = "I is usefull!";
$pdf = PDF::loadView('whateveryourviewname', $data);
return $pdf->stream('whateveryourviewname.pdf');
}
//yourViewPage.blade.php
<a href="{{route("pdfStream")}}" target="_blank" > click me to pdf </a>
Here more information
Am still experimenting, but something like this works fine as well
$pdf->loadView('file/path', compact('values'));
return $pdf->stream();
With this you can add dynamic values to your pdf file page within the browser.

Resources