HTML FileReader - html

function fileSelected() {
// get selected file element
var files = document.getElementById('files[]').files;
for (var i = 0; i < files.length; i++) //for multiple files
{
(function (file) {
var fileObj = {
Size: bytesToSize(file.size),
Type: file.type,
Name: file.name,
Data: null
};
var reader = new window.FileReader();
reader.onload = function (e) {
fileObj.Data = e.target.result;
};
// read selected file as DataURL
reader.readAsDataURL(file);
//Create Item
CreateFileUploadItem(fileObj);
})(files[i]);
}
}
function CreateFileUploadItem (item) {
console.log(item);
$('<li>', {
"class": item.Type,
"data-file": item.Data,
"html": item.Name + ' ' + item.Size
}).appendTo($('#filesForUpload'));
}
So when console.log(item) gets run in the CreateFileUploadItem function it shows the item.Data. YET it won't add it to the data-file of the LI. Why is that?

The call to readAsDataURL is asynchronous. Thus, the function call is likely returning prior to the onload function being called. So, the value of fileObj.Data is still null when you are attempting to use it in CreateFileUploadItem.
To fix it, you should move the call to CreateFileUploadItem into your onload function. As for the console logging the proper value, you can't rely on that being synchronous either. I think using a breakpoint during debugging at that line instead will likely show the true null value.

Related

variable insert to a blink function

I'm new to HTML and ajax. I'm trying to insert a ip list from flask , to the ajax and trigger the js function to blink.
but somehow I can't find a way to insert the ip variable (response[i]) into the function value column in a right way.
it is to trigger the blink on the required ip tab in html.
function ajaxForm(){
// var form= new FormData(document.getElementById("myform2"));
var data = {"name":"John Doe"}
$.ajax({
url:"{{ url_for('Submit_form') }}",
type:"post",
contentType:'application/json',
data:JSON.stringify(data),
dataType: "json",
processData:false,
// async: false
success:function(response){
// alert(response)
if (response == "success")
{alert("Success !!!" );}
else {
for(i in response)
{
BLINK(response[i]);
}
}
},
// #time out 也进入 error
error:function(e){
// alert(e.)
alert("Failed submit form trigger!!!!");
}
})
}
<script type="text/javascript">
function BLINK(){
var t = null;
function blink() {
var obj = $('input[id="IP"][value=response[i]]') . <---- here
obj.addClass("blink-class");
t = setTimeout(function () {
obj.removeClass("blink-class");
t = setTimeout(function () {
blink(IP);
}, 550);
}, 550);
}
blink(IP);
t = setTimeout(function () {
clearTimeout(t);
}, 5000);
}
At first, you shoul always provide the HTML code too :) because now we dont know if the issue is there.
So let's try to solve the problem blindly :)
if i see this correctly, you just go wrong on the element and make it even more complicated than it is since you're using jquery, because if u have an ID on your elem, check this out:
// change this:
var obj = $('input[id="IP"][value=response[i]]') . <---- here // .. is your problem :)
obj.addClass("blink-class");
// with the dot you add this obj, which is it self, on it self :) that cant work :)
// you can try:
var obj = $('input[value="' + response[i] + '"]') // with NO dot and no fixed ID!
obj.addClass("blink-class");
// or try this
var obj = $('#' + response[i]);
obj.addClass("blink-class");
// and put the IP into the ID attraktion of your input element.
Second Problem is you are using an undefined variable "ID":
blink(IP); // in your timeout function
but you didnt declare this var, so if i understand your code right then your response[i] should be the IP?
Your function should look like this:
function BLINK(IP) { // <-- here you need the ip as parameter for your: BLINK(response[i]) from ajax
var t = null;
function blink() {
var obj = $('#' + IP) // and put IP in the id from input
obj.addClass("blink-class")
t = setTimeout(function () {
obj.removeClass("blink-class");
t = setTimeout(function () {
blink(IP);
}, 550);
}, 550);
}
blink(IP);
t = setTimeout(function () {
clearTimeout(t);
}, 5000);
}
try this, if its doesnt work please provide complete html and your css code too, also we could need an eventually error message from console, you can see that by pressing F12 in FireFox or Chrome and then switch to the console tab, press F5 then to reload the page and see errors, post it too please.
Or try out my jsfiddle for you:
https://jsfiddle.net/AIQIA/tjg659sr/17/
You have to remove dots from your IP and put it as id in your elem you wants get to blink, further you need to remove the dots from the response[i] or in your php code before, easy use $ip = preg_replace('/\./','',$ip);
Or use this to use only the complete IP in your input value, then you dont need to remove dots:
https://jsfiddle.net/AIQIA/tjg659sr/21/
greetz Toxi

Calling window.webkitRequestFileSystem twice causes first call not to be bypassed

