How to force / set locale in PDF.js - html

I'm upgrading from an old version of PDF.JS (1.9.426) to the latest stable (2.5.207).
Previously, it was very simple to force the locale to match your applications current locale.
You simply pass it through as a parameter in the URL;
/PDFJS/web/viewer.html?file=example.pdf #locale=zh-CN
However, on upgrading, I see that this is no longer recommended.
This is despite the documentation still mentioning it.
In my application, users can override their prefered locale, so it might not match the browser.
I've looked into embed / object, which seemed like the solution, until I realised Android browsers don't support embedded PDF viewing.
I've been searching for the correct way to implement this, and so far I've not found a good or recommended answer.
It seems PDF.js is still the best all round solution, but I can't figure out the correct way of using it to simply render an existing PDF into a div.
From what I can tell the developers simply removed the option, didn't upgrade the docs, and are recommending to hard code the locale in viewer.js (which to me, kind of defeats the point).
I'm hoping someone can point me in the correct direction, and possibly help others who come across this.

For anyone looking to just get this working (until a better answer comes along), heres a fix;
Find the method "_initializeL10n" in viewer.js (line 552 in v2.5.207);
async _initializeL10n() {
this.l10n = this.externalServices.createL10n({
locale: _app_options.AppOptions.get("locale")
});
const dir = await this.l10n.getDirection();
document.getElementsByTagName("html")[0].dir = dir;
}
Change it to this;
async _initializeL10n() {
var hash = document.location.hash.substring(1);
var hashParams = (0, _ui_utils.parseQueryString)(hash);
this.l10n = this.externalServices.createL10n({
locale: ('locale' in hashParams) ? hashParams['locale'] : _app_options.AppOptions.get("locale")
});
const dir = await this.l10n.getDirection();
document.getElementsByTagName("html")[0].dir = dir;
}
This takes the code we need from the old version and gets #locale= working.
I hope to be told the correct way of doing it at some point.

Related

What's the lightest way to add the smallest amount of dynamics to a static HTML site?

I have a personal website that's all static html.
It works perfectly for my needs, except for one tiny thing.
I want to dynamically change a single word on a single page: the name of the current map for a game server I'm running.
I can easily run a cron job to dump the name of the map into a file in the site's html directory, call it mapname.txt. This file contains a single line of text, the name of the map.
How would I update, say, game.html to include this map name?
I would very strongly prefer to not pull in some massive framework, or something like php or javascript to accomplish this.
I want the lightest weight solution possible. Using sed is an option, although definitely a hacky one. What's the tiniest step up from static html?
If you say "dynamically", do you mean:
If the information changes ...
A) the user should see it after they have re-loaded the page?
B) the page should update without the need to reload?
For A, you can use PHP (or any other language your server supports) to read the data from the file and print it into the web page. This will happen on server side.
For B, you can use JS that queries the file and updates the HTML. This will happen on client side.
To change text there are a few way though only two appropriate methods.
First is using textContent:
document.getElementById('example').textContent = 'some example text';
Secondly is the older nodeValue however it's a bit more tricky since you have to specify the exact textNode (e.g. .firstChild):
document.getElementById('example').firstChild.nodevalue = 'some example text';
You're 100% on the mark about not using frameworks or libraries, almost everything exists without the suck.
I'm not going to test this though this is a very stripped down version of my ajax function from my web platform. Some people might scream about the Fetch API however the syntax is an absolute mess. I recommend figuring out how to standardize this function so you can use it for everything instead of making copies of the code for every instance. Mine supports both GET and POST requests.
function ajax(method, url, param_id_container_pos, id_container)
{
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.timeout = 8000;
xhr.open(method,url,true);
xhr.send(null);
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
if (xhr.getResponseHeader('content-type'))
{
var type = xhr.getResponseHeader('content-type').split('/')[1];
if (type.indexOf(';') >- 1) {type = type.split(';')[0];}
}
else {var type = 'xml';}//Best guess for now.
console.log(type,xhr);
console.log(xhr.responseText);
//console.log(type,xhr.responseXML);
//document.getElementById('example').textContent = xhr.responseText;
}
}
}
You're also going to have to ensure that the url is set to an absolute path. I use path variable in my platform (see my profile for the link, wildly clean and organized code).
There are plenty of ways to make this function reusable and I highly recommend doing that. For now use the last non-curley-bracket line to update your line of text.

Simple function to read file from an URL to a string buffer ( C++ / MQL{4|5} using WinInet.dll )

