Ajax call: What is the difference between new ActiveXObject("Msxml2.XMLHTTP") and new ActiveXObject("Microsoft.XMLHTTP")? - ajax

I hope both the object invocations are referring to the ActiveXObject.
But why are we passing two different parameters to work in IE.
1. Msxml2.XMLHTTP and
2. Microsoft.XMLHTTP
Are they both same ? Or Are they browser dependent(IE7 and IE8) ?
I used both. I did not get any exception. Both are looking same for me. I am using IE 8.

Both are actually outdated. There are various versions of Microsoft's venerable MSXML ActiveX object (I believe the last one was version 5.0 and came with some version of Office.) The versions have minor differences in behavior, and bug fixes that usually don't come into play in AJAX scenarios.
Starting with IE7, Microsoft supported the standardized "XmlHttpRequest" object that other modern browsers had adopted. See http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx. You should definitely be using that as IE7 is now the de-facto lowest common denominator. IE6 has been declared dead by most major organizations, so there's no reason to support the old Microsoft-specific ActiveX ProgIDs.
And of course, there is very little reason these days to roll your own AJAX calls, as libraries like jQuery and ASP.NET Ajax do it for you, abstracting away these obscure browser quirks. I would strongly suggest learning one of those libraries.
Jordan Rieger

jquery (at least 1.4.2) has problem on $.ajax() calling. It makes great memory leakage (like fountain)
tragedy code:
if ( window.ActiveXObject ) {
jQuery.ajaxSettings.xhr = function() {
if ( window.location.protocol !== "file:" ) {
try {
return new window.XMLHttpRequest();
} catch(xhrError) {}
}
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch(activeError) {}
};
}
resolution:
if ( window.ActiveXObject ) {
jQuery.ajaxSettings.xhr = function() {
if ( window.location.protocol !== "file:" ) {
if ( window.ActiveXObject ) {
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
try {
return new window.XMLHttpRequest();
} catch(xhrError) {}
}
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch(activeError) {}
};
}

Related

How to implement message passing callbacks in an all-in-one (Edge/Firefox/Chrome) browser extension's content script?

Development Environment OS: Windows 7 Enterprise LTS
Browser compatibility minimum requirements: Should support all Edge, Firefox, Chrome browsers, as of 2018.
Current ongoing issue: Unable to run VM on dev workstation; Cannot run Windows 10 VMs to debug Microsoft Edge extensions.
To explain:
An "all-in-one browser extension" refers to a browser extension code that uses the same code with minor differences to work on various WebExtensions / Chrome Extensions supported browsers. At bare minimum, the same codebase should work and run on Edge, Firefox, and Chrome with very minor changes.
Callbacks on the content scripts for Edge/Firefox/Chrome extensions are handled differently.
For unknown reasons, I cannot run VM on my workstation machine. When VM is running, VM client is black. This is a localized issue on my end that I cannot resolve, so I'm forced to find a different solution/alternative.
How are they handled differently on the content scripts:
Edge: browser.runtime.sendMessage uses callbacks, and returns undefined.
Firefox: browser.runtime.sendMessage uses Promises, and returns a Promise.
Chrome: chrome.runtime.sendMessage uses callbacks, and returns undefined.
According to various references:
Firefox / Chrome / MS Edge extensions using chrome.* or browser.*
https://www.smashingmagazine.com/2017/04/browser-extension-edge-chrome-firefox-opera-brave-vivaldi/
On the content scripts, you can declare the following JavaScript snippet at the top in order to create a global variable that can be referenced everywhere else:
//Global "browser" namespace definition.
window.browser = (function() {
return window.msBrowser || window.browser || window.chrome;
})();
Unfortunately, because of the issue I'm experiencing (VM not running), I cannot tell if window.msBrowser is still being used. And this solution is not helpful for me when handling message callbacks when using namespace.runtime.sendMessage.
With all that said, my main question is: How to write a message passing function that can handle callbacks properly?
Currently, I'm using the following code:
function sendGlobalMessage(messageRequest, callback) {
if (chrome && window.openDatabase) {
//This is Chrome browser
chrome.runtime.sendMessage(messageRequest, callback);
}
else if (browser) {
try {
//Edge will error out because of a quirk in Edge IndexedDB implementation.
//See https://gist.github.com/nolanlawson/a841ee23436410f37168
let db = window.indexedDB.open("edge", (Math.pow(2, 30) + 1));
db.onerror = function(e) {
throw new Error("edge is found");
};
db.onsuccess = function(e) {
//This is Firefox browser.
browser.runtime.sendMessage(messageRequest).then(callback);
};
}
catch (e) {
//This is Edge browser
browser.runtime.sendMessage(messageRequest, callback);
}
}
}
I truly felt this is a hacky solution, because the code is based off of browser platform exclusive quirks in order to separate chrome.runtime.sendMessage and browser.runtime.sendMessage API calls, so as to handle callbacks in their respective platforms. I really wanted to change this.
So I'm asking what better ways are there, out there, that is useful to detect the different platforms, and handle message passing callbacks properly at the same time?
Thanks in advance.
I believed I solved it.
EDIT: The FINAL final version (updated and more stable, less message passing):
//Global "browser" namespace definition, defined as "namespace". Can be renamed to anything else.
window.namespace = (function() {
return window.browser || window.chrome;
})();
function sendGlobalResponse(message, callback){
if (window.namespace === window.chrome) {
//Chrome
window.namespace.runtime.sendMessage(message, callback);
}
else if (window.namespace === window.browser) {
//Using instanceof to check for object type, and use the returned evaluation as a truthy value.
let supportPromises = false;
try {
supportPromises = window.namespace.runtime.getPlatformInfo() instanceof Promise;
}
catch(e) { }
if (supportPromises){
//Firefox
window.namespace.runtime.sendMessage(message).then(callback);
}
else {
//Edge
window.namespace.runtime.sendMessage(message, callback);
}
}
}
(Original Post):
The final version (Now obsoleted):
//Global "browser" namespace definition.
window.namespace = (function() {
return window.browser || window.chrome;
})();
function sendGlobalResponse(message, callback){
if (window.namespace === window.chrome) {
//Chrome
window.namespace.runtime.sendMessage(message, callback);
}
else if (window.namespace === window.browser) {
let returnValue = window.namespace.runtime.sendMessage({});
if (typeof returnValue === "undefined"){
//Edge
window.namespace.runtime.sendMessage(message, callback);
}
else {
//Firefox
window.namespace.runtime.sendMessage(message).then(callback);
}
}
}
In the second if statement, by checking to see if the return value of a window.browser.runtime.sendMessage is a Promise or undefined, we can detect if the platform is Firefox or Edge.
I think this is the only solution to handle message passing callbacks/message responses on the content scripts.
I really couldn't think of a better solution than this. So I'll be using this from now on.
But if anyone else knows a better way, a way where you don't need to send out 1 extra dummy message for Firefox and Edge per function call, that would be great!
It sucks that anything inside the content script is not persistent, and even if you store information about what platform the code is being run on, you still have to fetch the information from the background script before filtering out which runtime.sendMessage function to call on, so it doesn't really save much time.

Getting Webpack 2 to support IE8

I want to use Webpack 2 in a large project which must still support IE8.
I've installed babel-preset-env so I can easily deprecate any IE < 11 in future, one by one, once each of the browsers becomes unsupported by this project.
According to the babel-preset-env readme "If you are targeting IE 8 and Chrome 55 [babel-preset-env] will include all plugins required by IE 8 since you would need to support both still."
As I understand it, I also need to install babel-polyfill mostly for its IE5 shim, but also for its polyfills for ES6 and 7 features that I may wish to use.
However having installed these things, my code still falls over on IE8 (in Browserstack) at the point where Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); is first run. A function I thought was getting 'fixed' by the shims.
Is it not getting shimmed properly? Have I missed out a step?
I had the same problem before and here is what I did to solve.
In es6 features,
a class can define a property with get and set to encapsulate a field.
but it is not woroking on IE8.
because the defineProperty method is not supported see the docs,
so we changed the whole code pattern to like below
let val1;
class className {
methodName() {
this.val2 = 'test';
//code here
}
getVal1() {
return val1;
}
setVal1(_val1) {
val1 = _val1;
}
getVal2() {
return this.val2;
}
setVal2(_val2) {
this.val2 = _val2;
}
}
module.exports = className;
and I recommend that adding 'es3ify' see the link,github es3ify to your webpack build for IE7/8

