I'm using THREE.js scenes and graphic objects on my webpage. I know, at the least, THREE.js utilizes WebGL.
I'd like to utilize Modernizr to check the current browser for compatability with WebGL and, if the browser doesn't have it, prompt a message to the user.
When selecting the browser features to have Modernizr test for, I see two features that relate to my goal
WebGL: Detects for WebGL in the browser.
WebGl Extentions: Detects support for OpenGL extensions in WebGL. It's true if the WebGL extensions API is supported, then exposes the supported extensions as subproperties, e.g.:
So in order for THREE.js to work, do I need to test for WebGL Extentions and WebGL or simply just WebGL?
It depends whether you're using features that require extensions. Three.js itself doesn't need any extensions. Certain things like shadows probably run faster if you WEBGL_depth_texture extension.
If you don't know what extensions you personally need consider inserting some code to hide them and see if your app still runs
Example:
// disable all extensions
WebGLRenderingContext.prototype.getExtension = function() {
return null;
}
WebGLRenderingContext.prototype.getSupportedExtensions = function() {
return [];
}
// now init three.js
If you want to allow specific extensions you could do something like this
var allowedExtensions = [
"webgl_depth_texture",
"oes_texture_float",
];
WebGLRenderingContext.prototype.getExtension = function(origFn) {
return function(name) {
if (allowedExtensions.indexOf(name.ToLowerCase()) >= 0) {
return origFn.call(this, name);
}
return null;
};
}(WebGLRenderingContext.prototype.getExtension);
WebGLRenderingContext.prototype.getSupportedExtensions = function(origFn) {
return function() {
return origFn.call(this).filter(function(name) {
return allowedExtensions.indexOf(n) >= 0;
});
};
}(WebGLRenderingContext.prototype.getSupportedExtensions);
Related
Javascript:
I want my Windows Store app to check for updates, especially mandatory ones, and then prompt the user to update.
I have found out this involves Windows.Services.Store, but I cannot find any javascript examples of how this is done, only the usual c#/vb ones.
Does anyone know of a code template?
I have found out this involves Windows.Services.Store, but I cannot find any javascript examples of how this is done, only the usual c#/vb ones.
I'd suppose the examples you've found are Code examples in Download and install package updates for your app. Although, these examples are written with C#, but we can convert them to JavaScript easily as most of them are Windows Runtime APIs.
Using Download and install all package updates for example, the JavaScript version would like the following:
var context = Windows.Services.Store.StoreContext.getDefault();
context.getAppAndOptionalStorePackageUpdatesAsync().then(function (updates) {
if (updates.size > 0) {
var dialog = new Windows.UI.Popups.MessageDialog("Download and install updates now? This may cause the application to exit.", "Download and Install?");
dialog.commands.append(new Windows.UI.Popups.UICommand("Yes"));
dialog.commands.append(new Windows.UI.Popups.UICommand("No"));
dialog.showAsync().then(function (command) {
if (command.label === "Yes") {
context.requestDownloadAndInstallStorePackageUpdatesAsync(updates).then(function (result) {
// TODO
}, function (error) {
//TODO
}, function (progress) {
var downloadProgressBar = document.getElementById("downloadProgressBar");
downloadProgressBar.value = progress.packageDownloadProgress;
});
}
});
}
});
Two major differences between C# and JavaScript version here are casing conventions and asynchronous methods. For more info, please see Using the Windows Runtime in JavaScript.
I am using console.log() and console.dir() statements in 3 places in my 780 lines of code JS script. But all of them are useful for debugging and discovering problems that might appear when using the application.
I have a function that prints internal application's state i.e current value of variables:
printData: function () {
var props = {
operation: this.operation,
operand: this.operand,
operandStr: this.operandStr,
memory: this.memory,
result: this.result,
digitsField: this.digitsField,
dgField: this.dgField,
operationField: this.operationField,
opField: this.opField
};
console.dir(props);
}
I also have a list of immutable "contants" which are hidden with closure but I can print them with accessor method called list(); in console.
Something like this:
list: function () {
var index = 0,
newStr = "",
constant = '';
for (constant in constants) {
if (constants.hasOwnProperty(constant)) {
index = constant.indexOf('_');
newStr = constant.substr(index + 1);
console.log(newStr + ": " + constants[constant]);
}
}
}
The third place where I use console in debugging purposes is in my init(); function, where I print exception error if it happens.
init: function (config) {
try {
this.memoryLabelField = global.getElementById(MEMORY_LABEL);
this.digitsField = global.getElementById(DIGITS_FIELD);
this.digitsField.value = '0';
this.operationField = global.getElementById(OPERATION_FIELD);
this.operationField.value = '';
return this;
} catch (error) {
console.log(error.message);
return error.message;
}
}
As my question states, should I keep these console statements in production code?
But they come very useful for later maintenance of the code.
Let me know your thoughts.
Since these are not persistent logs you won't get much benefit out of them. Also it runs on every individuals machine since everyone has their own copy of the program. If you really need it, it would be better to have a variable that can toggle this feature. Espcially if you are targetting to debug a whole lot of pre-determined stuffs.
Client Side issues needs to be debugged slightly different from Server Side. Everyone has their own copy of the program. Browser-JS is run on client side you open the browser and all code that you wrote is with you in a full blown repl and debugging is easy compared to Server side where most likely you wouldn't have access to that system. It is so flexible that you could just override it when you are checking something in production right from your own browser without affecting anyone. Just override it with those console statements and debug the issue.
Its a good idea to have logs in Server side programming. It gives a lot of useful information and is persistent.
As said above, debugging code should not be present on a production environment.
However, if you plan to keep it anyway, keep in mind that all browsers do not support it.
So you may check its availability and provide a fallback:
if (typeof window.console === 'undefined')
{
window.console = {};
}
if (typeof window.console.log === 'undefined')
{
window.console.log = function() { };
}
According to mozilla developer network
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.
Leaving console.log() on production sites can cause issues since it is not supported by older browsers. It is most likely to throw exceptions in that case.
It's historically considered a bad-practice by Javascript programmers. At the start of the eons, some browsers didn't have support for it (IE8 or less for example). Other thing to take in mind is that you are making your code larger to download.
Working on a small engine to run my HTML5 test games, using it as a great way to get deeper into Javascript and have fun at the same time. Succeeding, btw.
However, I just found this cool little script called PreloadJS ( http://www.createjs.com/#!/PreloadJS ). Also using John Resig's classical inheritence class JS. Very cool, enjoying it. I am attempting to use PreloadJS to pull in all of my engine files...but I seem to be having an issue. Here's the code I'm using (keeping it simple on purpose):
var ScriptLoader = Class.extend({ // Want to add functionality to this to allow PHP or inline loading...perhaps later
init: function() {
this.fileList = [
'Empty.js',
'./engine/Scene.js'
];
this.preload;
},
loadProjectSource: function(directory) {
if (this.preload != null) { this.preload.close(); }
this.preload = new createjs.LoadQueue();
this.preload.addEventListener("fileload", this.fileLoaded);
this.preload.addEventListener("error", this.fileError);
this.preload.setMaxConnections(5);
this.loadAnother();
},
loadAnother: function() {
var item = this.fileList.shift();
if(this.fileList.length != 0) {
this.preload.loadFile(item);
}
},
fileLoaded: function(e) {
debug('Loaded ' + e.item.src);
this.loadAnother();
},
fileError: function(e) {
debug('Error ' + e.item.src);
}
}
From my engine instantiation, I'm calling ScriptLoader.loadProjectSource. It's doing nothing but throwing errors, and the documentation on error handling (and loading JS files in general...) is very sparse on the PreloadJS site. It focuses on preloading images (which, admittedly, looks great). Anyway, so yea, it's throwing errors. And it can't be the files, as I tried loading a completely blank JS file (as you can see). Still throwing an error on the Empty.js file.
Annoyed :) Thanks in advance.
The PreloadJS script uses XHR where available with browser support. In order for this to function correctly with locally-hosted scripts, a local webserver must be running. Upon activating my local webserver and attempting the same operation, full success.
We have inhouse library which uses canvas for displaying charts in my application. And dojo as scripting language.Everything is fine, but my charts are not appearing in IE8.
I google about this, and found that there is some VML issue in IE8.
I found this:
var printChart = function(time, freq){
if (!document.namespaces['g_vml_']) {
document.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml', '#default#VML');
}
if (!document.namespaces['g_o_']) {
document.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office', '#default#VML');
}
if (freq === undefined) {
this.freq = "1mi";
}
if (time === undefined) {
this.time = "1dy";
}
self.reload();
}
Now I was trying to add this in my DOJO code and that is creating problem.
As when I do document.namespace I get firebug error 'document.namespaces is undefined'.
Q: How can we fix this, are the any better alternative approaches for the same, basic problem am having is browser related, charts are rendered properly on other browsers but not on IE8, any suggestions ?
Update:
What are ways to deal with such cross browser issue ?
Regarding the cross-browser issues you mentioned, there are basically two ways: browser sniffing and object detection. Browser sniffing is to detect the browser vendor and version. For example, you can know that the browser is IE 8 or Firefox 4.0 from the navigator object. Object detection is to test whether a object/function is available on the browser before actually using it.
For the problem you have here, you can use the two approaches. For example, you can sniff the browser using dojo.isIE.
if (dojo.isIE == 8) {
//Your code to add the namespace
}
Or you can use:
if (document.namespaces) {
// Your code to add the namespace
}
I wanted some of those spiffy rounded corners for a web project that I'm currently working on.
I thought I'd try to accomplish it using javascript and not CSS in an effort to keep the requests for image files to a minimum (yes, I know that it's possible to combine all required rounded corner shapes into one image) and I also wanted to be able to change the background color pretty much on the fly.
I already utilize jQuery so I looked at the excellent rounded corners plugin and it worked like a charm in every browser I tried. Being a developer however I noticed the opportunity to make it a bit more efficient. The script already includes code for detecting if the current browser supports webkit rounded corners (safari based browsers). If so it uses raw CSS instead of creating layers of divs.
I thought that it would be awesome if the same kind of check could be performed to see if the browser supports the Gecko-specific -moz-border-radius-* properties and if so utilize them.
The check for webkit support looks like this:
var webkitAvailable = false;
try {
webkitAvailable = (document.defaultView.getComputedStyle(this[0], null)['-webkit-border-radius'] != undefined);
}
catch(err) {}
That, however, did not work for -moz-border-radius so I started checking for alternatives.
My fallback solution is of course to use browser detection but that's far from recommended practice ofcourse.
My best solution yet is as follows.
var mozborderAvailable = false;
try {
var o = jQuery('<div>').css('-moz-border-radius', '1px');
mozborderAvailable = $(o).css('-moz-border-radius-topleft') == '1px';
o = null;
} catch(err) {}
It's based on the theory that Gecko "expands" the composite -moz-border-radius to the four sub-properties
-moz-border-radius-topleft
-moz-border-radius-topright
-moz-border-radius-bottomleft
-moz-border-radius-bottomright
Is there any javascript/CSS guru out there that have a better solution?
(The feature request for this page is at http://plugins.jquery.com/node/3619)
How about this?
var mozborderAvailable = false;
try {
if (typeof(document.body.style.MozBorderRadius) !== "undefined") {
mozborderAvailable = true;
}
} catch(err) {}
I tested it in Firefox 3 (true) and false in: Safari, IE7, and Opera.
(Edit: better undefined test)
I know this is an older question, but it shows up high in searches for testing border-radius support so I thought I'd throw this nugget in here.
Rob Glazebrook has a little snippet that extends the support object of jQuery to do a nice quick check for border-radius support (also moz and web-kit).
jQuery(function() {
jQuery.support.borderRadius = false;
jQuery.each(['BorderRadius','MozBorderRadius','WebkitBorderRadius','OBorderRadius','KhtmlBorderRadius'], function() {
if(document.body.style[this] !== undefined) jQuery.support.borderRadius = true;
return (!jQuery.support.borderRadius);
}); });
Attribution
That way, if there isn't support for it you can fall back and use jQuery to implement a 2-way slider so that other browsers still have a similar visual experience.
Why not use -moz-border-radius and -webkit-border-radius in the stylesheet? It's valid CSS and throwing an otherwise unused attribute would hurt less than having javascript do the legwork of figuring out if it should apply it or not.
Then, in the javascript you'd just check if the browser is IE (or Opera?) - if it is, it'll ignore the proprietary tags, and your javascript could do it's thing.
Maybe I'm missing something here...
Apply CSS unconditionally and check element.style.MozBorderRadius in the script?
As you're already using jQuery you could use jQuery.browser utility to do some browser sniffing and then target your CSS / JavaScript accordingly.
The problem with this is that Firefox 2 does not use anti-aliasing for the borders. The script would need to detect for Firefox 3 before is uses native rounded corners as FF3 does use anti-aliasing.
I've developed the following method for detecting whether the browser supports rounded borders or not. I have yet to test it on IE (am on a Linux machine), but it works correctly in Webkit and Gecko browsers (i.e. Safari/Chrome and Firefox) as well as in Opera:
function checkBorders() {
var div = document.createElement('div');
div.setAttribute('style', '-moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px;');
for ( stylenr=0; stylenr<div.style.length; stylenr++ ) {
if ( /border.*?-radius/i.test(div.style[stylenr]) ) {
return true;
};
return false;
};
If you wanted to test for Firefox 2 or 3, you should check for the Gecko rendering engine, not the actual browser. I can't find the precise release date for Gecko 1.9 (which is the version that supports anti-aliased rounded corners), but the Mozilla wiki says it was released in the first quarter of 2007, so we'll assume May just to be sure.
if ( /Gecko\/\d*/.test(navigator.userAgent) && parseInt(navigator.userAgent.match(/Gecko\/\d*/)[0].split('/')[1]) > 20070501 )
All in all, the combined function is this:
function checkBorders() {
if ( /Gecko\/\d*/.test(navigator.userAgent) && parseInt(navigator.userAgent.match(/Gecko\/\d*/)[0].split('/')[1]) > 20070501 ) {
return true;
} else {
var div = document.createElement('div');
div.setAttribute('style', '-moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px;');
for ( stylenr=0; stylenr<div.style.length; stylenr++ ) {
if ( /border.*?-radius/i.test(div.style[stylenr]) ) {
return true;
};
return false;
};
};