Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GM 2.0 + FF30 and ajax from jQuery #1952

Closed
ArkadiuszMichalski opened this issue Jul 11, 2014 · 11 comments
Closed

GM 2.0 + FF30 and ajax from jQuery #1952

ArkadiuszMichalski opened this issue Jul 11, 2014 · 11 comments

Comments

@ArkadiuszMichalski
Copy link

Hello, after changing unsafeWindow rules some scripts stop work. I have this situation:

  • som page use jQ library by script tag
  • from GM script I want get access to this jQuery in page and invoke ajax() method

Before change (older GM and Firefox) I use sth like this:

unsafeWindow["$"]["ajax"]({
  "url": "someURL",
  "success": function(result) {
     alert(result["test1"] + result["test2"]);
  },
  "dataType": "json"
}); 

and all works fine. Now I get "access denited" info because use object as argument. So in next step I try this:

unsafeWindow["$"]["ajax"](cloneInto({
  "url": "someURL",
  "success": function(result) {
     alert(result["test1"] + result["test2"]);
  },
  "dataType": "json"
}, unsafeWindow));

When cloning simple object doesn't have problem, but in this code problem make:

"success": function(result) {
  alert(result["test1"] + result["test2"]);
}

and generate error:
"Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIXPCComponents_Utils.cloneInto]"

When delete this method don't get any error. So how can I define this success method in GM side when jQ is defined in page side and make all works?

@arantius
Copy link
Collaborator

The description is incomplete, but given what you've said: this is intended. Read the release notes. http://www.greasespot.net/2014/06/greasemonkey-20-release.html

@ArkadiuszMichalski
Copy link
Author

Now is complete so please give some advice.

@cletusc
Copy link
Contributor

cletusc commented Jul 11, 2014

Now is complete so please answer or open next bug?

Set $ and jQuery in your own scope, and assign it to the page's jQuery. Just make sure you specify @grant none in your metadata.

// Make our own copy of jQuery...
var $, jQuery;
$ = jQuery = window.jQuery;

// Then ajax like normal...
$.ajax({
  "url": "someURL",
  "success": function(result) {
     alert(result["test1"] + result["test2"]);
  },
  "dataType": "json"
}); 

@ArkadiuszMichalski
Copy link
Author

I can't specify @grant none because I use some API and defined them in my metadata.

$ = jQuery = window.jQuery; << what is window.jQuery? I have undefined. Like I said, I use jQ from page, not import in GM, and I want invoke some method from this jQ but after changing rule for passing object its not easy.

Now I see why get error - cloneInto() can't convert function so I try use other things:

var configObject = {
  "url": "someURL",
  "dataType": "json"        
};
// Clone GM object to page
unsafeWindow.configObject = cloneInto(configObject, unsafeWindow);
// Extend this object by function for jQ
exportFunction(function(){alert("test")}, unsafeWindow.configObject, {defineAs: "success"});
// Invoke ajax by passing this object
unsafeWindow["$"]["ajax"](unsafeW.configObject);                

And this work, make conection to server and get json data but "success" is not invoke, don't know why. Any advice? I can only add that this work:

unsafeWindow.configObject.success(); // get alert with "test"

@cletusc
Copy link
Contributor

cletusc commented Jul 11, 2014

What GM_* API are you using?

@ArkadiuszMichalski
Copy link
Author

// @grant GM_getValue
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @grant GM_getResourceURL
// @grant unsafeWindow

But now find solution, cloneInto() take some additional argument allowing clone function and DOM object:
https://developer.mozilla.org/en-US/docs/Components.utils.cloneInto#cloneInto_options
When use it all works fine:

unsafeWindow["$"]["ajax"](cloneInto({
  "url": "someURL",
  "success": function(result) {
     alert(result["test1"] + result["test2"]);
  },
  "dataType": "json"
}, unsafeWindow, {"cloneFunctions": true}));

But still wondering why my solution with sharing by using exportFunction() not work. Its has effects like I completly don't defined "success", maybe do something wrong. All works fine but can't correctly define "success" for $.ajax().

@cletusc
Copy link
Contributor

cletusc commented Jul 12, 2014

But still wondering why my solution with sharing by using exportFunction() not work.

exportFunction isn't really what is needed in this case. cloneInto is what you want as it drops the whole object (and your callbacks) down to the correct scope. The entire object must be in the correct scope, not just your success function.

If you wanted to ease the pain, you could use something like this:

/**
 * unsafeWindow.jQuery.ajax workaround for GM 2.0+. This automatically uses the pages jQuery
 * when `@grant unsafeWindow` is used. Do not use this unless you have an absolute need
 * for any of the `GM_*` APIs. `@grant none` is much cleaner for this.
 *
 * Accepts same parameters as the standard `jQuery.ajax`: http://api.jquery.com/jQuery.ajax/
 * Does not return anything; Promises will not work--use the setting object instead.
 */
function ajax(url, settings) {
    // The ajax method.
    var ajax = unsafeWindow.jQuery.ajax;
    if (typeof settings === 'undefined') {
        ajax(cloneInto(url, unsafeWindow, {cloneFunctions: true}));
        return;
    }
    ajax(url, cloneInto(settings, unsafeWindow, {cloneFunctions: true}));
};

// Example usage.
ajax({
    url: 'someURL'
    success: function (result) {
        console.log(result);
    },
    dataType: 'json'
});

@arantius
Copy link
Collaborator

That looks like a good explanation to have somewhere on the wiki Ryan; can you put it up?

@cletusc
Copy link
Contributor

cletusc commented Jul 15, 2014

Sure, I'll make some more consistent examples of each then probably mention it somewhere on the @grant page unless you have a better spot for it (unsafeWindow maybe?)

@CodenameCookie
Copy link

function ajax(url, settings) {
    // The ajax method.
    var ajax = unsafeWindow.jQuery.ajax;
    if (typeof settings === 'undefined') {
        ajax(cloneInto(url, unsafeWindow, {cloneFunctions: true}));
        return;
    }
    ajax(url, cloneInto(settings, unsafeWindow, {cloneFunctions: true}));
};

// Example usage.
ajax({
    url: 'someURL'
    success: function (result) {
        console.log(result);
    },
    dataType: 'json'
});

I keep getting 'cloneinto not defined'.

Is this example just too old to use now?

@Sxderp
Copy link
Contributor

Sxderp commented Jul 26, 2020

I keep getting 'cloneinto not defined'.

Is this example just too old to use now?

Very much so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants