javascript: parsing JSON to create new classes with background-image preloaded - javascript

I am developing a browser game using MVC4 and have been able to deploy to my website for the first time tonight. I'm sloshing through the differences between running the site off of localhost and running it from the website.
Right now the first thing I do is load all of the static content on the page--navigation bars, icons, the world map, and some basic javascript to interact with it. Then, I call four AJAX functions that return information about various elements on my 2d map, such as cities and their x,y coordinate, name, and a small flag icon.
Upon completing the AJAX function I begin to parse the JSON returned. For each item in the JSON, I add a new 20x20 pixel class using code like this:
function loadSuccessCityTiles(data) {
var cityTiles = jQuery.parseJSON(data);
var cityTileCount = cityTiles.length;
$(".CityTile").remove();
for (var i = 0; i < cityTiles.length; i++) {
var imgName = "../Images/City_Tiles/Small/" + cityTiles[i].Type + "";
$("#scrollWindow").append("<div class = 'CityTile' style = 'left: " + Math.floor(cityTiles[i].X)*tileSize + "px; top: " + Math.floor(cityTiles[i].Y)*tileSize + "px; background-image: url(" + imgName + ");'></div>") ;
}
}
As you can see, I append a new class using that has its background-image set to the appropriate image url (that is what Type means). This works great on localhost, but when I run it on the website I discover that the images don't load.
I'm not quite sure how to proceed here. I have a lot of small image elements (each in separate files) and there is no guarantee that all will be used, so it is wasteful to load them all. What would be a good solution in this case? One thought I have had is to return JSON data on which image files will be used and then preload those images via javascript all before creating the classes that will use them.
Why does this happen on the server but not localhost? Clearing my cache before reloading on localhost does not recreate this problem. Is it because there is no need for a download as all the files are already on your hard drive?
Does anyone have a suggestion on a better way to do this all together?

A better option could be to use a single image sprite as a background image for each tile. Use the Type as a class name, and set the background x,y positioning in CSS. The single image will have a large file size, but it will be a single request that could easily be cached.
As for it not working, what errors are you getting? What do you see in the network tab in Chrome dev tools for the image request?

Related

How to update a PSD file linked layer with opened image

I am a bit stuck. I have created a script for Photoshop that opens a PSD file containing a few layers plus a linked one, sort of a template.
So far, I got things working for me by creating a droplet that runs the following steps and scripts:
Opening the file/image that is dropped.
Opening the PSD file (opening template, scripted).
Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action).
Applying the template features to this linked layer which has been updated previously (scripted).
Saves a PNG file (scripted),
And finally, closing up opened image and template documents (recorded action).
All is good so far. But this has a limitation. It will only work on one file at a time, with a specific name, at a specific location. So, for example, for the update linked layer to work, the name of the image must be 1.png inside Downloads folder only, in this case.
So my question is: How can I script this to run an iteration of the update on the linked layer using as source(s) the images dropped onto the droplet, regardless of file types (png, jpg, etc.), name, location, and index the output saved PNG file(s)? (1.png, 2.png, 3.png, and so on.)
I started working on my approach, and the steps previously mentioned:
1 - Opening the file/image that is dropped onto the Photoshop droplet.
This would happen automatically with the file—Photoshop will open the file dropped onto the droplet, thus triggering the specific actions sequence set forth. Step one solved. Next!
2 - Opening the PSD file (opening template, scripted)
With this step, I wrote a script that opens the template file. The first step in the action sequence would be this!
var template = new File("/Users/name/Desktop/Folder/Template.psd"); // Of course, you can have your template file anywhere on your computer as long as the path to find it is correct. I have selected my desktop for testing purposes.
app.open(template);
That was another effortless one. Next!
3 - Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action)
I needed to ensure that the template would easily find its previously linked layer location for the update for this third step to work. I know there are ways to update this with a script, but I didn't want to tinker with that. It was too much of a hassle for me at this stage and with my limited knowledge. Therefore I've decided to accommodate the necessary so the template would find a familiar file name it would look for when the "Update all Modified Content" action is triggered.
At this stage, there are two files opened in Photoshop, one the initial image that serves as a new source for the template, and the second file the template.psd, which contains the linked layer that needs to be updated with the content of the first file.
First, I have saved a copy of the image using the name that the template would look for when searching for the linked layer's name. Next, I have saved a copy of the template using the location of the first image file to keep the initial template safe from all these actions. And third, I triggered the "Update all Modified Content" action. And voila, everything worked. The initial template had the linked file next to it. So the new template copy would search and find the file next to it, in the same place, folder/location, as it happened on the previews step that helped save it as such.
// The following script will retrieve the path of the opened image and will save a copy that matches the name of the linked layer in the template in the same location.
var image_doc = app.documents[0]; //If two or more documents are opened, this approach will help switch between them.
var image_name = image_doc.name;
var image_path = app.documents[0].path.fsName;
var temp_image = new File("" + image_path + "/" + image_name + "");
var opts, file;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
var image_temp_name = "link.png";
pngFile = new File("" + image_path + "/" + image_temp_name + "");
image_doc.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);
// Save a copy of the template.psd in the same location as the image and the link.png file needed to update the linked layer.
var temp_template = new File("" + image_path + "/" + image_name + "");
app.open(template);
var opts, file;
opts = new PhotoshopSaveOptions();
opts.format = SaveDocumentType.PHOTOSHOP;
var template_temp_name = "template.psd";
psdFile = new File(image_path + "/" + template_temp_name);
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
activeDocument.saveAs(psdFile, psdSaveOptions, false, Extension.LOWERCASE);
// After these Update all Modified Content action
Now, four, five, and six are straightforward:
4 - Applying the template features to this linked layer which has just been updated previously (scripted). Done!
5 - Saves the newly formed template as a PNG file (scripted). Done!
6 - And finally, closing up opened image and template documents (recorded action). Done!