I am looking for a simple function which is able to read a text or binary file from the internet into a string variable.
It´s unbelievable that I could not find anything in the web, just low level descriptions of all the WinInet functions and useless samples, that do not work at all, at the MQL-forums.
What I need is a function like:
string buffer = ReadTextFileFromWeb( "www.myurl.net/textfile.txt" );
No more, no less. I am not very familiar with internet programming stuff at all, but I am sure there is anybody out there who is able to present the reason just like that.
The code will be used in MQL4/MQL5. I know that there is already a WebRequest() function which works, but it is restricted to expert advisors and cannot be used in Custom Indicator type of code.
I need this solution to load data into a custom indicator.
Go get this on github https://github.com/sergeylukin/mql4-http
//For MT4 Add HTTP Access
#include <mql4-http.mqh>
string URLr = "www.myurl.net/textfile.txt";
Print("URLr return is: ", URLr);
For MT5 you are on your own.
The above dose not have the issues that WebRequest() has. Or I have not seen it have any issues. I use it all the time in a lot of EA and never had a chart lockup or have a issue.

Opening specific MimeTypes with google picker

I am working with realtime API and I am making use of realtime-client-utils.
Using existing code, I am creating realtime files with this method:
createRealtimeFile = function(title, callback) {
gapi.client.load('drive', 'v2', function() {
gapi.client.drive.files.insert({
'resource': {
mimeType: rtclient.REALTIME_MIMETYPE,
title: title
}
}).execute(callback);
});
}
and then I am trying to open files with this picker:
var popupOpen = function () {
var token = gapi.auth.getToken().access_token;
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes(rtclient.REALTIME_MIMETYPE+ "."+realTimeOptions.appId);
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.setAppId(realTimeOptions.appId)
.setOAuthToken(token)
.addView(view)
.addView(new google.picker.DocsUploadView())
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
};
Although if I use the setMimeTypes, no documents are found. If I remove that filter, my documents appear normally(along with every time of document in the drive). THe mime type I am using is the default one:
rtclient.REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk';
I am adding the appID as this is how its done on realtime-playground. I also tried without the "." or the appID but no documents are found.
Any suggestions about how to fix the filter ?
You should look for mimeType you created with.
You created your file with mimeType rtclient.REALTIME_MIMETYPE and you're looking for files with mimeType rtclient.REALTIME_MIMETYPE+ "."+realTimeOptions.appId That is the reason why you're not getting any files.
Change filepicker code to:
view.setMimeTypes(rtclient.REALTIME_MIMETYPE);
And make sure you change
rtclient.REALTIME_MIMETYPE = 'application/{{YOURE_CUSTOM_MIMETYPE}}';
to avoid collision with other apps.
Found the answer on an android forum. I had to create files with this mimeType:
REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk.'+appID;
and use same mimeType on view :
view.setMimeTypes(REALTIME_MIMETYPE);
Short answer: correct your appID. It is the first part of your CLIENT-ID. That is, if your client-id is 1088706429537-4oqhqr7o826ditbok23sll1rund1jim1.apps.googleusercontent.com, your APP_ID is 1088706429537. I initially confused it with the project-id and had your problem.
I started new answer because all accepted ones are wrong since they disregard the main issue. Might be they are right advising to change the mime-type to something completely custom. Yet, the most popular answer says that
You created your file with mimeType rtclient.REALTIME_MIMETYPE and
you're looking for files with mimeType rtclient.REALTIME_MIMETYPE+
"."+realTimeOptions.appId
This is seems natural but wrong fact. The topic author is right reproducing the demos. Google demos seem to do exactly that: they create application/vnd.google-apps.drive-sdk file and look for appid-expanded ones. This is correct actually because whenever you create a REALTIME_MIMETYPE=application/vnd.google-apps.drive-sdk file, google drive silently fixes file type! It expands it with .APP_ID. This also means that you do not need to customize your mime-type, as other answers propose. You can proceed with application/vnd.google-apps.drive-sdk, I suppose. I have checked: Google will even fix your mime type if some letters are misspelled, which makes the proposed customization even harder. Google API will take another mime type only if it is too different from REALTIME one. But I am not sure that this is a right thing to do, despite this is proposed by all other accepted answers as 'solution' because I do not know about the difference this implies. Nevertheless,
to to tie up, the reasons to use application/vnd.google-apps.drive-sdk instead of proposed custom types are:
This standard type is proposed by Google in realtime playground demos instead of custom type
Google calls this type 'REALTIME_MIMETYPE'. If your use something different, you use Realtime API to create non-realtime files. At least not that much realtime as proposed by google.
If you specify a different mime type, google still corrects it to REALTIME_MIMETYPE. This means that custom mime types are unwelcomed.
Proponents of customization do not understand anything of this. They even dare to laugh at Google official examples as 'ridiculous'. They basically say that we should not trust them.

MvxDynamicImageHelper unreliable

