In HTML, how do I select all images from a folder to be shown in img src [duplicate] - html

I have a folder named "images" in the same directory as my .js file. I want to load all the images from "images" folder into my html page using Jquery/Javascript.
Since, names of images are not some successive integers, how am I supposed to load these images?

Works both localhost and on live server without issues, and allows you to extend the delimited list of allowed file-extensions:
var folder = "images/";
$.ajax({
url : folder,
success: function (data) {
$(data).find("a").attr("href", function (i, val) {
if( val.match(/\.(jpe?g|png|gif)$/) ) {
$("body").append( "<img src='"+ folder + val +"'>" );
}
});
}
});
NOTICE
Apache server has Option Indexes turned on by default - if you use another server like i.e. Express for Node you could use this NPM package for the above to work: https://github.com/expressjs/serve-index
If the files you want to get listed are in /images than inside your server.js you could add something like:
const express = require('express');
const app = express();
const path = require('path');
// Allow assets directory listings
const serveIndex = require('serve-index');
app.use('/images', serveIndex(path.join(__dirname, '/images')));

Use :
var dir = "Src/themes/base/images/";
var fileextension = ".png";
$.ajax({
//This will retrieve the contents of the folder if the folder is configured as 'browsable'
url: dir,
success: function (data) {
//List all .png file names in the page
$(data).find("a:contains(" + fileextension + ")").each(function () {
var filename = this.href.replace(window.location.host, "").replace("http://", "");
$("body").append("<img src='" + dir + filename + "'>");
});
}
});
If you have other extensions, you can make it an array and then go through that one by one using in_array().
P.s : The above source code is not tested.

