I need to read data from a GPSMap 62 device using the device control Javascript library. Problem is, unlike older devices, this device stores its waypoints in separate .GPX files every day. The javascript library expects all tracks and waypoints to be in the current.gpx file, but the 62 stores them in e.g. Waypoints_06-MAY-14.gpx and so on each day.
Short of requiring users to manually upload the appropriate file, has anyone gotten the DeviceControl library to actually support the newer devices with separate GPX files?
As an added bonus, the Garmin Device Control library is deprecated, so no updates are forthcoming.
Some code
startReadFromGps: function(deviceNumber) {
this.plugin.StartReadFromGps( deviceNumber ); //invokes the external plugin
},
I've checked out plugin in version 2.3-RC1 (I do not know, which version do you use).
Indeed there is startReadFromGps method:
/** Initiates the read from the gps device conneted. Use finishReadFromGps and getGpsProgressXml to
* determine when the plugin is done with this operation. Also, use getGpsXml to extract the
* actual data from the device. <br/>
* <br/>
* Minimum plugin version 2.0.0.4
*
* #param deviceNumber {Number} assigned by the plugin, see getDevicesXml for
* assignment of that number.
* #see #finishReadFromGps
* #see #cancelReadFromGps
* #see #getDevicesXml
*/
startReadFromGps: function(deviceNumber) {
this.plugin.StartReadFromGps( deviceNumber );
},
So it uses getGpsXml. I assume that it uses specified filename that is read and method returns file's content. My first thought is to change the filename - it is possible with:
/** This the filename that wil contain the gps xml once the transfer is complete. Use with
* setWriteGpsXml to set what the file contents will be. Also, use startWriteToGps to
* actually make the write happen.
*
* #private
* #param filename {String} the actual filename that will end up on the device. Should only be the
* name and not the extension. The plugin will append the extension portion to the file name--typically .gpx.
* #see #setWriteGpsXml, #startWriteToGps, #startWriteFitnessData
*/
_setWriteFilename: function(filename) {
this.plugin.FileName = filename;
},
But _setWriteFilename is private method. However called by
startWriteToGps: function(gpsXml, filename, deviceNumber)
and
startWriteFitnessData: function(tcdXml, deviceNumber, filename, dataTypeName)
Since now I will check if calling those methods with your specified filename will override filename value permanently and further calling of startReadFromGps will use new filename.
I cannot test it, I didn't use this library but you can give a shot.
Related
I've gotten this IPFS info such as "/ipfs://QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE" as API response.
I want to display this file(image) on my page, but I can't find out the correct solution.
How can I get the image URL from this info in react app?
Please help with my concern.
Try adding https://ipfs.io in the beginning of your ipfs info as suggested in this document https://docs.ipfs.io/concepts/what-is-ipfs/
i.e
ipfs://QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE
becomes
https://ipfs.io/ipfs/QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE
If you're using js-ipfs, you can retrieve the image over IPFS, and display it:
/** Uses `URL.createObjectURL` free returned ObjectURL with `URL.RevokeObjectURL` when done with it.
*
* #param {string} cid CID you want to retrieve
* #param {string} mime mimetype of image
* #param {number} limit size limit of image in bytes
* #returns ObjectURL
*/
async function loadImgURL(cid, mime, limit) {
if (cid == "" || cid == null || cid == undefined) {
return;
}
const content = [];
for await (const chunk of ipfs.cat(cid, {length:limit})) {
content.push(chunk);
}
return URL.createObjectURL(new Blob(content, {type: mime}));
}
Then you can display it with something like:
<body>
<img id="myImage" />
<script>
async function setImage() {
// just an example, make sure to free the resulting ObjectURL when you're done with it
//
// if your CID doesn't work, try this one: Qmcm32sVsMYhURY3gqH7vSQ76492t5Rfxb3vsWCb35gVme
// that's a popular CID, which should resolve every time
document.getElementById("myImage").src = await loadImgURL("QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE", "image/png", 524288);
}
setImage();
</script>
</body>
The big advantage of this is you're using the IPFS network itself, and not relying on a public HTTP gateway (the recommended way).
You can do something like that:
tokenURI.replace("ipfs://", "https://ipfs.io/ipfs/");
One thing to note here about fetching images from IPFS that I think isn't being discussed sufficiently in these answers is that you will need to either
Run your own node of IPFS, or
Get a hosted IPFS node through a service like Infura
I have spent a little bit of time working through this in the last couple of days, and it will always come back to you having to have direct access to your own node.
There are "Gateways," which are nodes hosted by the community, and you can read more about them in the IPFS docs here: https://docs.ipfs.io/concepts/ipfs-gateway/#limitations-and-potential-workarounds
The thing with the gateways is that they are not meant to be relied upon for production sites, as you can see below. It's possible that there is some hosted node out there that somebody is giving out for free, but I doubt it, and you wouldn't want to rely on that anyways.
I think that other questions above have elaborated how you actually process the responses once you get it, but I wanted to cover this extra ground in my answer.
ipfs docs
let imgUrl = url?.slice(url.indexOf(":"),url?.lastIndexOf("/"));
let slice = url?.slice(url.lastIndexOf("/"),url?.length)
let renderURL = `https${imgUrl}.ipfs.dweb.link${slice}`;
console.log(renderURL);
I've gotten this IPFS info such as "/ipfs://QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE" as API response.
I want to display this file(image) on my page, but I can't find out the correct solution.
How can I get the image URL from this info in react app?
Please help with my concern.
Try adding https://ipfs.io in the beginning of your ipfs info as suggested in this document https://docs.ipfs.io/concepts/what-is-ipfs/
i.e
ipfs://QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE
becomes
https://ipfs.io/ipfs/QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE
If you're using js-ipfs, you can retrieve the image over IPFS, and display it:
/** Uses `URL.createObjectURL` free returned ObjectURL with `URL.RevokeObjectURL` when done with it.
*
* #param {string} cid CID you want to retrieve
* #param {string} mime mimetype of image
* #param {number} limit size limit of image in bytes
* #returns ObjectURL
*/
async function loadImgURL(cid, mime, limit) {
if (cid == "" || cid == null || cid == undefined) {
return;
}
const content = [];
for await (const chunk of ipfs.cat(cid, {length:limit})) {
content.push(chunk);
}
return URL.createObjectURL(new Blob(content, {type: mime}));
}
Then you can display it with something like:
<body>
<img id="myImage" />
<script>
async function setImage() {
// just an example, make sure to free the resulting ObjectURL when you're done with it
//
// if your CID doesn't work, try this one: Qmcm32sVsMYhURY3gqH7vSQ76492t5Rfxb3vsWCb35gVme
// that's a popular CID, which should resolve every time
document.getElementById("myImage").src = await loadImgURL("QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE", "image/png", 524288);
}
setImage();
</script>
</body>
The big advantage of this is you're using the IPFS network itself, and not relying on a public HTTP gateway (the recommended way).
You can do something like that:
tokenURI.replace("ipfs://", "https://ipfs.io/ipfs/");
One thing to note here about fetching images from IPFS that I think isn't being discussed sufficiently in these answers is that you will need to either
Run your own node of IPFS, or
Get a hosted IPFS node through a service like Infura
I have spent a little bit of time working through this in the last couple of days, and it will always come back to you having to have direct access to your own node.
There are "Gateways," which are nodes hosted by the community, and you can read more about them in the IPFS docs here: https://docs.ipfs.io/concepts/ipfs-gateway/#limitations-and-potential-workarounds
The thing with the gateways is that they are not meant to be relied upon for production sites, as you can see below. It's possible that there is some hosted node out there that somebody is giving out for free, but I doubt it, and you wouldn't want to rely on that anyways.
I think that other questions above have elaborated how you actually process the responses once you get it, but I wanted to cover this extra ground in my answer.
ipfs docs
let imgUrl = url?.slice(url.indexOf(":"),url?.lastIndexOf("/"));
let slice = url?.slice(url.lastIndexOf("/"),url?.length)
let renderURL = `https${imgUrl}.ipfs.dweb.link${slice}`;
console.log(renderURL);
Help me please, how i can translate text "Drop an image here" in upload pop-up for my language?(for example ru_RU)? Buttons upload, browse for an image - translated with such solution:
tinymce.i18n.data.uk_UA['Upload'] = 'My text';
But "Drop an image here" can't(
this text from tinymce.js
define(
'tinymce.core.ui.DropZone',
[
'tinymce.core.ui.Widget',
'tinymce.core.util.Tools',
'tinymce.core.ui.DomUtils',
'global!RegExp'
],
function (Widget, Tools, DomUtils, RegExp) {
return Widget.extend({
/**
* Constructs a instance with the specified settings.
*
* #constructor
* #param {Object} settings Name/value object with settings.
* #setting {Boolean} multiple True if the dropzone is a multiple control.
* #setting {Number} maxLength Max length for the dropzone.
* #setting {Number} size Size of the dropzone in characters.
*/
init: function (settings) {
var self = this;
settings = Tools.extend({
height: 100,
text: "Drop an image here",
multiple: false,
accept: null // by default accept any files
}, settings);
self._super(settings);
self.classes.add('dropzone');
if (settings.multiple) {
self.classes.add('multiple');
}
},
To translate the text you need to modify the language file for the language(s) you wish to modify. If I download the current language file for uk_UA I see these two strings on lines 55 and 57
You need to change the right side of these two string to whatever you want them to be in each language.
Note: When we add new features to TinyMCE it often takes the community some time to translate the new strings in all the languages we support. We always welcome assistance with the translation process: https://www.transifex.com/moxiecode/tinymce/
if you did write and you want to translate it using some library you can use these i think it will help unless like the previous response check the controle constructor
https://github.com/muaz-khan/Translator ||
https://www.npmjs.com/package/google-translate-api
With relation to Exception "The disk is full " is thrown when trying to store data in usedata object in IE7+ which has been left unanswered:
I am heavily browsing a government website created with Oracle ADF using WatiN.
The website is located in a WPF window --> WindowsFormsHost --> WebBrowser control.
The website makes heavy use of this: http://msdn.microsoft.com/en-us/library/ie/ms531424(v=vs.85).aspx, via the save and load methods.
After 2-3 minutes of browsing, I get the following javascript error during one of the "save" calls:
The disk is full, character #, line ####.
When I get this error, the WebBrowser control is rendered completely useless (no further javascript commands can be executed) and my app must be restarted.
I have tried to clear browser cache, change it's location, clear localStorage, everything to no avail.
The PC that reproduces the error has IE10 installed, but via the registry I force IE8 / IE9 mode in the webbrowser control.
Is there any way to get around this problem?
Information on this is very scarce, so any help will be greatly appreciated.
I'm on linux, so no way to test this now, but the files in question are not stored in browser cache, but in
Note: As of IE 10 this no longer holds water. Ref. edit 2 below.
W7+: %HOMEPATH%\AppData\Roaming\Microsoft\Internet Explorer\UserData
# c:\users\*user-name*\...
XP : %HOMEPATH%\Application Data\Microsoft\Internet Explorer\UserData
# c:\Documents and Settings\*user-name*\...
Or, I guess, this one also work (as a short-cut), :
%APPDATA%\Roaming\Microsoft\Internet Explorer\UserData
Modify or delete the files there.
Note that the files are tagged as protected operating system files, so to view in Explorer you have to change view to include these. If you use cmd, as in Command Prompt you have to include the /a flag as in:
dir /a
Edit 1:
Note, that index.dat is the one holding information about allocated size etc. so it won't (probably) help to only delete/move the xml files.
Edit 2:
OK. Had a look at this in Windows 7 running IE 10.
In IE 7 (on XP) the above mentioned path have an index.dat file that gets updated on save by userData. The file holds various information such as size of the index file, number of sub folders, size of all files. Then an entry for each file with a number identifying folder, url where it was saved from, name of xml file, dates etc. Wrote a simple VBScript parser for this, but as IE 10 does not use the index.dat file it is a waste.
Under IE 10 there is no longer various index.dat files but a central database file in:
%APPDATA%\Local\Microsoft\Windows\WebCache\
On my system the database file is named WebCacheV01.dat, the V part seems to differ between systems and is perhaps an in-house version number rather then a file type version.
The files are tightly locked, and as such, if one want to poke at them one solution is to make a shadow copy by using tools such as vscsc, Shadowcopy etc.
Anyhow, hacking WebCacheVxx.dat would need a lot more work, so no attempts on that on my part (for now at least).
But, register that the file gets an entry with path to the old location – so e.g. on write of someElement.save("someStorageName");, WebCacheVxx.dat gets an entry like:
...\AppData\Roaming\Microsoft\Internet Explorer\UserData\DDFFGGHH\someStorageName[1].xml
and a corresponding file is created in the above path.
The local container.dat, however, is not updated.
userData
As for the issue at hand, clearing localStorage will not help, as userData is not part of that API.
Can not find a good example on how to clear userData. Though, one way is to use the console.
Example from testing on this page:
Save some text.
Hit F12 and enter the following to clear the data:
/* ud as an acronym for userData */
var i, at,
ud_name = "oXMLBranch",
ud_id = "oPersistText",
ud = document.getElementById(ud_id);
/* To modify the storage one have to ensure it is loaded. */
ud.load(ud_name);
/* After load, ud should have a xmlDocument where first child should hold
* the attributes for the storage. Attributes as in named entries.
*
* Example: ud.setAttribute("someText", "Some text");
* ud.save(ud_name);
*
* XML-document now has attribute "someText" with value "Some text".
*/
at = ud.xmlDocument.firstChild.attributes;
/* Loop attributes and remove each one from userData. */
for (i = 0; i < at.length; ++i)
ud.removeAttribute(at[i].nodeName);
/* Finally update the file by saving the storage. */
ud.save(ud_name);
Or as a one-liner:
var ud_name = "oXMLBranch", ud_id = "oPersistText", i, at, ud = document.getElementById(ud_id); ud.load(ud_name); at = ud.xmlDocument.firstChild.attributes; for (i = 0; i < at.length; ++i) ud.removeAttribute(at[i].nodeName); ud.save(ud_name);
Eliminating one restriction
There are some issues with this. We can eliminate at least one, by ignoring the ud_id and instead create a new DOM object:
var i, at,
ud_name = "oXMLBranch",
ud = document.createElement('INPUT');
/* Needed to extend properties of input to include userData to userdata. */
ud.style.behavior = 'url(#default#userdata)';
/* Needed to not get access denied. */
document.body.appendChild(ud);
ud.load(ud_name);
at = ud.xmlDocument.firstChild.attributes;
for (i = 0; i < at.length; ++i)
ud.removeAttribute(at[i].nodeName);
/* Save, or nothing is changed on disk. */
ud.save(ud_name);
/* Clean up the DOM tree */
ud.parentNode.removeChild(ud);
So by this one should be able to clear userData by knowing name of the storage, which should be same as the file name (excluding [1].xml) or by looking at the page source.
More issues
Testing on the page mentioned above I reach a disk is full limit at 65,506 bytes.
Your problem is likely not that the disk is full, but that a write attempt is done where input data is above limit. You could try to clear the data as mentioned above and see if it continues, else you would need to clear the data about to be written.
Then again this would most likely break the application in question.
In other words, error text should have been something like:
Write of NNN bytes is above limit of NNN and not disk is full.
Tested by attaching to window onerror but unfortunately source of error was not found:
var x1, x2, x3, x4 ;
window.onerror = function () {
x1 = window.event;
x2 = x1.fromElement; // Yield null
x3 = x1.srcElement; // Yield null
x4 = x1.type;
};
End note
Unless the clear userData method solves the issue, I do not know where to go next. Have not found any option to increase the limit by registry or other means.
But perhaps it get you a little further.
There might be someone over at Super User that is able to help.
As many of you will be aware, Google offers an API whereby you can load particular modules/libraries by calling a simple function:
<script type="text/javascript" src="//www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.7.1");
google.load("jqueryui", "1.8.2");
</script>
I am currently in the process of developing my own library of code of which I would like to distribute amongst my websites easily and efficiently and I cannot think of a better method than the one above.
However, I am not too sure what the best way of writing the code for this is. Obviously my library will be an object, so will start with something like this (I think, correct me if I am wrong):
function company(){
this.load = function(modules){
// Modules is an array of modules to load
// Load the separate modules here
// from external files in their minified format
}
}
var company = new company;
company.load(['forms']);
Is the above method the right way to go? How do I then load in the modules from separate files?
You could go with the CommonJS Module spec. Then you can load them with RequireJS.
After searching around and gaining experience from others, I figured the following was the best method. Others may disagree, feel free to comment
/**
* Sine Macula Javascript API
* The Sine Macula API contains all base functions for use throughout
* all websites
* #name class.sinemacula.js
* #author Ben Carey
* #version 1.0
* #date 25/10/2012
* #copyright (c) 2012 Sine Macula Limited (sinemaculammviii.com)
*/
function SineMacula(){
// Only proceed if jQuery has been loaded
if(typeof jQuery=='undefined'){
// jQuery has not been loaded
console.log('jQuery has not been loaded');
}else{
/**
* Sine Macula Load
* Load the Sine Macula Libraries and Plugins
* into the current document
*
* The options:
* - package: the package of libraries to load
* - packageURL: a remote source to load the package details from
* - libraries: any additional libraries to load
*
* #param object options The options for the Sine Macula load
*/
this.load = function(options){
var url,query,script;
// Set the defaults for the loader
var options = $.extend({
package: 'none', // Do not load any packages by default
packageURL: false, // Do not retrieve the package details from a URL by default
libraries: [] // Do not load any libraries by default
},options);
// Build the query based on the parameters supplied
if(options.packageURL){
// Build the query to allow for a remote
// package definition
query = '?packageURL='+encodeURIComponent(options.packageURL);
}else if(options.package=='none'){
query = '?libraries='+encodeURIComponent(options.libraries.join());
}else{
query = encodeURIComponent(options.package)+'/?libraries='+encodeURIComponent(options.libraries.join());
}
// Complete the url by appending the query
url = '//libraries.sinemaculammviii.com/'+query;
// Append the script tag to the end of the document
script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
$('head')[0].appendChild(script);
}
}
};