I have an Mvx base iOS project which is having problems with image downloads.
I have a couple of screens which contain UICollectionViews and the UICollectionViewCells use MvxDynamicImageHelpers to set the Image of their UIImageViews to images hosted on the internet (Azure blob storage via Azure CDN in actual fact). I have noticed that the images sometimes do not appear and that this is more common on a slow connection and if I scroll through the whole UICollectionView while the images are loading - presumably as it initiates a large number of simultaneous downloads. Restarting the app causes some, but not all, of the images to be shown.
Looking in the Caches/Pictures.MvvmCross folder I see there are a number of files with .tmp extensions and some without .tmp extensions but a 0 byte file size. I presume that the .tmp files are the ones that are re-downloaded following an app restart and that an invalid in-memory cache entry is causing them not to be re-downloaded until this happens.
I have implemented my versions of MvxDownloadRequest and MvxHttpFileDownloader and registered my IMvxHttpFileDownloader. The only modification in MvxHttpFileDownloader is to use my MvxDownloadRequest instead of the standard Mvx one.
As far as I can see, there are no exceptions being thrown in MvxDownloadRequest.Start or MvxDownloadRequest.ProcessResponse and MvxDownloadRequest.FileDownloadFailed is not being called. Having replaced MvxDownloadRequest.Start with the following, all images are always downloaded and displayed successfully:
try
{
ThreadPool.QueueUserWorkItem((state) => {
try
{
var fileService = this.GetService<IMvxSimpleFileStoreService>();
var tempFilePath = DownloadPath + ".tmp";
var imageData = NSData.FromUrl(NSUrl.FromString(Url));
var image = UIImage.LoadFromData(imageData);
NSError nsError;
image.AsPNG().Save(tempFilePath, true, out nsError);
fileService.TryMove(tempFilePath, DownloadPath, true);
}
catch (Exception exception)
{
FireDownloadFailed(exception);
return;
}
FireDownloadComplete();
});
}
catch (Exception e)
{
FireDownloadFailed(e);
}
So, what could be causing the problems with the standard WebRequest which is not affecting the above version? I'm guessing it's something to with GC and will do further debugging when I get time, but this won't be fore a while unfortunately. Would be very much appreciated if someone can answer this or provide pointers for when I do look at it.
Thanks,
J
From the description of your investigations so far, it sounds like you have isolated the problem down to the level that httpwebrequest sometimes fails, but that the NSData methods are 100% reliable.
If this is the case, then it would suggest that the problem is somewhere in the xamarin.ios network stack or in the use of it.
It might be worth checking the xamarin bugzilla repository and also asking their support team if they are aware of any issues in this area. I believe they did make some announcements about changes to the iOS networking at evolve - see the CFNetworkHandler part late in the video and slides at http://xamarin.com/evolve/2013#session-b3mx6e6rmb - and there are worrying questions on here like iPhone app gets into a state where network requests never complete
Beyond that, I'd guess the first step in any debugging would be to isolate the issue in a simple test app - eg a simple app which just downloads one image at a time and which demonstrates a simple pass/fail for each technique. If you can replicate the issue in a small test app, then it'll be much quicker to work out what the issue is.

Chrome extension : Download/export content created "on the fly"

I need to let the user to download a file created on the fly from some data contained in the extension, but I don't want to do this server-side.
As a real-world example : There is a variable containing the text "hello world". I want the user to be able to download/create a .TXT file containing such text.
Is it possible ?
-edited Oct 30, 2010-
Solutions so far:
window.saveAs - not working at all
createObjectURL - works, but the filename and other options can't be customized yet
copy data to clipboard - works, but too many steps are required to the user
create a GoogleDocs document - could work, but needs messing with the API and Oauth
-edited Apr 15, 2011
Looks like things are improving: https://github.com/eligrey/FileSaver.js
But Chrome 14+ is still a bit weird about filenames.
I think the only way is to call save dialog through flash, see Downloadify library.
In the Chromium-extensions Google Group I have found this working example: (I have modified it to work from the pop-up)
BuiltBlob = new BlobBuilder("");
BuiltBlob.append("Hello, world");
BlobToSave = BuiltBlob.getBlob();
chrome.tabs.create({'url': createObjectURL(BlobToSave), 'selected': false});
But the filename is not set, ending with something like cf8a56bf-d724-4b97-b10f-e252961135bd
On the The W3C docs ( http://dev.w3.org/2009/dap/file-system/file-writer.html ) I've found this not working example:
var bb = new BlobBuilder();
bb.append("Lorem ipsum");
var fileSaver = window.saveAs(bb.getBlob(), "test_file");
fileSaver.onwriteend = myOnWriteEnd;
but window.saveAs doesn't appear to exists.
Googleing around I've found outdated Google Gears references, but nothing else, maybe because I'm dealing with something too new to have proper documentation ?
Is there a way to set the filename/mime-type to the first example?
I don't think this is possible because of safety reasons