Background:
I'm trying to preload some images in an AngularJS app before presenting them to the user to prevent them from "peeling" in. I my preload facility to return a promise resolved when the image has been downloaded.
Current approach:
At the moment I'm using a simple $http call to download the image. Imagine element is an <img> tag with my image in it:
$http.get("my/image/url.jpg")
.then( function() {
$animate.enter(element);
});
This seems to work okay, but I would appreciate any pointers if there's a better way to do it.
Problem
I'm hitting issues with CORS I think. One application of this preloader is to load profile pictures from twitter. When I do this, my $http.get throws an error in the console:
XMLHttpRequest cannot load https://path/to/img.jpg.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://my.server.com' is therefore not allowed access.
Is there a way to preload this sort of image?
I've created a very simple plunkr demonstrating the problem - you'll need the console open to see the error.
Use one of the standard ways to preload images - img tag that's not shown on screen would still force image loads.
Combined with Angular, sounds like a preloader directive would work perfectly.
No need to reinvent the wheel, just make the most use of Angular.
Related
I have put ng-cloak on the body tag. I am loading a large JSON document from the server, and setting it to a variable in scope. The JSON document has image URLs which are used to loading some images.
However, I feel that the page does not become visible until the images are loaded instead of becoming visible after the JSON document is loaded. Is that how it works? Also, should I use lazy-loading to fix this? Could someone suggest something good for this?
i'm doing protractor tests and using angular-mocks to "fake" requests.
In my app where is one place where image should be displayed:
<img ng-src="api/documents/image/{{file.Id}}">
Is it possible to intrcept the request for getting image data and replace it by some fake image data, in the way things done with json?
$httpBackend.whenGET('api/documents/123').respond(200,[]);
Currently i'm getting broken image icons on the screen, which i prefer to be replaced by some fake images.
I hope that it is possible...
Kind regards
ngSrc just accepts an expression/static path - it doesn't perform an $http call which you can mock unless your expression is a function call to fetch images which is probably not what you want. I would recommend:
1) Add a config variable to your image paths that can be switched for dev/prod such as:
ng-src="{{ baseUrl }}/api/documents/image/{{file.Id}}"
2) Point this baseUrl to a dev server which delivers whatever mock images you desire. You can create a simple Express server that delivers the same image for every request for example.
How can I prevent route loading when I hit refresh or when I load the page for the first time?
My backend respond with a chunk of HTML when ajax request and the whole page when normal request. If a normal request was made, I don't want angular to made the same request all over again to retrieve the same page but with a chunk of html instead of the whole page when the page loads.
How can I configure this?
May be you can't do that.
If you don't want the page to blink when angular load the whole page again, you can use the resolve attribute in angular-route or angular-ui-router.
You know, if angular don't load the page again, it can't handle user click or something else.
I have wrote a blog about this, researching the same problem with you, but in chinese. In the last, I decide to use resolve.
My blog url is http://isay.me/2014/06/angular-prerender-seo-and-use-resolve-for-page-flicker.html
Maybe you can have a look or not :)
I'm trying to maintain a website that was built with the jquery lightbox plugin. When a user loads one of the pages which uses lightbox, the server logs indicate that lightbox is making a second http request. The sequence of events in the logs looks like this:
The user requests example.com/subfolder/data/myPage.jsp
When lightbox loads, it initiates a http request to example.com/subfolder/data
Since there isn't anything meaningful in example.com/subfolder/data (it's just the parent folder for the jsp), it just throws some errors in the log about page not found. These errors are filling up lots of errors on the server and my goal is to make lightbox stop initiating these requests.
Does anyone have any suggestions about what lightbox config I might have misconfigured to cause these http requests? When I look at the jsp page, the only things that I see is the line which loads the lightbox javascript library and an attribute data-lightbox="image-1" on one of the html tags.
Is it possible to get ng-include directive to work with a CDN?
In this case:
<div ng-include='http://cdn.somewebsite.com/templates/home.tpl.html'></div>
The cdn sub-domain of somewebsite.com is mapped through DNS/CName to a content delivery network.
However when loading the main site somewebsite.com, it does not render the template. I guess internally it is treating this as a cross-domain call.
Is there any work arounds to get Angular templates be hosted on third party CDN's and work with the local domain?
Yes, you are right - the problem is with cross-domain call.
Official docs say:
By default, the template URL is restricted to the same domain and protocol as the application document. This is done by calling $sce.getTrustedResourceUrl on it. To load templates from other domains or protocols you may either whitelist them or wrap them as trusted values. Refer to Angular's Strict Contextual Escaping.
and
Please note: The browser's Same Origin Policy and Cross-Origin Resource Sharing (CORS) policy apply in addition to this and may further restrict whether the template is successfully loaded. This means that without the right CORS policy, loading templates from a different domain won't work on all browsers.
Example:
angular.module('myApp', []).config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
// Allow same origin resource loads.
'self',
// Allow loading from outer templates domain.
'http://cdn.somewebsite.com/templates/**'
]);
});
Helpful links:
ngInclude
$sce
So your problem may be solved by appropriate angular settings, but not for all browsers.
Perhaps you can alter this code a bit. I have my client's intranet in a datatbase and that's connected to a remote API server. I use an angular app to pull the HTML, but it is part of a JSON object, so obviously that's pretty specicific to my own needs.
I happen to have full control over the CORS attributes of my server, so I can do this. If you try it google or some other site... you're stuck with an iframe. (I have not idea what that's allowed by JS is so strict!)
So, here's what I do to get my remote HTML data.
1:
In my controller I add this:
<div ng-bind-html="content"></div>
then in the code, I add this
$http.get(url)
.then(function (data) {
$scope.content = $sce.trustAsHtml(data.data.PageData);
});
That's it. Just don't forget that the site in the URL has to be allowing you to get the data via your remote system.
NOW: Just for fun, I used to use IFRAMEs to bring data from other sites before CORS was even invented. It was a big hack. Before AJAX, I'd make a tiny form on one page with all the form values empty. On another page, I'd have an iframe for it and just fill those input boxes with javascript and post them back with javascript, keeping the main page without a reload.
If you need more control of your data, you could simply have a hidden iframe, rip the HTML you want from it, put it in a variable and drop it whereever you want on your page.
There's always some half-a$$ed way to get things done. :)