Is there a way to remove all the default autocomplete suggestions?

I've been able to add a list of suggestions to autocomplete but there is a large list of other suggestions as well.
Is there a way to get rid of the default autocomplete suggestions?
I'm looking at the source here and here and it doesn't describe anything about it. Here is what I have so far:
public function codeCompleter(editor, session, position, prefix, callback):void {
var row:int = position.row;
var column:int = position.column;
if (prefix.length === 0) {
callback(null, []);
}
var testing:Boolean = false;
if (testing) {
callback(null, attributes);
}
else {
callback(null, [{value:"addedToStage"},{value:"test"},{value:"test1"},{value:"adding"},{value:"added"}]);
}
}
I tried setting the completers to an empty array but no effect:
editor.setCompleters([]);
The problem was on my end. The version I was using must have been outdated. I updated to a newer version and the following code clears the auto complete list:
// either line does it
languageTools.setCompleters(null);
languageTools.setCompleters([]);
FYI:
Using version 1.2.6+, 12.03.2016
PS Sorry to anyone looking into this. I will post version numbers in future questions.

Get room/rooms of client [duplicate]

I can get room's clients list with this code in socket.io 0.9.
io.sockets.clients(roomName)
How can I do this in socket.io 1.0?
Consider this rather more complete answer linked in a comment above on the question: https://stackoverflow.com/a/24425207/1449799
The clients in a room can be found at
io.nsps[yourNamespace].adapter.rooms[roomName]
This is an associative array with keys that are socket ids. In our case, we wanted to know the number of clients in a room, so we did Object.keys(io.nsps[yourNamespace].adapter.rooms[roomName]).length
In case you haven't seen/used namespaces (like this guy[me]), you can learn about them here http://socket.io/docs/rooms-and-namespaces/ (importantly: the default namespace is '/')
Updated (esp. for #Zettam):
checkout this repo to see this working: https://github.com/thegreatmichael/socket-io-clients
Using #ryan_Hdot link, I made a small temporary function in my code, which avoids maintaining a patch. Here it is :
function getClient(roomId) {
var res = [],
room = io.sockets.adapter.rooms[roomId];
if (room) {
for (var id in room) {
res.push(io.sockets.adapter.nsp.connected[id]);
}
}
return res;
}
If using a namespace :
function getClient (ns, id) {
return io.nsps[ns].adapter.rooms[id]
}
Which I use as a temporary fix for io.sockets.clients(roomId) which becomes findClientsSocketByRoomId(roomId).
EDIT :
Most of the time it is worth considering avoiding using this method if possible.
What I do now is that I usually put a client in it's own room (ie. in a room whose name is it's clientID). I found the code more readable that way, and I don't have to rely on this workaround anymore.
Also, I haven't tested this with a Redis adapter.
If you have to, also see this related question if you are using namespaces.
For those of you using namespaces I made a function too that can handle different namespaces. It's quite the same as the answer of nha.
function get_users_by_room(nsp, room) {
var users = []
for (var id in io.of(nsp).adapter.rooms[room]) {
users.push(io.of(nsp).adapter.nsp.connected[id]);
};
return users;
};
As of at least 1.4.5 nha’s method doesn’t work anymore either, and there is still no public api for getting clients in a room. Here is what works for me.
io.sockets.adapter.rooms[roomId] returns an object that has two properties, sockets, and length. The first is another object that has socketId’s for keys, and boolean’s as the values:
Room {
sockets:
{ '/#vQh0q0gVKgtLGIQGAAAB': true,
'/#p9Z7l6UeYwhBQkdoAAAD': true },
length: 2 }
So my code to get clients looks like this:
var sioRoom = io.sockets.adapter.rooms[roomId];
if( sioRoom ) {
Object.keys(sioRoom.sockets).forEach( function(socketId){
console.log("sioRoom client socket Id: " + socketId );
});
}
You can see this github pull request for discussion on the topic, however, it seems as though that functionality has been stripped from the 1.0 pre release candidate for SocketIO.