Have an interesting problem ... I am making a BB10 application (I know) and am using the window.webkitRequestFileSystem call to a) provide a list of local files that this application has downloaded and b) read one of those files and display the contents - nothing crazy.
Individually, I can get both calls a) and b) to work; however, when I place them in the same function hoping to both display a list of files and read one of them, it causes the reading one not to fire at all.
In the example below, regardless of whether the listing call comes before or after the reading call, the reading call will not fire, i.e., I will never see the 'fileentry' alert.
What's going on?
function initFS(){
sharedFolder = blackberry.io.sharedFolder;
var path = sharedFolder+'/downloads';
//alert(path);
document.getElementById('plancontents').value="initialized";
window.requestFileSystem = window.requestFileSystem ||
window.webkitRequestFileSystem;
//window.requestFileSystem(window.TEMPORARY, 1024 * 1024,
//window.requestFileSystem(LocalFileSystem.PERSISTENT, 1024*1024*5,
window.webkitRequestFileSystem(window.PERSISTENT, 1024*1024*5,
function (fs) {
//fs.root.getFile(blackberry.io.sharedFolder
//fs.root.getFile('file:///accounts/1000/shared/downloads/filename.xml', {create: false},
fs.root.getFile(sharedFolder+'/downloads/filename.xml', {create: false},
function (fileEntry) {
alert("fileentry");
fileEntry.file(function (file) {
var reader = new FileReader();
//alert("trying to read file");
reader.onloadend = function (e) {
document.getElementById('plancontents').value = this.result;
};
reader.readAsText(file);
}, errorHandler);
}, errorHandler);
});
window.webkitRequestFileSystem(window.PERSISTENT, 1024*1024*5,
function (fs) {
alert('FS requested and inside');
fs.root.getDirectory(path, {}, function(dirEntry){
alert('inside getDir');
var dirReader = dirEntry.createReader();
alert('created reader');
dirReader.readEntries(function(entries) {
alert('trying to list dir');
for(var i = 0; i < entries.length; i++) {
var entry = entries[i];
if (entry.isDirectory) {
alert('Directory: ' + entry.fullPath);
}
else if (entry.isFile) {
alert('File: ' + entry.fullPath);
}
}
}, errorHandler);
}, errorHandler);
});
}

In chrome App, video file is not saved with its original data/size

In appCtrl.js, for saving video file -
$('#save_file').click(function(e) {
var config = {type: 'saveFile', suggestedName: chosenEntry.name};
chrome.fileSystem.chooseEntry(config, function(writableEntry) {
//blob content is the DataUrl
var blob = new Blob([$scope.blobContent], {type: 'video/mp4'});
$scope.writeFileEntry(writableEntry, blob, function(e) {
console.log('Write complete :)');
});
});
});
$scope.writeFileEntry = function(writableEntry, opt_blob, callback) {
if (!writableEntry) {
console.log('Nothing selected.');
return;
}
writableEntry.createWriter(function(writer) {
writer.onerror = $scope.errorHandler;
writer.onwriteend = callback;
// If we have data, write it to the file. Otherwise, just use the file we
// loaded.
if (opt_blob) {
writer.truncate(opt_blob.size);
$scope.waitForIO(writer, function() {
writer.seek(0);
writer.write(opt_blob);
});
}
else {
chosenEntry.file(function(file) {
writer.truncate(file.fileSize);
waitForIO(writer, function() {
writer.seek(0);
writer.write(file);
});
});
}
}, $scope.errorHandler);
}
$scope.waitForIO = function(writer, callback) {
// set a watchdog to avoid eventual locking:
var start = Date.now();
// wait for a few seconds
var reentrant = function() {
if (writer.readyState===writer.WRITING && Date.now()-start<4000) {
setTimeout(reentrant, 100);
return;
}
if (writer.readyState===writer.WRITING) {
console.error("Write operation taking too long, aborting!"+
" (current writer readyState is "+writer.readyState+")");
writer.abort();
}
else {
callback();
}
};
setTimeout(reentrant, 100);
};
In above code the video file is saved but when i tried to play that saved file in Window Media Player or VLC player , it prompt me as Window media player cannot play the file.The player might not support the file type or might not support the codec that was used to compress the file.
Can u please guide me where m getting wrong, as its my first chrome app.
Thanks in advance.
Change the method to store blob like this.
function dataURItoBlob(dataURI, callback) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], {type: 'video/mp4'});
};
To handle click.
$('#save_file').click(function(e) {
var config = {type: 'saveFile', suggestedName: chosenEntry.name};
chrome.fileSystem.chooseEntry(config, function(writableEntry) {
var blob = dataURItoBlob($scope.blobContent);
$scope.writeFileEntry(writableEntry, blob, function(e) {
console.log('Write complete :)');
});
});
});

Uncaught TypeError: Cannot read property 'pageSize' of undefined

