Update:
Please see the answer noted below as, ultimately, the problem had nothing to do with jsquery.
=============
Issue:
I submit an object to jquery to convert into a serialized string that will become part of a "POST" request to a server, and the data returned from the serialization request is different than the data sent on many occasions.
An example:
The JavaScript code that implements the server POST request:
function send_data(gpg_data) {
var query_string;
query_string = '?' + $.param(gpg_data, traditional = true);
console.log('gpg_data =', gpg_data)
console.log('query_string =', query_string);
$.post(server_address + query_string);
return;
}
This is the structure sent to the jquery param() function.
(copied from the browser console in developer mode.)
gpg_data =
{controller_status: 'Connected', motion_state: 'Stopped', angle_dir: 'Stopped', time_stamp: 21442, x_axis: 0, …}
angle_dir: "Stopped"
controller_status: "Connected"
force: 0
head_enable: 0
head_x_axis: 0
head_y_axis: 0
motion_state: "Stopped"
time_stamp: 21490
trigger_1: 0
trigger_2: 0
x_axis: 0
y_axis: "0.00"
. . . and the returned "query string" was:
query_string = ?controller_status=Connected&motion_state=Stopped&angle_dir=Stopped&time_stamp=21282&x_axis=0&y_axis=0.00&head_x_axis=0&head_y_axis=0&force=0&trigger_1=1&trigger_2=1&head_enable=0
The data received by the server is:
ImmutableMultiDict([('controller_status', 'Connected'), ('motion_state', 'Stopped'), ('angle_dir', 'Stopped'), ('time_stamp', '21282'), ('x_axis', '0'), ('y_axis', '0.00'), ('head_x_axis', '0'), ('head_y_axis', '0'), ('force', '0'), ('trigger_1', '1'), ('trigger_2', '1'), ('head_enable', '0')])
For example, note that "trigger_1" returns 1 when the data sent to it is a zero.
I have tried setting the query to "traditional = true" to revert to an earlier style of query handling as some articles suggested - which did not work. I tried this with jquery 3.2 and 3.6.
I am not sure exactly how jquery manages to munge the data so I have no idea where to look.
I have looked at my script and at the unpacked jquery code, and I can make no sense out of why or how it does what it does.
Any help understanding this would be appreciated.
P.S.
web searches on "troubleshooting jquery" returned very complex replies that had more to do with editing e-commerce web pages with fancy buttons and logins than with simply serializing data.
P.P.S.
I am tempted to just chuck the jquery and write my own serialization routine. (grrrr!)
===================
Update:
As requested, a link to the browser-side context.
To run: unpack the zip file in a folder somewhere and attach an analog joystick/gamepad to any USB port, then launch index.html in a local browser. Note that a purely digital gamepad - with buttons only or with a joystick that acts like four buttons - won't work.
You will want to try moving joystick axes 1 and 2, (programmatically axes 0 and 1) and use the first (0th) trigger button.
You will get a zillion CORS errors and it will complain bitterly that it cannot reach the server, but the server side context requires a GoPiGo-3 robot running GoPiGo O/S 3.0.1, so I did not include it.
Note: This does not work in Firefox as Firefox absolutely requires a "secure context" to use the Gamepad API. It does work in the current version of Chrome, (Version 97.0.4692.99 (Official Build) (64-bit)), but throws warnings about requiring a secure context.
Please also note that I have made every attempt I know how to try to troubleshoot the offending JavaScript, but trying to debug code that depends on real-time event handling in a browser is something I have not figured out how to do - despite continuous searching and efforts. Any advice on how to do this would be appreciated!
======================
Update:
Researching debugging JavaScript in Chrome disclosed an interesting tidbit:
Including the line // #ts-check as the first line in the JavaScript code turns on additional "linting" (?) or other checks that, (mostly) were a question of adding "var" to the beginning of variable declarations.
However. . . .
There was one comment it made:
gopigo3_joystick.x_axis = Number.parseFloat((jsdata.axes[0]).toFixed(2));
gopigo3_joystick.y_axis = Number.parseFloat(jsdata.axes[1]).toFixed(2);
I could not assign gopigo3_joystick.y_axis to a string object, (or something like that), and I was scratching my head - that was one of the pesky problems I was trying to solve!
If you look closely at that second line, you will notice I forgot a pair of parenthesis, and that second line should look like this:
gopigo3_joystick.y_axis = Number.parseFloat((jsdata.axes[1]).toFixed(2));
Problem solved - at least with respect to that problem.
I figured it out and it had nothing to do with jquery.
Apparently two things are true:
The state of the gpg_data object's structure is "computed", (snapshot taken), the first time the JavaScript engine sees the structure and that is the state that is saved, (even though the value may change later on). In other words, that value is likely totally bogus.
Note: This may only be true for Chrome. Previous experiments with Firefox showed that these structures were updated each time they were encountered and the values seen in the console were valid. Since Firefox now absolutely requires a secure context to use the gamepad API, I could not use Firefox for debugging.
I was trying to be "too clever". Given the following code snippet:
function is_something_happening(old_time, gopigo3_joystick) {
if (gopigo3_joystick.trigger_1 == 1 || gopigo3_joystick.head_enable == 1) {
if (old_time != Number.parseFloat((gopigo3_joystick.time_stamp).toFixed(0))) {
send_data(gopigo3_joystick)
old_time = gopigo3_joystick.time_stamp
}
}
return;
}
The idea behind this particular construction was to determine if "something interesting" is happening, where "something interesting" is defined as:
A keypress, (handled separately)
A joystick movement if either the primary trigger or the pinky trigger is pressed.
Movement without any trigger pressed is ignored so that if the user accidentally bumps against the joystick, the robot doesn't go running around.
Therefore the joystick data only gets updated if the trigger is pressed. In other words, trigger "release" events - the trigger is now = 0 - are not recorded.
The combination of these two events - Chrome taking a "snapshot" of object variables once and once only, (or not keeping them current) - and the trigger value persisting, lead me to believe that jquery was the problem since the values appeared to be different on each side of the jquery call.
I'm having difficulties to add an HyperLink to my Word Document using the Javascript API. I've look to Doc and I can't find any hints how to accomplish my duty...
Here is my Question: What is the best way to add an HyperLink inside a Word Document using the Javascript API.
And Here is what I tried:
Word.run((context: Word.RequestContext) => {
var range = context.document.getSelection();
context.load(range, "hyperlink");
return context.sync().then(() => {
range.font.highlightColor = '#FFFF00';
range.hyperlink = "C:\My Documents\MyFile.doc";
}).then(context.sync);
});
I've added the highlightColor just to have a visual that my changes are being sync. Everything seems fine but the Hyperlink property is not being updated. Am I missing something?
And If you guys are wondering what's this syntax, I'm using TypeScript.
Good, if you don't mind i will reply in JavaScript :)
Setting a hyperlink to a file must work (provided that the file exists :) ). I have this simplified example working successfully, btw you don't need to load the range for setting this.
Also hyperlinks is now supported as preview, so please make sure that you are running an updated (latest) version of Word (go file and install updates) and most importantly make sure you are using the preview CDN for Office.js which is here: https://appsforoffice.microsoft.com/lib/beta/hosted/office.js
Word.run(function(context) {
// Insert your code here. For example:
context.document.getSelection().hyperlink = "C:\My Documents\MyFile.doc";
return context.sync();
});
I'm looking for a simple solution to record audio file and upload it to s3.
My web searches come up to find:
WebRTC-Experiment which is the most popuplar solution i could find.
it also have a working example in the following link : https://www.webrtc-experiment.com/RecordRTC/
I also found ngCamRecorder which wasn't supported by firefox yet.
I'm looking for a simple solution + working example, and suggestion.
Which solution is most popuplar to use with AngularJS?
if you can provide your own example or link to a working example that i can use.
if you also used S3 i would like to know how you can push the file to S3, and get the link to the controller.
The solution i found, throw error, and include a working example without the code itself explained.
I also would like to know how to push it to s3.
This is the code i implemented from the example:
$scope.start_recording = function()
{
navigator.getUserMedia(session, function (mediaStream) {
window.recordRTC = RecordRTC(MediaStream);
recordRTC.startRecording();
}, function(error){console.log(error)});
};
$scope.stop_recording = function()
{
navigator.getUserMedia({audio: true}, function(mediaStream) {
window.recordRTC = RecordRTC(MediaStream);
recordRTC.startRecording();
});
};
It simply throw an error: undefined is not a function on recordrtc.js line 641
if(!mediaStream.getAudioTracks().length) throw 'Your stream has no audio tracks.';
obviously mediaStrem is null.
Thanks.
There's an AngularJS wrapper for this, it's a simple directive that supports HTML5 (RecorderJS), Cordova Media and Flash.
Usage is straightforward
<ng-audio-recorder audio-model="someModel" auto-start="false">
<!-- controls -->
<button ng-click='recorder.startRecording()'>Start</button>
<button ng-click='recorder.stopRecording()'>Stop</button>
</ng-audio-recorder>
You can see the full usage here:
https://github.com/logbon72/angular-recorder
I got the same issue and figured it out. The function argument in the success function of navigation.getUserMedia() is supposed to be "MediaStream" instead of "mediaStream".
Is it possible to detect if the user is accessing through the browser or application using JavaScript?
I'm developing a hybrid application to several mobile OS through a web page and a PhoneGap application and the goal would be to:
Use the same code independently of the deployment target
Add PhoneGap.js file only when the user agent is an application
You could check if the current URL contains http protocol.
var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
if ( app ) {
// PhoneGap application
} else {
// Web page
}
Quick solution comes to mind is,
onDeviceReady
shall help you. As this JS call is invoked only by the Native bridge (objC or Java), the safari mobile browser will fail to detect this. So your on device app(phone gap) source base will initiate from onDeviceReady.
And if any of the Phonegap's JS calls like Device.platform or Device.name is NaN or null then its obviously a mobile web call.
Please check and let me know the results.
I figured out a way to do this and not rely on deviceready events thus, keeping the web codebase intact...
The current problem with using the built in deviceready event, is that when the page is loaded, you have no way of telling the app: "Hey this is NOT running on an mobile device, there's no need to wait for the device to be ready to start".
1.- In the native portion of the code, for example for iOS, in MainViewController.m there's a method viewDidLoad, I am sending a javascript variable that I later check for in the web code, if that variable is around, I will wait to start the code for my page until everything is ready (for example, navigator geolocation)
Under MainViewController.m:
- (void) viewDidLoad
{
[super viewDidLoad];
NSString* jsString = [NSString stringWithFormat:#"isAppNative = true;"];
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
}
2.- index.html the code goes like this:
function onBodyLoad()
{
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady(){;
myApp.run();
}
try{
if(isAppNative!=undefined);
}catch(err){
$(document).ready(function(){
myApp.run();
});
}
PhoneGap has window.PhoneGap (or in Cordova, it's window.cordova or window.Cordova) object set. Check whether that object exists and do the magic.
Inside the native call where the url for the phonegap app is loaded you add a parameter target with value phonegap. So the call for android becomes something like this.
super.loadUrl("file:///android_asset/www/index.html?target=phonegap");
Your website using this code won't be called with the extra parameter, so we now have something different between the two deploying platforms.
Inside the javascript we check if the parameter exists and if so we add the script tag for phonegap/cordova.
var urlVars = window.location.href.split('?');
if(urlVars.length > 1 && urlVars[1].search('target=phonegap') != -1){
//phonegap was used for the call
$('head').append('<script src="cordova.js"></script>');
}
A small caveat: this method requires to change the call to index.html in phonegap for each different targeted mobile platform. I am unfamiliar where to do this for most platforms.
what if you try following :
if(window._cordovaNative) {
alert("loading cordova");
requirejs(["...path/to/cordova.js"], function () {
alert("Finished loading cordova");
});
}
I am using the same code for both phonegap app and our web client. Here is the code that I use to detect if phonegap is available:
window.phonegap = false;
$.getScript("cordova-1.7.0.js", function(){
window.phonegap = true;
});
Keep in mind that phonegap js file is loaded asynchronously. You can load it synchronously by setting the correct option of a nifty jquery $.getScript function.
Note that approach does make an extra GET request to grab phonegap js file even in your webclient. In my case, it did not affect the performance of my webclient; so it ended up being a nice/clean way to do this.Well at least until someone else finds a quick one-line solution :)
It sounds like you are loading another webpage once the webview starts in the Phonegap app, is that correct? If that's true then you could add a param to the request url based on configuration.
For example, assuming PHP,
App.Config = {
target: "phonegap"
};
<body onload="onbodyload()">
var onbodyload = function () {
var target = App.Config.target;
document.location = "/home?target=" + target;
};
Then on the server side, include the phonegap js if the target is phonegap.
There is no way to detect the difference using the user agent.
The way I'm doing it with is using a global variable that is overwritten by a browser-only version of cordova.js. In your main html file (usually index.html) I have the following scripts that are order-dependent:
<script>
var __cordovaRunningOnBrowser__ = false
</script>
<script src="cordova.js"></script> <!-- must be included after __cordovaRunningOnBrowser__ is initialized -->
<script src="index.js"></script> <!-- must be included after cordova.js so that __cordovaRunningOnBrowser__ is set correctly -->
And inside cordova.js I have simply:
__cordovaRunningOnBrowser__ = true
When building for a mobile device, the cordova.js will not be used (and instead the platform-specific cordova.js file will be used), so this method has the benefit of being 100% correct regardless of protocols, userAgents, or library variables (which may change). There may be other things I should include in cordova.js, but I don't know what they are yet.
Ive ben struggling with this aswell, and i know this is an old thread, but i havent seen my approach anywhere, so thought id share incase itll help someone.
i set a custom useragent after the actual useragent :
String useragent = settings.getUserAgentString();
settings.setUserAgentString(useragent + ";phonegap");
that just adds the phonegap string so other sites relying on detecting your mobile useragent still works.
Then you can load phonegap like this:
if( /phonegap/i.test(navigator.userAgent) )
{
//you are on a phonegap app, $getScript etc
} else {
alert("not phonegap");
}
To my mind you try to make issue for self. You didn't mentioned your development platform but most of them have different deployment configuration. You can define two configurations. And set variable that indicates in which way code was deployed.
In this case you don't need to care about devices where you deployed your app.
Short and effective:
if (document.location.protocol == 'file:') { //Phonegap is present }
Similar to B T's solution, but simpler:
I have an empty cordova.js in my www folder, which gets overwritten by Cordova when building. Don't forget to include cordova.js before your app script file (it took my one hour to find out that I had them in wrong order...).
You can then check for the Cordova object:
document.addEventListener('DOMContentLoaded', function(){
if (window.Cordova) {
document.addEventListener('DeviceReady', bootstrap);
} else {
bootstrap();
}
});
function bootstrap() {
do_something()
}
New solution:
var isPhoneGapWebView = location.href.match(/^file:/); // returns true for PhoneGap app
Old solution:
Use jQuery, run like this
$(document).ready(function(){
alert(window.innerHeight);
});
Take iPhone as example for your mobile application,
When using PhoneGap or Cordova, you'll get 460px of WebView, but in safari, you'll lose some height because of browser's default header and footer.
If window.innerHeight is equal to 460, you can load phonegap.js, and call onDeviceReady function
Nobody mentioned this yet, but it seems Cordova now supports adding the browser as a platform:
cordova platforms add browser
This will automatically add cordova.js during run-time, which features the onDeviceReady event, so that you do not need to fake it. Also, many plugins have browser support, so no more browser hacks in your code.
To use your app in the browser, you should use cordova run browser. If you want to deploy it, you can do so using the same commands as the other platforms.
EDIT: forgot to mention my source.
Solution: Patch index.html in Cordova and add cordova-platform="android" to <html> tag, so that cordova-platform attribute will be only present in Cordova build and missing from original index.html used for web outside of Cordova.
Pros: Not rely on user agent, url schema or cordova API. Does not need to wait for deviceready event. Can be extended in various ways, for example cordova-platform="browser" may be included or not, in order to distinguish between web app outside of Cordova with Cordova's browser platform build.
Merge with config.xml
<platform name="android">
<hook src="scripts/patch-android-index.js" type="after_prepare" />
</platform>
Add file scripts/patch-android-index.js
module.exports = function(ctx) {
var fs = ctx.requireCordovaModule('fs');
var path = ctx.requireCordovaModule('path');
var platformRoot = path.join(ctx.opts.projectRoot, 'platforms/android');
var indexPath = platformRoot + '/app/src/main/assets/www/index.html';
var indexSource = fs.readFileSync(indexPath, 'utf-8');
indexSource = indexSource.replace('<html', '<html cordova-platform="android"');
fs.writeFileSync(indexPath, indexSource, 'utf-8');
}
Notes: For other than android, the paths platforms/android and /app/src/main/assets/www/index.html should be adjusted.
App can check for cordova-platform with
if (! document.documentElement.getAttribute('cordova-platform')) {
// Not in Cordova
}
or
if (document.documentElement.getAttribute('cordova-platform') === 'android') {
// Cordova, Android
}
I've been using swfobject for a recent project, and its great. But now that I've managed to get FlashSwitcher up and running in Firefox I notice that when I'm running Flash Player 7 the info displayed when I am running a version lower than I've specified has been customised (in this case by the Moodle page the the swfobject embed code sits in). Attached is a screenshot of that output SWF, as generated by Moodle. I can confirm that some of my users also see this, so my FlashSwitcher is functioning correctly.
Most of my use cases are outside of the Moodle context, they're standalone, what I'm after is exactly how they customised it, how I can change their customisation, and how I can do the same when the swfobject detection is standalone.
Please note that enforcing the user to upgrade their Flash Player plugin via ExpressInstall has been frowned upon by the client, they want suggestive actions and a link - but no auto installs or similar.
My implementation uses the 'twice cooked' method as I have an accessibility requirement to show non-Flash content should a user have neither Flash, Javascript or both. Here's my embed method call, which executes when a YUI2 document load event fires:
swfobject.embedSWF("../../swf/video-loader.swf", "flash_object_a", "877", "400", "8.0");
Ultimately I want to customise this "old version" output to be something I've created/written.
cheers,
d
You can use swfobject's getFlashPlayerVersion method (explained here) to check for Flash Player version and take appropriate action.
A simple example would be:
var has_version_8_or_greater = swfobject.hasFlashPlayerVersion("8");
if(has_version_8_or_greater){
//embed SWF using SWFObject
} else {
//Check to see whether an older version of Flash is found.
var version = swfobject.getFlashPlayerVersion();
if(version.major > 0){
//You have Flash but it's too old.
var version_str = version.major + "." + version.minor + "." + version.release;
alert("You have Flash Player version " + version_str + ". Please update!");
} else {
//You don't have Flash.
}
}