This is the way to add more file extentions, in the example given by Roy M J in the top of this page.
var fileextension = [".png", ".jpg"];
$(data).find("a:contains(" + (fileextension[0]) + "), a:contains(" + (fileextension[1]) + ")").each(function () { // here comes the rest of the function made by Roy M J
In this example I have added more contains.

If interested in doing this without jQuery - here's a pure JS variant (from here) of the answer currently most upvoted:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/img", true);
xhr.responseType = 'document';
xhr.onload = () => {
if (xhr.status === 200) {
var elements = xhr.response.getElementsByTagName("a");
for (x of elements) {
if ( x.href.match(/\.(jpe?g|png|gif)$/) ) {
let img = document.createElement("img");
img.src = x.href;
document.body.appendChild(img);
}
};
}
else {
alert('Request failed. Returned status of ' + xhr.status);
}
}
xhr.send()

Here is one way to do it. Involves doing a little PHP as well.
The PHP part:
$filenameArray = [];
$handle = opendir(dirname(realpath(__FILE__)).'/images/');
while($file = readdir($handle)){
if($file !== '.' && $file !== '..'){
array_push($filenameArray, "images/$file");
}
}
echo json_encode($filenameArray);
The jQuery part:
$.ajax({
url: "getImages.php",
dataType: "json",
success: function (data) {
$.each(data, function(i,filename) {
$('#imageDiv').prepend('<img src="'+ filename +'"><br>');
});
}
});
So basically you do a PHP file to return you the list of image filenames as JSON, grab that JSON using an ajax call, and prepend/append them to the html. You would probably want to filter the files u grab from the folder.
Had some help on the php part from 1

$(document).ready(function(){
var dir = "test/"; // folder location
var fileextension = ".jpg"; // image format
var i = "1";
$(function imageloop(){
$("<img />").attr('src', dir + i + fileextension ).appendTo(".testing");
if (i==13){
alert('loaded');
}
else{
i++;
imageloop();
};
});
});
For this script, I have named my image files in a folder as 1.jpg, 2.jpg, 3.jpg, ... to 13.jpg.
You can change directory and file names as you wish.

Based on the answer of Roko C. Buljan, I have created this method which gets images from a folder and its subfolders . This might need some error handling but works fine for a simple folder structure.
var findImages = function(){
var parentDir = "./Resource/materials/";
var fileCrowler = function(data){
var titlestr = $(data).filter('title').text();
// "Directory listing for /Resource/materials/xxx"
var thisDirectory = titlestr.slice(titlestr.indexOf('/'), titlestr.length)
//List all image file names in the page
$(data).find("a").attr("href", function (i, filename) {
if( filename.match(/\.(jpe?g|png|gif)$/) ) {
var fileNameWOExtension = filename.slice(0, filename.lastIndexOf('.'))
var img_html = "<img src='{0}' id='{1}' alt='{2}' width='75' height='75' hspace='2' vspace='2' onclick='onImageSelection(this);'>".format(thisDirectory + filename, fileNameWOExtension, fileNameWOExtension);
$("#image_pane").append(img_html);
}
else{
$.ajax({
url: thisDirectory + filename,
success: fileCrowler
});
}
});}
$.ajax({
url: parentDir,
success: fileCrowler
});
}

This is the code that works for me, what I want is to list the images directly on my page so that you just have to put the directory where you can find the images for example -> dir = "images /"
I do a substring var pathName = filename.substring (filename.lastIndexOf ('/') + 1);
with which I make sure to just bring the name of the files listed and at the end I link my URL to publish it in the body
$ ("body"). append ($ ("<img src =" + dir + pathName + "> </ img>"));
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script src="jquery-1.6.3.min.js"></script>
<script>
var dir = "imagenes/";
var fileextension = ".jpg";
$.ajax({
//This will retrieve the contents of the folder if the folder is configured as 'browsable'
url: dir,
success: function (data) {
//Lsit all png file names in the page
$(data).find("a:contains(" + fileextension + ")").each(function () {
var filename = this.href.replace(window.location.pathname, "").replace("http://", "");
var pathName = filename.substring(filename.lastIndexOf('/') + 1);
$("body").append($("<img src=" + dir + pathName + "></img>"));
console.log(dir+pathName);
});
}
});
</script>
</head>
<body>
<img src="1_1.jpg">
</body>
</html>

If, as in my case, you would like to load the images from a local folder on your own machine, then there is a simple way to do it with a very short Windows batch file. This uses the ability to send the output of any command to a file using > (to overwrite a file) and >> (to append to a file).
Potentially, you could output a list of filenames to a plain text file like this:
dir /B > filenames.txt
However, reading in a text file requires more faffing around, so I output a javascript file instead, which can then be loaded in your to create a global variable with all the filenames in it.
echo var g_FOLDER_CONTENTS = mlString(function() { /*! > folder_contents.js
dir /B images >> folder_contents.js
echo */}); >> folder_contents.js
The reason for the weird function with comment inside notation is to get around the limitation on multi-line strings in Javascript. The output of the dir command cannot be formatted to write a correct string, so I found a workaround here.
function mlString(f) {
return f.toString().
replace(/^[^\/]+\/\*!?/, '').
replace(/\*\/[^\/]+$/, '');
}
Add this in your main code before the generated javascript file is run, and then you will have a global variable called g_FOLDER_CONTENTS, which is a string containing the output from the dir command. This can then be tokenized and you'll have a list of filenames, with which you can do what you like.
var filenames = g_FOLDER_CONTENTS.match(/\S+/g);
Here's an example of it all put together: image_loader.zip
In the example, run.bat generates the Javascript file and opens index.html, so you needn't open index.html yourself.
NOTE: .bat is an executable type in Windows, so open them in a text editor before running if you are downloading from some random internet link like this one.
If you are running Linux or OSX, you can probably do something similar to the batch file and produce a correctly formatted javascript string without any of the mlString faff.

You can't do this automatically. Your JS can't see the files in the same directory as it.
Easiest is probably to give a list of those image names to your JavaScript.
Otherwise, you might be able to fetch a directory listing from the web server using JS and parse it to get the list of images.

In jQuery you can use Ajax to call a server-side script. The server-side script will find all the files in the folder and return them to your html file where you will need to process the returned information.

You can use the fs.readdir or fs.readdirSync methods to get the file names in the directory.
The difference between the two methods, is that the first one is asynchronous, so you have to provide a callback function that will be executed when the read process ends.
The second is synchronous, it will returns the file name array, but it will stop any further execution of your code until the read process ends.
After that you simply have to iterate through the names and using append function, add them to their appropriate locations. To check out how it works see HTML DOM and JS reference

Add the following script:
<script type="text/javascript">
function mlString(f) {
return f.toString().
replace(/^[^\/]+\/\*!?/, '');
replace(/\*\/[^\/]+$/, '');
}
function run_onload() {
console.log("Sample text for console");
var filenames = g_FOLDER_CONTENTS.match(/\S+/g);
var fragment = document.createDocumentFragment();
for (var i = 0; i < filenames.length; ++i) {
var extension = filenames[i].substring(filenames[i].length-3);
if (extension == "png" || extension == "jpg") {
var iDiv = document.createElement('div');
iDiv.id = 'images';
iDiv.className = 'item';
document.getElementById("image_div").appendChild(iDiv);
iDiv.appendChild(fragment);
var image = document.createElement("img");
image.className = "fancybox";
image.src = "images/" + filenames[i];
fragment.appendChild(image);
}
}
document.getElementById("images").appendChild(fragment);
}
</script>
then create a js file with the following:
var g_FOLDER_CONTENTS = mlString(function() { /*!
1.png
2.png
3.png
*/});

Using Chrome, searching for the images files in links (as proposed previously) didn't work as it is generating something like:
(...) i18nTemplate.process(document, loadTimeData);
</script>
<script>start("current directory...")</script>
<script>addRow("..","..",1,"170 B","10/2/15, 8:32:45 PM");</script>
<script>addRow("fotos-interessantes-11.jpg","fotos-interessantes-> 11.jpg",false,"","");</script>
Maybe the most reliable way is to do something like this:
var folder = "img/";
$.ajax({
url : folder,
success: function (data) {
var patt1 = /"([^"]*\.(jpe?g|png|gif))"/gi; // extract "*.jpeg" or "*.jpg" or "*.png" or "*.gif"
var result = data.match(patt1);
result = result.map(function(el) { return el.replace(/"/g, ""); }); // remove double quotes (") surrounding filename+extension // TODO: do this at regex!
var uniqueNames = []; // this array will help to remove duplicate images
$.each(result, function(i, el){
var el_url_encoded = encodeURIComponent(el); // avoid images with same name but converted to URL encoded
console.log("under analysis: " + el);
if($.inArray(el, uniqueNames) === -1 && $.inArray(el_url_encoded, uniqueNames) === -1){
console.log("adding " + el_url_encoded);
uniqueNames.push(el_url_encoded);
$("#slider").append( "<img src='" + el_url_encoded +"' alt=''>" ); // finaly add to HTML
} else{ console.log(el_url_encoded + " already in!"); }
});
},
error: function(xhr, textStatus, err) {
alert('Error: here we go...');
alert(textStatus);
alert(err);
alert("readyState: "+xhr.readyState+"\n xhrStatus: "+xhr.status);
alert("responseText: "+xhr.responseText);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Gulp task to replace all Root-Relative URLs with Document-Relative URLs

There are 4 distinct URL types;
Absolute http://www.example.com/images/icons.png
Document-Relative ../images/icons.png
Root-Relative /images/icons.png
Protocol-Relative //www.example.com/images/icons.png
I have a large static file site (html, css, js) which is built with Jigsaw. This framework takes PHP templates and compiles them into static HTML. I am also using Gulp tasks to compile assets (sass, js..etc).
Using Jigsaw's build process I can either have the site built with full Absolute paths/urls (http://example.com/path-to/page) or Root-Relative (/path-to/page).
This is great but now the client wants the site to use Document-Relative as they are now hosting the site in a subdirectory with a URL pointing to that subdirectory.
E.g. http://example.com would point to http://xx.server.com/hosted-files/directory
My issue is that Jigsaw doesn't allow for Document-Relative URLs. Is there a gulp/node script I can use to convert all references (image sources, links, css paths..etc)? Or is there another solution (e.g. using .htacccess)?
TLDR;
I need to replace any Absolute or Root-Relative references in multiple HTML files and directories with Document-Relative paths and URLs. Or is there another solution (e.g. using .htacccess)?
I have managed to solve my own issue with what I feel is a "hacky" fix.
I've basically created a custom gulp plugin replaces URLs/paths..etc with Document-Relative paths.
gulpfile.js - relative-urls task runs after all other tasks have completed.
const relative = require('./tasks/document-relative');
gulp.task('relative-urls', function() {
return gulp.src('build/**/*.html')
.pipe( relative({
directory: 'build',
url: 'http://localhost:8000',
}) )
.pipe( gulp.dest('build') );
});
./tasks/document-relative.js - plugin
'use strict';
const fs = require('fs');
const PluginError = require('plugin-error');
const through = require('through2');
const PLUGIN_NAME = 'document-relative';
let count = 0;
module.exports = function(options) {
// Remove slashes from beginning and end of string
const strip_slashes = (string) => {
return string ? string.replace(/^\/|\/$/g, '') : null;
}
// Users options object
options = options || {};
// Cleanup options
const base_dir = strip_slashes(options.directory);
const url = strip_slashes(options.url) + '/';
return through({
objectMode: true,
writable: true,
readable: true
},
function(file, enc, callback) {
count++;
// Check for null file
if (file.isNull()) {
return callback(null, file);
}
if (file.isStream()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Stream not supported!'));
return callback(null, file);
}
if (file.isBuffer()) {
// Get contents of this file
let html = file.contents.toString(enc);
// This files full path (/home/usr/project/build/page/example/index.html)
const path = file.path;
// Path task was run from (/home/usr/project/)
const cwd = file.cwd+( base_dir ? '/'+base_dir : '' );
// Project specific path (/page/example/index.html)
const relative = path.replace(cwd, '');
// Get array of directories ['page', 'example', 'index.html']
let paths = strip_slashes(relative).split('/');
// Remove last item ['page', 'example']
paths.pop();
// Add ../ for nth number of paths in array
let rel_path = paths.length === 0 ? '' : ('../'.repeat(paths.length));
// Replace dom attributes (e.g. href="/page/example")
html = html.replace( /(?:(?!="\/\/)="\/)/g, '="'+rel_path );
// Replace inline background (e.g. background: url('/image/something.jpg'))
html = html.replace( /url\(\'\//g, 'url(\''+rel_path );
html = html.replace( /url\('\//g, 'url(''+rel_path );
// If user defined URL, match and remove
if (url && url.length) {
html = html.replace( new RegExp(url, 'g'), rel_path );
}
// Overwrite file
fs.writeFileSync(file.path, html, {
encoding: enc,
flag:'w'
});
return callback();
}
});
};
This basically opens all .html files in my build folder, calculates how many paths deep each file is (/folder1/folder2/index.html) and replaces any instances of url (http://localhost:8000) with ../ repeated for the number of paths calculated.
Node has path.relative.
Read Levi Coles' own answer to understand where url and directory come from.
const path = require("path");
// create a regular expression from your url property.
const domain_expression = new RegExp(url);
// Once you have an offending 'href' you can do this.
// - Here 'href' is Absolute, but this same code would work
// with Root-Relative paths too.
const href = "http://localhost:8000/images/icons.png";
const file_index = href.lastIndexOf("/") + 1;
const file_component = href.substring(file_index);
const root_relative = href.replace(domain_expression, "");
const relative_href = path.relative(`${directory}/${root_relative}`, directory);
const _href = relative_href + file_component;
// _href = ../../icons.png

Reference Google Spreadsheet (CSV) in Jekyll Data

I am managing a website displaying a lot of tabular data (language stuff) and running on Jekyll. I really like to display content based on a CSV file stored in the _data folder of Jekyll.
I would like to be able to edit / add / remove content from this CSV directly on Google and then reference it to Jekyll (like a shortcut or something that sync the CSV content from Google to my static folder).
Which way would be the simplest to reference an external file (either in the _data folder or directly in my templace). I can find the CSV file with this kind of link but downloading it every time is a hassle (https://docs.google.com/spreadsheets/d//export?format=csv).
How can Jekyll understand data from external stored file (maybe in javascript ?).
Thank you.
Getting datas from google docs is becoming harder ;-(
I've tried with jquery.ajax but I met the CORS limitation.
Then I found tabletop and it works !
go to your google spreadsheet and File > Publish to the web > Start publishing
note the publish url
download tabletop script and save it to eg: js/tabletop.js
put a link at the bottom of your _includes/header.html eg
<script src="`{{ site.baseurl }}`/js/tabletop.js"></script>
in a data.html page put
---
title: csv to json
layout: page
---
<div id="csvDatas"></div>
you can now get your datas with a js/script.js file that you've also included at the very end of you _includes/footer.html
var csvParse = function() {
// put you document url here
var sharedDocUrl = 'https://docs.google.com/spreadsheets/d/1Rk9RMD6mcH-jPA321lFTKmZsHebIkeHx0tTU0TWQYE8/pubhtml'
// can also be only the ID
// var sharedDocUrl = '1Rk9RMD6mcH-jPA321lFTKmZsHebIkeHx0tTU0TWQYE8'
var targetDiv = 'csvDatas';
// holds datas at a closure level
// this then can be accessed by closure's functions
var dataObj;
function showInfo(data, tabletop) {
dataObj = data;
var table = generateTable();
var target = document.getElementById(targetDiv);
target.appendChild(table);
}
function generateTable(){
var table = document.createElement("table");
var head = generateTableHeader();
table.appendChild(head);
var body = generateTableBody();
table.appendChild(body);
return table;
}
function generateTableHeader(){
var d = dataObj[0];
var tHead = document.createElement("thead");
var colHeader = [];
$.each(d, function( index, value){
console.log(index + ' : ' + value);
colHeader.push(index);
});
var row = generateRow(colHeader, 'th');
tHead.appendChild(row);
return tHead;
}
// this can be factorized with generateTableHeader
function generateTableBody(){
var tBody = document.createElement("tbody");
$.each(dataObj, function( index, value ){
var rowVals = [];
$.each(value, function(colnum, colval){
rowVals.push(colval);
});
var row = generateRow(rowVals);
tBody.appendChild(row);
});
return tBody;
}
function generateRow(headersArray, cellTag){
cellTag = typeof cellTag !== 'undefined' ? cellTag : 'td';
var row = document.createElement("tr");
$.each(headersArray, function( index, value){
if( value != "rowNumber"){
var cell = document.createElement(cellTag);
var cellText = document.createTextNode(value);
cell.appendChild(cellText);
row.appendChild(cell);
}
});
return row;
}
return {
init: function() {
if( $('#' + targetDiv).length ){
Tabletop.init( { key: sharedDocUrl ,
callback: showInfo,
simpleSheet: true } );
}else{
console.log('Not the good page to parse csv datas');
}
}
};
}();
$( document ).ready(function() {
csvParse.init();
});

Set File path using javascript

How can i set a default file path in HTML using javascript? If it is possible , if not please advice me another thing to make it.
Everytime i will export the CSV file it will save and replace the old CSV file in the same path were i can get my old CSV file. Thank you in advance for the help. I have no idea how can i do it. By the way i am using codeigniter here.
i tried this code but it didn't work
$(document).ready(function () {
function exportTableToCSV($table, filename) {
var $rows = $table.find('tr:has(td)'),
tmpColDelim = String.fromCharCode(11),
tmpRowDelim = String.fromCharCode(0),
colDelim = '","',
rowDelim = '"\r\n"',
csv = '"' + $rows.map(function (i, row) {
var $row = $(row),
$cols = $row.find('td');
return $cols.map(function (j, col) {
var $col = $(col),
text = $col.text();
return text.replace('"', '""');
}).get().join(tmpColDelim);
}).get().join(tmpRowDelim)
.split(tmpRowDelim).join(rowDelim)
.split(tmpColDelim).join(colDelim) + '"',
csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);
$(this)
.attr({
'download': filename,
'href': csvData,
'target': 'C:\xampp\htdocs\Datacast\bin\pdw_table.csv'
});
}
$(".export").on('click', function (event) {
});
});
it cause me error at the target
How can i set a default file path in HTML using javascript?
You can't.
If it is possible , if not please advice me another thing to make it.
Write a stand-alone application that isn't subject to the browser sandbox and use it instead of a web browser.

File field - Append file list

I have made me a simple file field:
<input type="file" name="pictures_array[]" multiple accept="image/*" id="page_pictures_array" />
and some HTML5 File API code to list the files:
$('.page-form #page_pictures_array').change(function(evt) {
var file, files, reader, _i, _len;
files = evt.target.files;
console.log(files);
$('#file-list').empty();
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
reader = new window.FileReader;
reader.onload = (function(file) {
return function(e) {
var src;
src = e.target.result;
return $("<li>" + file.name + " - " + file.size + " bytes</li>").prepend($('<img/>', {
src: src,
"class": 'thumb'
})).appendTo($('#file-list'));
};
})(file);
reader.readAsDataURL(file);
}
});
(cf. here)
However, since I expect my users to be very stupid indeed, I am sure they will choose one file, then click on the upload field another time to choose the next. However, the list of the <input type="file"> is reset each time with the newly chosen images.
How can I make sure the new files are appended to the <input>'s array so I don't get flooded with angry user comments?
I'm also looking for an answer to this, I think others already do that.
But if you look at the filelist W3 reference http://www.w3.org/TR/FileAPI/#dfn-filelist it says that its readonly....
Edit: It's a big code now, with some improvements, that make the copy/paste difficult. But I started to create one variable that saves all the tmp files.
var tmp_files = new Array();
Then when I add a new file I push the file to that array like this
tmp_files.push(file);
After all the insertions/removals (I have another var to save the deletions) when the user clicks to send the files I have this code that makes the formdata with the files I want
var data = new FormData(); var count = 0;
$.each(tmp_files, function(i, file){
if(del_files.indexOf(file.name)== -1){
data.append(count, file);
count++;
}
});
Then I just send the var data thru ajax and save them.
You can get them using $data = $_FILES;
Hope this helps you.

Filename of downloaded file in data:Application/octet-stream;

I am trying to download a file using data uri in following manner:
<input type="button"
onclick="window.location.href='data:Application/octet-stream;content-disposition:attachment;filename=file.txt,${details}'"
value="Download"/>
The problem is that the downloaded file is always named 'Unknown', whatever I try to use as
filename. Is this the correct way to give the file a name ? or something else needs to be
done ?
Here's the solution, you just have to add a download attribute to anchor tag
a with desired name
<a href="data:application/csv;charset=utf-8,Col1%2CCol2%2CCol3%0AVal1%2CVal2%2CVal3%0AVal11%2CVal22%2CVal33%0AVal111%2CVal222%2CVal333"
download="somedata.csv">Example</a>
Another solution is to use JQuery/Javascript
Anchor's Download Property
On Safari, you might want to use this, and instruct the user to ⌘-S the file:
window.open('data:text/csv;base64,' + encodeURI($window.btoa(content)));
Otherwise, this uses Filesaver.js, but works ok:
var downloadFile = function downloadFile(content, filename) {
var supportsDownloadAttribute = 'download' in document.createElement('a');
if(supportsDownloadAttribute) {
var link = angular.element('<a/>');
link.attr({
href: 'data:attachment/csv;base64,' + encodeURI($window.btoa(content)),
target: '_blank',
download: filename
})[0].click();
$timeout(function() {
link.remove();
}, 50);
} else if(typeof safari !== 'undefined') {
window.open('data:attachment/csv;charset=utf-8,' + encodeURI(content));
} else {
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
saveAs(blob, filename);
}
}
Note: There is some AngularJS in the code above, but it should be easy to factor out...
I had the same issue and finally I solved in all browsers serving the CSV file in the server-side:
const result = json2csv({ data });
res.writeHead(200
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment;filename=issues.csv',
'Content-Length': result.length
});
res.end(result);
For those that are using other libraries like angularjs or backbone, you can try something like this.
$('a.download').attr('href', 'data:application/csv;charset=utf-8,'+$scope.data);
For anybody looking for a client-side solution using Javascript only, here is mine, working on any browser except IE 10 and lower (and Edge...why?!):
var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(csv);
var link = document.createElement('a');
link.setAttribute("download", "extract.csv");
link.setAttribute("href", uri);
document.body.appendChild(link);
link.click();
body.removeChild(body.lastChild);