I'm trying to start a loader to show that I have a process going on. Converting a kml file to geojson. The converting part works fine. Larger kml files take longer to convert and I want to show that my web page is doing something while it's converting the file. I have this:
function convertFunction() {
loader.style.display = "block";
if(format.value = "kml"){
out.value = JSON.stringify(toGeoJSON["kml"]((new DOMParser()).parseFromString(input.value, 'text/xml')), null, 4);
}
};
I'm used to working with Android and when I order my processes like that, it usually starts the first one first.
Why does my loader not start until after my file is converted and placed into my out text view? How can I get it to work the way I want it to?
I'm not uploading the file to a server first. I'm reading the text from the file, placing the text in a text view(input), getting the text from the input, convert and put new text in the output text view. Then last button to create the geojson file and download it.
The reason that your loader isn't showing is that your conversion process is blocking code. This means that it will hold up the main thread (the UI thread) until the conversion process is done. The loader will never be shown because the conversion will already be done before the browser has a chance to show it.
A possible solution:
Use a Web Worker to carry out the conversion process on a separate thread. This will keep your UI thread free so that your loader can display and animate.
Another possible (simpler) workaround:
Display something on the page to indicate that the conversion process is going on, and use setTimeout to delay the conversion process just enough to allow the page to update. Note that you wouldn't be able to show any sort of animation during the conversion in this case because the blocked UI thread would prevent it from animating.
function convertFunction() {
if(format.value === "kml"){
loadingMessage.style.display = "block";
setTimeout(function () {
out.value = JSON.stringify(toGeoJSON["kml"]((new DOMParser()).parseFromString(input.value, 'text/xml')), null, 4);
loadingMessage.style.display = 'none';
// run any code that would use out.value
}, 100);
}
};
Related
For my Angular 1.5 file upload component, I implemented a preview.
When the user selects a file, it is read by a FileReader and on load end, I store the content in a controller variable like
fileReader.onloadend = function(ev) {
$rootScope.$evalAsync(function($scope) {
$ctrl.rawFileContent = ev.target.result;
});
};
The template shows it to the user
<pre ng-show="$ctrl.rawFileContent">{{$ctrl.rawFileContent}}</pre>
This worked pretty well for my test during development.
The Problem
Real world users are going to upload >500kB files and then it takes minutes until the template is rendered.
Profiling showed, that some internal function in 'content-script.bundle.js' takes by far most of the time.
Update:
And worst of all ;) it has to run in IE11.
What I tried so far
using one time binding {{::$ctrl.rawFileContent}} which yielded no improvement
fetching the <PRE> and setting its inner text via direct DOM manipulation, which still takes long and seemed a bit 'non-angulary' to me.
<pre ng-show="$ctrl.rawFileContentReady" class="previewTarget"></pre>`
$rootScope.$evalAsync(function($scope) {
var previewTarget = document.getElementsByClassName("previewTarget")[0];
previewTarget.innerHTML = ev.target.result;
});
Do you have any ideas, why this takes so long?
How can I speed it up?
Or, as a workaround, can I track the progress somehow to inform the user?
This link helps to find how to do progress
I have a not too big grid (30x20) with numbers in cells. I have to display all, calculate them in different ways (by columns, rows, some cells, etc.) and write values to some cells. This data is also written and read from db table fields. Everything is working, excluding simple (theoretically) mask tools.
In time of e.g. writing data to the field in the table I try to start mask and close it on finish. I used such a “masks” very often but only in this situation I have a problem and can’t solve it.
I prepare this mask the following way:
msk = new Ext.LoadMask(Ext.getBody(), { msg: "data loading ..." });
msk.show();
[writing data loops]
msk.hide();
msk.destroy();
I also tried to use grid obiect in place of Ext.getBody(), but without result.
I found also that the program behaves in a special way – loops which I use to write data to the table field are "omitted" by this mask, and it looks like loops are working in the background (asynchronously).
Would you be so kind as to suggest something?
No, no, no, sorry guys but my description isn’t very precise. It isn’t problem of loading or writing data to the database. Let’s say stores are in the memory but my problem is to calculate something and write into the grid. Just to see this values on the screen. Let me use my example once again:
msk = new Ext.LoadMask(Ext.getBody(), { msg: "data loading ..." });
msk.show();
Ext.each(dataX.getRange(), function (X) {
Ext.each(dataY.getRange(), function (Y) {
…
X.set('aaa', 10);
…
}
msk.hide();
msk.destroy();
And in such a situation this mask isn’t visible or is too fast to see it.
In the mean time I find (I think) a good description of my problem but still can’t find a solution for me. When I use e.g. alert() function I see this mask, when I use delay anyway, mask is too fast. Explanation is the following:
The reason for that is quite simple - JS is single threaded. If you modify DOM (for example by turning mask on) the actual change is made immediately after current execution path is finished. Because you turn mask on in beginning of some time-consuming task, browser waits with DOM changes until it finishes. Because you turn mask off at the end of method, it might not show at all. Solution is simple - invoke store rebuild after some delay.*
I have no idea how is your code looks in general but this is some tip that you could actually use.
First of all loading operations are asynchronously so you need to make that mask show and then somehow destroy when data are loaded.
First of all check if in your store configuration you have autoLoad: false
If yes then we can make next step:
Since Extjs is strongly about MVC design pattern you should have your controller somewhere in your project.
I suppose you are loading your data on afterrender or on button click event so we can make this:
In function for example loadImportantData
loadImportantData: function(){
var controller = this;
var store = controller.getStore('YourStore'); //or Ext.getStore('YourStore'); depends on your configuration in controller
var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
myMask.show();
store.load({
callback: function (records, operation, success) {
//this callback is fired when your store load all data.
//then hide mask.
myMask.hide();
}
});
}
When data is loaded your mask will disappear.
If you have a reference to the grid, you can simply call grid.setLoading(true) to display a loading mask over the grid at any time.
I tried to print multiple html files in folder with qz-print and EPSON - TM-T20II, but seem no work.
This is an example of script that i used:
function printPages() {
if (notReady()) {
return;
}
qz.appendHTMLFile(getPath() + "misc/out-may-21.html");
qz.appendHTMLFile(getPath() + "misc/out-may-22.html");
while (!qz.isDoneAppending()) {
qz.printHTML();
}
but it will only print "out-may-22.html" file.
- And one more problem, when printing html file, it print html file, then print one more text file with tag "".
So confused,
thanks.
Update: Since QZ Tray 2.0, the new API supports a data block which supports multiple HTML files without confusing callbacks.
For those still using QZ Print/QZ Tray 1.9, the function qz.appendHTMLFile("..."); is not synchronous and cannot currently be called in succession.
Instead, you'll have to wait until qzDoneAppending() is called, then call printHTML(), then call qz.appendHTMLFile("..."); again, etc.
<script>
// Called automatically when the software has loaded
function qzReady() {
qz.findPrinter("epson");
}
// Called automatically when the software has finished searching for the printer
function qzDoneFinding() {
// append first file
qz.appendHTMLFile("first.html");
}
var secondHasAppended= false;
// Called automatically when a file is done appending
function qzDoneAppending() {
qz.print();
}
// Called automatically when document has been sent to the printer
function qzDonePrinting() {
if (!secondHasAppended) {
qz.appendHTMLFile("second.html");
secondHasAppended = true;
// qzDoneAppending and qzDonePrinting will take care of the rest
} else {
alert("Done!");
}
}
</script>
If you require more than two documents, replace the boolean with a counter.
I use QZTray 2.0.2 and I could not make it prints multi pages.
It only prints first page. In other words it only prints what it can render for only 1 page.
I have 3 pages HTML.
When I set "scaleContent" to false it only prints the one portion of first page. When I set it true it prints all pages into 1 page with scaling.
All I need is to print all pages one by one with scaling.
Best
So, for a little backstory, I'm using the jRecorder plugin for jQuery on a page that is dynamically fed some HTML via ajax. The user can record a .wav narration for an image in a slideshow, then (via ajax) flip over to another image, record another narration, rinse and repeat. End backstory!
The question itself is geared more towards jQ/JS in general, I believe. When I run the 'record' function again, I get this error in the console:
Uncaught TypeError: Object # has no method 'jStartRecording'
This only appears when I switch to the second image and click "record". The first narration records just fine, and can be played back and whatnot with no issue. I'm thinking I'm receiving the error because I need to re-initialize or reload the jRecorder plugin/method/function since I am trying to call jRecorder again using a different set of options (after switching to another image in the slideshow). Since I'm calling it again, it would appear that something hasn't completely loaded, or there is some sort of conflict between each instance of the plugin's operation.
Bottom line: is there a way to reinitialize a jQuery plugin so it can be run again after dynamically switching parameters?
Perhaps I'm barking up the wrong tree entirely -- I don't know. Any insight from a different set of eyes would be greatly appreciated. Thanks so much!
EDIT: As requested, here's a little bit of code. And here is the plugin source. Hope it helps!
renderPanes() is called each time the widget containing the narration recorder is refreshed with a new image's data. Obviously some things have been edited out for brevity and security.
function renderPanes(type, bucket_id) {
var isRecording = false;
$.getJSON( [endpoint] )
.done(function(json){
[....]
$.jRecorder({
host : [endpoint],
callback_started_recording: function(){callback_started(); },
callback_stopped_recording: function(){callback_stopped(); },
callback_activityLevel: function(level){callback_activityLevel(level); },
callback_activityTime: function(time){callback_activityTime(time); },
callback_finished_sending: function(time){ callback_finished_sending() },
swf_path : '/assets/js/jrecorder/jRecorder.swf',
});
$("#narration_play").click(function(){
var audio = new Audio("[folder path]/"+bucket_id+".wav");
audio.play();
});
$("#narration_record").click(function(){
if (!isRecording) {
$.jRecorder.record(30);
$("#narration_record").html("<i class='icon-stop'></i> Stop");
isRecording = true;
} else {
isRecording = false;
$("#narration_record").html("<i class='icon-comment'></i> Record");
$("#narration_play").removeClass('disabled');
$.jRecorder.stop();
$.jRecorder.sendData();
}
});
});
}
I'm attempting to create a page that displays and refreshes an image from a webcam (camimg.jpg), but displays a static image (notlive.jpg) if the image hasn't been updated recently. I've found the AJAXCam script, which serves the purpose of reloading the "live" image at a set interval (15 secs), yet with no Javascript experience I can't figure out how to determine when the image was last updated in order to decide whether or not camimg.jpg or notlive.jpg should be displayed.
My limited experience with programming has me thinking it should be something along the lines of:
pageLoaded = time page loaded in browser
imageUpdated = time the image was uploaded to server
if imageUpdated is not within 20 seconds of pageLoaded:
display notlive.jpg
else:
run AJAXCam
The AJAXCam code (initially called by <body onLoad="holdUp()">) is as follows:
<script type="text/javascript">
<!--
//
//AJAXCam v0.8b (c) 2005 Douglas Turecek http://www.ajaxcam.com
//
function holdUp()
{
//
// This function is first called either by an onLoad event in the <body> tag
// or some other event, like onClick.
//
// Set the value of refreshFreq to how often (in seconds)
// you want the picture to refresh
//
refreshFreq=15;
//
//after the refresh time elapses, go and update the picture
//
setTimeout("freshPic()", refreshFreq*1000);
}
function freshPic()
{
//
// Get the source value for the picture
// e.g. http://www.mysite.com/doug.jpg and
//
var currentPath=document.campic.src;
//
// Declare a new array to put the trimmed part of the source
// value in
//
var trimmedPath=new Array();
//
// Take everything before a question mark in the source value
// and put it in the array we created e.g. doug.jpg?0.32234 becomes
// doug.jpg (with the 0.32234 going into the second array spot
//
trimmedPath=currentPath.split("?");
//
// Take the source value and tack a qustion mark followed by a random number
// This makes the browser treat it as a new image and not use the cached copy
//
document.campic.src = trimmedPath[0] + "?" + Math.random();
//
// Go back and wait again.
holdUp();
}
// -->
</script>
Is what I'm trying to accomplish even possible? And if so, how would I go about implementing it? Thanks in advance for the help!
There is no way to do it in javascript.
Your only option is, in case you have access to server side languages like PHP you can send a simple HEAD request and check Last Modified header of the image then report it back to the browser via Ajax.