How to cache an image array?

I'm trying to make an Image sequence scrolling website, something like Apple Airpod Pro.
I'm facing an issue with images loading, each image will load once it displays only.
It appears that I have to preload all images on dom to cache it out so it'll look smooth when scrolling.
So I'm looking for a better way to cache my images
Here is my image array :
const MAX = 4875; //last image number
const PREFIX = "images/image-scroll/Test_"; //image location
const EXT = ".jpg"; //image format
var images = [];
for (let i = 0; i <= MAX; i += 1) {
images.push(
PREFIX + ("00000" + i).slice(-5) + EXT
);
}
Currently, I'm preloading images this way:
//Preload Images
jQuery('document').ready(function(){
jQuery.each(images, function() {
jQuery('<img />').attr('src', this).appendTo('body').hide();
});
});
This method works, but it makes the site heavy and it'll keep creating img elements every time you update the page.
Is it possible if I can just load all images to cache it without adding elements to the code?
One possible solution is to call GET requests to the image URLS directly instead of waiting for browser to call it from the DOM element. This way the DOM is not modified and the images may be cached in the browser.
The network and caching layers should work similarly to how it would if you had added it to DOM.
//Preload Images
jQuery('document').ready(function(){
jQuery.each(images, function() {
fetch(this); // uses the fetch API to do a get request. You may use the jQuery AJAX if required.
});
});

How to capture broken image urls with javascript then pass the urls to php?

I have a site that displays a lot of external images and thumbnails etc, easily up to 100 on a single page. I crawl and index the urls to the images and save them in mysql and display them with this code inside simple loops from queries.
<img src="<?php echo $row['img_url']; ?>" onerror="this.onerror=null;this.src='http://example.com/image.jpg';" width="150" height="150">
I use that particular code to replace any broken image urls with a default image.
My question is, is it possible to use javascripts onerror or something else to capture the image url that is broken when a broken url is found so that I can pass the url back to php and be able to automatically delete the urls from my database?
I am not very good with javascript and after searching I can't seem to find anything similar to what I am looking for, I mostly just find lots of posts on how to replace the broken image.
I am open to any ideas really, the original image urls come from $row['img_url'] as you can see in the code but I know I need javascript or something to catch the errors and then somehow get the urls passed back to php so that I can automate the deletion process instead of just replacing images with default images like my currnt code.
you can use file_exists to check like so:
if(file_exists($row['img_url'])){
echo '<img src="'.$row['img_url'].'" onerror="this.onerror=null;this.src="http://example.com/image.jpg";" width="150" height="150">';
}
You are almost there. Simply replace this:
this.src='http://example.com/image.jpg'
with:
this.src='http://example.com/image-missing.php?url={$row['primaryKey']}&w=150&h=150'
Now, "image-missing.php" receives the URL of the missing file and the intended size of the missing image. What it needs to do is clean the database (after checking that the call is legitimate (1) and that the referred row exists(2)), and output a replacement image in the proper size.
(1) otherwise you have just handed the possibility of deleting your whole image database to the first guy with time on his hands.
(2) someone else might have loaded the same page, and called the same script one millisecond ago.
You should try something like this (example uses vanilla JS, no jquery or any 3rd party library):
var allImages = document.querySelectorAll('img');
for (var i = 0; i < deleteLink.length; i++) {
document.querySelector('img').addEventListener('error', function(e) {
// Delete a user
var url = "<DELETION_URL>";
var xhr = new XMLHttpRequest();
xhr.open("DELETE", url+'?resource=' + e.target.src, true);
});
}
<DELETION-URL> should point to a PHP script that accepts DELETE (or at least POST) requests and read the resource parameter. It will then remove the image provided that resource is truly missing.