Is it possible to migrate preferences from a Firefox XUL addon to an SDK addon?

I'm down to the (hopefully) last hurdle in the process of migrating our extension from XUL to Firefox SDK, but I've got one last sticking point:
Preferences.
There are a number of preferences set that simply MUST be migrated when the SDK version of the addon is installed over the top of the XUL addon. These preferences are not exposed to the end user for various reasons. The preference namespacing between the two architectures are completely different. For example -
A "version_number" preference in XUL is named arbitrarily by the developer, and appears as such in about:config :
my.preference.name
However, in SDK, they are scoped to the extension in question:
extensions.[extension ID].my.preference.name
Can preferences from XUL addons be migrated for re-use inside SDK addons? If so, how?
While it didn't seem possible to read from preferences outside the SDK addon's namespace, it WAS possible to write into the EXPECTED namespace in the old XUL extension. The solution we came up with was to publish a small, final point release of the old XUL addon with a small bit of extra logic responsible for carrying out this migration before we publish the new SDK version to AMO.
Here's a pseudocode representation of our approach:
ContentScript.js
function initNewFFInstallation() {
...
if (checkIsUpgrade()) {
var keys = getPrefKeys()
migratePrefs(keys);
}
}
Utils.js - acts as a bridge to expose Overlay functionality to the content script
Util.prototype.getPrefsBranch = function() {
return Components.classes["#mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefService).
getBranch("my.prefs.ns.");
}
Util.prototype.getV2PrefsBranch = function() {
return Components.classes["#mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefService).
getBranch("extensions.[SDK_ADDON_ID].");
}
Util.prototype.setBoolPref = function(key, val) {
this.getPrefsBranch().setBoolPref(key, val);
this.getPrefsBranch().setBoolPref(key, val);
}
Util.prototype.setCharPref = function(key, val) {
this.getPrefsBranch().setCharPref (key, val);
this.getV2PrefsBranch().setCharPref (key, val);
}
//copies all the preferences over
Util.prototype.migratePrefs = function(boolPrefKeys, charPrefKeys) {
boolPrefKeys.each(function (key) {
this.getV2PrefsBranch().setBoolPref(key, this.getPrefsBranch().getBoolPref(key));
});
charPrefKeys.forEach(function (key) {
this.getV2PrefsBranch().setCharPref(key, this.getPrefsBranch().getCharPref(key));
});
}
Then in our scriptcompiler.js, which actually injects the scripts onto the page, the util methods are hooked onto the SafeWindow object.
injectScript: function(script, unsafeContentWin) {
var safeWin=new XPCNativeWrapper(unsafeContentWin);
var sandbox=new Components.utils.Sandbox(safeWin, {"sandboxPrototype":safeWin});
sandbox.window=safeWin;
sandbox.document=sandbox.window.document;
sandbox.unsafeWindow=unsafeContentWin;
var util = new Util();
//...other APIs
sandbox.migratePreferences=app_gmCompiler.hitch(util , "migratePreferences");
try {
Components.utils.evalInSandbox("(function(){"+script+"})()", sandbox);
} catch (e) {
}
}

Resources