Iam trying to apply paging to slickgrid and it shows an error in slick.pager.js as title in console and my code is
var jqxhr = $.getJSON('http://localhost:50305/Service1.svc/json/EmployeeDetails', function (data) {
dataView = new Slick.Data.DataView();
dataView.setItems(data, "EmpId");
dataView.setPagingOptions({ pageSize: 4 });
grid = new Slick.Grid("#teamGrid", dataView.rows, columns, options);
var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
dataView.onPagingInfoChanged.subscribe(function (e, pagingInfo) {
alert("hi");
var isLastPage = pagingInfo.pageNum == pagingInfo.totalPages - 1;
var enableAddRow = isLastPage || pagingInfo.pageSize == 0;
var options = grid.getOptions();
if (options.enableAddRow != enableAddRow) {
grid.setOptions({ enableAddRow: enableAddRow });
}
});
dataView.onRowCountChanged.subscribe(function (args) {
grid.updateRowCount();
grid.render();
});
Try this:
dataView.beginUpdate();
dataView.setItems(data, "EmpId");
dataView.endUpdate();
dataView.setPagingOptions({ pageSize: 4 });
grid = new Slick.Grid("#teamGrid", dataView, columns, options);
The code doesn't really even make sense.
The line
var jqxhr = $.getJSON('http://localhost:50305/Service1.svc/json/EmployeeDetails', function (data) {
is not well formed. There should be a function body and a closing brace.
The variable jqxhr is not used anywhere. Why does this line even exist ?
`pagesize=10`
let pagesizealt
if(!this.paginator){
pagesizealt=this.pagesize.toString()
}
else{
pagesizealt=this.paginator.pageSize
}`
u have to check for paginator to initialize after initializtion provide the value of pageSize

Angular JS correct factory structure

I have a factory in my AngularJS single page application that parses a given date against a JSON file to return season and week-number in season. I am currently calling the JSON file twice in each method $http.get('content/calendar.json').success(function(data) {....
How can i factor out the call to do it once regardless of how many methods?
emmanuel.factory('DayService', function($http, $q){
var obj = {};
obj.season = function(d){
// receives a mm/dd/yyyy string parses against Calendar service for liturgical season
d = new Date(d);
var day = d.getTime();
var promise = $q.defer();
var temp;
$http.get('content/calendar.json').success(function(data) {
for (var i=0; i<data.calendar.seasons.season.length; i++){
var start = new Date(data.calendar.seasons.season[i].start);
var end = new Date(data.calendar.seasons.season[i].end);
end.setHours(23,59);
//sets the time to be the last minute of the season
if (day >= start && day <= end){
//if given time fits within start and end dates in calendar then return season
temp = data.calendar.seasons.season[i].name;
//console.log(temp);
promise.resolve(temp);
break;
}
}
});
return promise.promise;
}
obj.weekInSeason = function(d){
//receives a date format mm/dd/yyyy
var promise = $q.defer();
$http.get('content/calendar.json').success(function(data) {
for (var i=0; i<data.calendar.seasons.season.length; i++){
d = new Date(d);
var day = d.getTime();
var end = new Date(data.calendar.seasons.season[i].end);
end.setHours(23,59);
end = end.getTime();
var diff = end - day;
if (parseFloat(diff) > 0){
var start = new Date(data.calendar.seasons.season[i].start);
start = start.getTime();
var startDiff = day - start;
var week = parseInt(startDiff /(1000*60*60*24*7))+1;
promise.resolve(week);
break;
}
}
});
return promise.promise;
}
obj.getData = function (d) {
console.log('DayService.getData')
console.log(today)
var data = $q.all([
this.season(d),
this.weekInSeason(d)
]);
return data;
};
return obj;
});
This solution assumes that content/calendar.json never changes.
I have answered a question which can help you in this problem one way or another. Basically you must fetch all necessary configurations/settings before the application bootstraps. Manually bootstrap the application, this means that you must remove the ng-app directive in your html.
Steps:
[1] Create bootstrapper.js as instructed in the answered question I have mentioned above. Basically, it should look like this(Note: You can add more configuration urls in urlMap, if you need to add more settings in your application before it bootstraps):
angular.injector(['ng']).invoke(function($http, $q) {
var urlMap = {
$calendar: 'content/calendar.json'
};
var settings = {};
var promises = [];
var appConfig = angular.module('app.settings', []);
angular.forEach(urlMap, function(url, key) {
promises.push($http.get(url).success(function(data) {
settings[key] = data;
}));
});
$q.all(promises).then(function() {
bootstrap(settings);
}).catch(function() {
bootstrap();
});
function bootstrap(settings) {
appConfig.value('Settings', settings);
angular.element(document).ready(function() {
angular.bootstrap(document, ['app', 'app.settings']);
});
}
});
[2] Assuming that the name of your main module is app within app.js:
angular.module('app', [])
.factory('DayService', function(Settings){
var calendar = Settings.$calendar,
season = calendar.seasons.season,
obj = {};
obj.season = function(d){
var day = new Date(d).getTime(),
start, end, value;
for (var i = 0; i < season.length; i++){
start = new Date(season[i].start);
end = new Date(season[i].end);
end.setHours(23,59);
if (day >= start && day <= end){
value = season[i].name;
break;
}
}
return value;
};
obj.weekInSeason = function(d){
var day = new Date(d).getTime(),
end, diff, start, startDiff, week;
for (var i = 0; i < season.length; i++){
end = new Date(season[i].end);
end.setHours(23,59);
end = end.getTime();
diff = end - day;
if (parseFloat(diff) > 0){
start = new Date(season[i].start);
start = start.getTime();
startDiff = day - start;
week = parseInt(startDiff /(1000*60*60*24*7))+1;
break;
}
}
return week;
};
return obj;
});
[3] Controller Usage(Example):
angular.module('app')
.controller('SampleController', function(DayService) {
console.log(DayService.season(3));
console.log(DayService.weekInSeason(3));
});
Another Note: Use .run() to check if Settings === null - if this is true, you can direct to an error page or any page that displays the problem(This means that the application bootstrapped but one of the requested configuration failed).
UPDATE:
I checked the link you have provided, and it seems that the version you are using is AngularJS v1.0.8, which does not have a .catch() method in their $q promise implementation.
You have the following options to consider in solving this problem:
-1 Change the AngularJS version you are using to the latest stable version 1.2.23.
Note that this option may break some of your code that is highly reliant on the version that you are using.
-2 Change this block:
$q.all(promises).then(function() {
bootstrap(settings);
}).catch(function() {
bootstrap();
});
to:
$q.all(promises).then(function() {
bootstrap(settings);
}, function() {
bootstrap();
});
This option is safer if you already have existing code that relies on the current AngularJS version you are using But I would suggest you change to the current stable version as it has more facilities and fixes than the one you are currently using.
Use your scope and closure of the factory to store the value of the response to the http call. I created an object called calData, which happens to already be a promise!
This gives you the ability to kick a few things off when the first call to the factory is made by running an IIFE (this is the function called initService), and everything chains together to resolve after the data is loaded.
.factory('dayService', function dayServiceFactory($http, $q){
var getCalData = $q.defer();
var calData = gettingData.promise; // null/undefined until _loadData is called and resolved
function _loadData(){
var deferred = $q.defer();
$http.get('content/calendar.json').success(function(data) {
calData.seasons = data.calendar.seasons; // your code seems to always use at least calendar.seasons, so easier to assign that
deferred.resolve(data);
});
return deferred.promise;
}
// this function will automatically run and load data the first time the factory is executed
(function initService(){
_loadData().then(){
// here is where you will build all your functions to assign properties to calData.seasons or any other child property of calData;
calData.getSeason = function(){
for (var i=0; i<data.calendar.seasons.season.length; i++){
// code here
}
}// function to get day using calData.seasons
calData.weekInSeason = function(){}
getCalData.resolve(); // this resolves the data in the outer scope
}
}());
return calData; // returns the promise, and will execute the first time called
});
To use this in a controller, make sure to either resolve the service before you instantiate the controller, or withing the controller, use your assignments of the data after it has resolved. (Bound values will auto-update when it's resolved)
dayService.then(function(){
// now you can use this:
var week = dayService.weekInSeason();
})
You can create separate method for getting calendar data and chain promises in getData method:
emmanuel.factory('DayService', ['$q', '$timeout', '$log',
function($q, $timeout, $log) {
return {
season: season,
weekInSeason: weekInSeason,
getData: getData
};
function season(d) {
$log.log('season called');
return getCalendar(d).then(function(calendar) {
return getSeason(d, calendar);
});
}
function weekInSeason(d) {
$log.log('weekInSeason called');
return getCalendar(d).then(function(calendar) {
return getWeekInSeason(d, calendar);
});
}
function getData(d) {
$log.log('getData called');
return getCalendar(d).then(
function(calendar) {
return $q.all({
season: getSeason(d, calendar),
weekInSeason: getWeekInSeason(d, calendar)
});
}
);
}
function getSeason(date, calendar) {
$log.log('getSeason called');
return {
date: date,
calendar: calendar,
method: 'getSeason'
};
}
function getWeekInSeason(date, calendar) {
$log.log('getWeekInSeason called');
return {
date: date,
calendar: calendar,
method: 'getWeekInSeason'
};
}
function getCalendar(d) {
$log.log('getCalendar called');
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(12345);
}, 2000);
return deferred.promise;
}
}
]);
Also, if calendar.json doesn't changed during application lifetime, you can cache calendar.json ajax request result as suggested by #runTarm
Plunker