Getting image dimensions with Angular vs Node.js

I am confused about the best way to discover the image dimensions, or the naturalWidth of images, given the url to the image, most often found in the src attribute of an <img> tag.
My goal is take as input a url to a news article and use machine learning to find the top 5 biggest pictures (.jpg, .png, etc) files in the document. The problem with using the front-end to do this, is that I don't know of a way to use AJAX to http GET html from some random page of some random server, because of CORS related issues.
However, using Node.js, or some server technology, I can make requests to get the HTML from other servers (as one would expect) but I don't know a way of getting the image sizes without downloading the images first. The problem is that, I want the downloaded images on the front-end, not the back-end, and therefore downloading images with Node.js is wasted effort, if it's just to check the image dimensions.
Has anyone experienced this exact problem before? Not sure how to proceed. As I said, my goals are to download images on the front-end, and keep the ones that are bigger than say 300px in width.
Both ways are ok, depends greatly on exactly what you need to achieve in terms of performance:
To me seems that, the simplest way for you would be on client side, then you only need a few lines of JavaScript to do it:
var img = new Image();
img.onload = function() {
console.log(this.width + 'x' + this.height);
}
img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
On server side is also possible but you will need to install GraphicsMagick or ImageMagick. I'd go with GraphicsMagick as it is faster.
Once you have installed both the program and it's module (npm install gm) you would do something like this to get the width and height.
gm = require('gm');
// obtain the size of an image
gm('test.jpg')
.size(function (err, size) {
if (!err) {
console.log(size.width + 'x' + size.height);
}
});
Also, this other module looks good, I haven't used it but it looks promsing https://github.com/netroy/image-size
To get the img urls from the html string
You can load your html string using a simple http request, then you need to use a regexp capture group to extract the urls, and if you're wanting to match globally g, i.e. more than once, when using capture groups, you need to use exec in a loop (match ignores capture groups when matching globally).
This way you'll have all the sources in an array.
For example:
var m;
var urls = [];
var rex = /<img[^>]+src="?([^"\s]+)"?\s*\/>/g;
// this is you html string
var str = '<img src="http://example.com/one.jpg />\n <img src="http://example.com/two.jpg />';
while ( m = rex.exec( str ) ) {
urls.push( m[1] );
}
console.log( urls );
// [ "http://example.com/one.jpg", "http://example.com/two.jpg" ]
Hope it helps.

HTML syntax unknown to display a javascript binary string containing a jpeg image

I can't get through this problem though it must be only a very small syntax problem, as you will see: In fact, I'm searching for just a little piece of syntax, unless what I intend to do would be impossible (But I can see no reason why it should be impossible...).
I have written a function to encode an image into Base64 on server side, because I want to store numerous images into an array:
So, with Base64 I can download images as ordinary strings that I can organize in an array, then put them into an object just when I have chosen the right image and the right moment, without having to refer to the server again, so that the user doesn't have to wait.
Then I do something like this:
First phase:
function download64(imageUrl) //->string
{ // ask the server to send the 'imageUrl' as a base64 string
var tx = DoTheJob(); // ...connect through ajax and download the image converted in base64 as a string in var 'tx'
return tx
}
At this stage, I'm holding the image in the 'tx' Base64-string on client side.
Somewhat later I want to display my image in the div called "cadre", so I do the following:
Second phase:
I just have to call the "display64" function to set my image into the "cadre" div-object on the screen:
display64("cadre",tx);
using this function:
function display64(destinationDiv,imgText64) //->void
{ // display 'imgText64' into destinationDiv
var oImg = "<img alt='' src='data:image/jpg;base64," + imgText64 + "'>";
var x = document.getElementById(destinationDiv);
x.innerHTML = oImg;
}
Now the image is displayed. Unfortunately, this works well only with Firefox, because Internet Explorer 8 can't read Base64 images above 32Kb! And in my entreprise, we use IE 8 only!
Then I dropped my base64 encoder and decided to fetch the image as a binary string, which I could manage though I initially had a problem with nul character.
Now, I'm here with my binary string containing the exact copy of the source JPG file (including zeros that I have encoded on server side then restored on client side). So, what I need now is the simple function 'displayBin', but I can't find the syntax on the web:
function displayBin(destinationDiv,imgTextBin) //->void
{ // display 'imgTextBin' into destinationDiv
var oImg = "<img alt='' src='??????? + imgTextBin + "'>"; // What's the syntax here, please?
var x = document.getElementById(destinationDiv);
x.innerHTML = oImg;
}
Can anyone help ? Thanks a lot.
If I understand your question your are wanting to store images so you do not have to connect back with the server. One way of doing this is to preload the images like var img=new Image; img.src='path'; You could load all of the images into an array and you could then add them to the page as necessary. There is a lot out there on image preloading since that seems what your trying to accomplish.

Categories