FANDOM

Kangaroopower

aka Kangaroo

Councilor
  • My occupation is A Quidditch Player
  • I am a track athlete and soccer player.

Welcome

Hi, welcome to Wikia Developers Wiki! Thanks for your edit to the User:Kangaroopower page.

Please leave a message on my talk page if I can help with anything! -- 127.0.0.1 (Talk) 04:11, July 11, 2011

No worries, go for it.
{{SUBST:User:Gracey91/Autosig|05:29,10/4/2011}} 05:29, October 4, 2011 (UTC)

Js debug

Hi, I read your message on Grunny's wall. I haven't read the code of your script, but I noticed you have defined the main function after the call. Since this has proven to be an issue with some other scripts, at least on Firefox, have you tried defining the function before the call to it? Cheers--Noemon *talk* 20:48, March 25, 2012 (UTC)

SpoilerAlert

SpoilerAlert

You may have a point there. I've asked Grunny to be sure. -- pecoes 15:10, March 29, 2012 (UTC)




BTW: This is the second time I get a double H2 for no apparent reason. What's going on here? This is weird. I'm going to leave this one. -- pecoes 15:13, March 29, 2012 (UTC)

Skin Switch Button

I'm not sure if the code I edited on there is correct or not. Please check the changes I made on SkinSwitchButton and SkinSwitchButton/code.js Sam Wang (talk) 03:32, June 24, 2012 (UTC)

Advanced Oasis UI

Hey... you do know that none of the user config options specified on the AdvancedOasisUIpageactually work, right?

// AdvancedOasisUI object doesn't exist yet
// You can't define AdvancedOasisUI.config here,
// because you can't give properties to undefined objects
 
window.AdvancedOasisUI.config = { 
      accountNavFollowedPages: false,
      accountNavWatchlist: false,
      categoryRedlink: true,
      RCHeader: true,
      lightbox: true,
      randomPageLimitedTo: "",
      userLang: true,
};
importScriptPage('AdvancedOasisUI/code.js', 'dev');

Mathmagician (message wall) 19:31, August 6, 2012 (UTC)

Thanks for the bug report. We have filed it with our technical staff and it has been noticed. :P Seriously though I think I've fixed it so clear your cache and make sure the import goes above the config. --Kangaroopowah (Talk) 20:57, August 6, 2012 (UTC)
Even if you put the import above the config options, when you use importScript, you're still loading the script asynchronously. You're banking on the hopes that AdvancedOasisUI object will be defined before the interpreter tries to assign the AdvancedOasisUI.config property.
importScriptPage('AdvancedOasisUI/code.js', 'dev');
 
 
// when the interpreter reaches this line, AdvancedOasisUI *might* exist,
// but it also might not exist. You don't know, because
// AdvancedOasisUI/code.js is loading asynchronously.
 
// Try running this from the console to test it yourself,
// it generates an error for me.
 
 
window.AdvancedOasisUI.config = { 
      accountNavFollowedPages: false,
      accountNavWatchlist: false,
      categoryRedlink: true,
      RCHeader: true,
      lightbox: true,
      randomPageLimitedTo: "",
      userLang: true,
};
Any approach that uses a property (config) of the AdvancedOasisUI object while loading AdvancedOasisUI/code.js asynchronously with an importScriptPage call is not going to be safe. If you're going to assign a property to an object, you *need* to know that object exists at the time you try to access its property. — Mathmagician (message wall) 23:44, August 6, 2012 (UTC)
You know, actually putting config like this is a pretty bad idea, not only for this. Give me a day or two and it'll be (unfortunately) a global again. --Kangaroopowah (Talk) 23:52, August 6, 2012 (UTC)

(reset indent)You don't necessarily need to have a 2nd global object just for the config options though. You could do something like this:

// user specifies their config options outside of your script...
AdvancedOasisUI = {
    accountNavFollowedPages: false,
    accountNavWatchlist: false
}
 
 
 
 
// Inside of your script...
$(function () {
    if (typeof AdvancedOasisUI == "object") {
        // transfer AdvancedOasisUI to AdvancedOasisUI.config property
        var temp = AdvancedOasisUI;
        window.AdvancedOasisUI = {};
        AdvancedOasisUI.config = temp;
    } else {
        window.AdvancedOasisUI = {};
        AdvancedOasisUI.config = {};
    }
 
 
    // extend the config object so that any undefined config
    // options are given default values
    $.extend(AdvancedOasisUI.config, {
        default config options...
    });
});
 
 
 
 
// Usage example
AdvancedOasisUI = {
    accountNavFollowedPages: false,
    accountNavWatchlist: false
}
importScriptPage('AdvancedOasisUI/code.js', 'dev');

Pecoes does something akin to this in some of his scripts, e.g. Sine. I do something similar in Railgun. — Mathmagician (message wall) 00:07, August 7, 2012 (UTC)

Sounds good. I've never really dealt with extends but it sounds pretty sound. btw can you come to central chat? --Kangaroopowah (Talk) 00:11, August 7, 2012 (UTC)

HideRail

Regarding your edit of HideRail/code.js: The script stopped working after your edit because return must be used inside a function. That's why I reverted it. Arkondi (talk) 09:04, August 19, 2012 (UTC)

  1. Is there a special reason why you want to change the way the decision, whether the script is executed or not, is done? And why do you removed my translation?
  2. return false is only needed, if the function should return a boolean value. If you only want to exit the function, a pure return will do.—Preceding unsigned comment added by Arkondi (talkcontribs) . Please sign your posts with ~~~~!
I honestly have no idea how that translation was removed and it was definetly not my intention. I was editing on my iPad so I guess accidents could happen but it might have just been on of those editor mishaps that occur from time to time. As for the script execution, there's no real reason I want to change it except to save a few bytes ;). Finally, I know return false is not needed. However it is nice for people who are debugging in console to have a return statement that isn't undefined. --Kangaroopowah (Talk) 16:57, August 19, 2012 (UTC)
  • In my opinion, a specific message in the console log (as done in messageSet) would be more useful for debugging.
  • As Lunarity said in the summary of this edit, it is more efficient to decide whether the script is executed or not, before the document is loaded completely.
Arkondi (talk) 17:48, August 19, 2012 (UTC)

MarkForDeletion

Hey, I have reverted your change to MarkForDeletion/code.js. Please respect my request not to edit the script at this time. While I have no qualms with the concept of improvement, it is still in a rather early stage and unexpected architectural changes may confuse me at this point. Please use Talk:MarkForDeletion to suggest improvements. 20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 04:30 UTC, Thursday, 27 December 2012

Heh, I was just going to tell you about these changes and say that I made some quick changes and that you could revert them if you wanted, but then I went out for a while. Two quick suggestions- implement my changes ;) (as they simplify your ajax life AND it removes XML dependence AND it is shorter) as well to not use prompts. It's not worth it long term. --Kangaroopowah (Talk) 05:32, December 27, 2012 (UTC)
About getting rid of prompt: that's on the to-do list. Quick and dirty, it serves its purpose of getting a single piece of information from the user. Ultimately I will create some sort of HTML form, but that's more work and thinking for another day.
JSON's main advantages over XML are 1) being easily translated to JavaScript objects and 2) being smaller. In this case, if you take a look at the URL to get the edit token:
http://dev.wikia.com/api.php?action=query&prop=info&intoken=edit&format=xml&titles=MarkForDeletion
there's not much content there, so while JSON as a data format is more compact than XML in general, in this case we're talking about a very, very small data package. And out of that data package, I don't need any JavaScript objects, all I need is just the edit token string. So the XML versus JSON point is really a non-issue.
If you really want me to use JSON, I could simply change format=xml to format=json in the URL and use string functions to parse the resulting JSON string manually instead of parsing the XML string manually like I am currently doing.
But there's no particular benefit to using $.getJSON in this case. All that would do is automate the process of converting a JSON string to a usable JavaScript object. Which in general may be a great convenience. But in this case, it's simply unnecessary overhead, both on the count of using jQuery instead of fast-executing native code for the AJAX request, and also on the count of letting it parse the entire server response for every single JavaScript property and object when all I need is just the edit token string and I'm going to throw away the rest of the data.
Theory aside, your implementation of the setDeleteNotice method in http://dev.wikia.com/wiki/MarkForDeletion/code.js?oldid=10456 was not functioning as intended (a couple of callback issues: one with window.location.reload executing immediately instead of as callback to $.post and one related to $.post not being inside the $.getJSON callback so that the POST request actually happens prematurely before the edit token has been retrieved). Replacing functional/tested code with non-functional/non-tested code is not my favorite thing to do, which is another reason why I'd prefer to discuss it on the talk page first so that I have a chance to test the suggested code before incorporating it into the script. 20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 10:10 UTC, Thursday, 27 December 2012

Weird, when I tested in console it worked. But then again, console has a habit of messing up callback related things. That aside, I still feel that in this case, jQuery and Json will help more than not. --Kangaroopowah (Talk) 17:17, December 27, 2012 (UTC)

Ben 10 Fan Fiction Chat

Hey, about the script. Can you come over to the B10FF chat?. Here's the link: http://ben10fanfiction.wikia.com/wiki/Special:Chat NickFusi0n Talk Blog Contribs 22:26, January 1, 2013 (UTC)

Announce

Hey, I saw that you and Plasma set it up. It's working fine! The problem is, since the script was copied from your Chat.js, it has other scripts on it. It has the "Timestamp" that shows seconds and all usernames on chat have < and > boundaries. I believe that's a separate script and I tried fixing it myself but couldn't. Could you edit it so that exludes the second counter and the < > name boundaries? Thanks, sorry if I'm disturbing you. --NickFusi0n Talk Blog Contribs 21:50, January 5, 2013 (UTC)

AjaxRC

I see you're making some improvements to the Ajax auto refresh script, and was wondering if it was possible to add another feature in. Something that came up a while back on another wiki was compatibility with the advanced recent changes dropdowns. I'm not sure if your version of the script does this, but when RC refreshes all the opened parts collapse.

In case I'm being confusing, imagine I edited a page, then you did. On the RC that would result in a collapsed menu that could be expanded to show the individual edits, or left collapsed to show who has edited the page and how many times.

I went as far to ask Pcj if it was possible to stop the collapsing with the refresh, but he said no, with no real explanation. I assume it would rely on some cookies to remember which parts were opened, but from Pcj's response I guess it's not possible to add those cookies in? Thanks, cqm 15:30, 11 Jan 2013 (UTC)

I spent the majority of the day thinking about this and I think I know why Pcj thought it wasn't feasible- because the script is about autoupdating RC or whatever page you have it set for. So when it updates, it's probably going to bring new edits in, which stops you from looping through all the collapsible elements and then seeing if they should stay collapsed. Sorry. --Kangaroopowah (Talk)
I've come across a rather interesting bug: when non-special pages are added into the array of pages to refresh (ie pages you can actually edit) the auto refresh function will continue to refresh the page every 30 secs/1 min/however-long-it's-set-for, including when you try to edit the page. It is possible to disable the auto-refresh when the url contains ?action=edit? cqm 12:42, 14 Jan 2013 (UTC)
It's particularly confusing in oasis, where the checkbox doesn't appear as the elements are completely different when editing to viewing the page. I though it was a Wikia editor bug until I though to use the skin Wikia make a point of not touching (monobook), where the checkbox shows up. cqm 12:44, 14 Jan 2013 (UTC)
Done. Any action other than edit will show it though. Is that okay, or do you want it to only show on wgAction === view (when you're just reading). --Kangaroopowah (Talk) 20:35, January 14, 2013 (UTC)
Just when editing should be fine. I can't imagine it being an inconvenience when viewing history, unless you know of a ?action= where refreshing is an issue? cqm 16:10, 15 Jan 2013 (UTC)

Whenever the AjaxRc refreshes the RC, there is an error: TypeError: Wikia.MultiSelectDropdown is not a constructor Thought it might be useful for the new version...--~ UltimateSupreme 17:43, February 14, 2013 (UTC)

Minor note about aliasing the jQuery namespace

In response to your edit summary here, the function passed to $(document).ready() accepts a single parameter (the jQuery object) per http://api.jquery.com/ready/ (under Aliasing the jQuery namespace). Eladkse was simply using it as a byproduct of the construction I suggested on his talk page.

If you alias $ like that, the code inside the function will use the local $ var from within that closure, rather than wasting time looking outside the closure for the global $ var. It's basically serving the same purpose as the

( function ( $, mw ) {
    // code inside here
}( jQuery, mediaWiki) );

that you're familiar with. 20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 22:43 UTC, Sunday, 13 January 2013

That's what I thought, but the reason I didn't find it useful is because he did $(function ($) { . If he had done jQuery(function ($) { IMO there would have been a practical use for it as it would help with overriding other versions of $ and the like. But thanks for clarifying. --Kangaroopowah (Talk) 01:07, January 14, 2013 (UTC)

Ajax call again

Hey Kangaroo, there are a couple reports on Talk:AjaxRC of the ajaxCallAgain option not working properly with the updated AjaxRC. The problem seems to be that the new version copies window.ajaxCallAgain into a local variable "too early", before other scripts have actually had a chance to add their functions to the array. I've moved the variable down into the proper context so that it's calculated when the ajaxComplete event actually happens. Please review my edit http://dev.wikia.com/?diff=11451&oldid=11433 and let me know if you think it solves this issue. Thanks, 20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 00:28 UTC, Sunday, 21 April 2013

I tested it and everything works. Thanks for the fix! --Kangaroopowah (Talk) 01:48, April 21, 2013 (UTC)
Great. When you're done making changes on your end, please ask Grunny to push another update.
Edit: btw, one other change I would suggest, although it's not really critical. In the part where you set localStorage.setItem( 'refresh', true ); — I would recommend renaming the variable from "refresh" to "AjaxRC-refresh". "refresh" is a very general term, and it could potentially collide with other scripts/features that have a refresh variable in localStorage. Naming it "AjaxRC-refresh" would be a more specific name. 20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 16:20 UTC, Sunday, 21 April 2013
Good point. I'll make that change. Then I'll put the changes on the code review portal and we can get Grunny to push the changes in a bit. --Kangaroopowah (Talk) 20:01, April 21, 2013 (UTC)
Could you review (and maybe get some other people) Portal:Code_Review/AjaxRC. --Kangaroopowah (Talk) 00:18, April 22, 2013 (UTC)

AjaxRC memory concerns

Hey,

Recently I've noticed some issues with AjaxRC appearing to cause a memory leak in Firefox and Chrome, and have been discussing it with Grunny. For example, roughly over the course of a night it sent my Firefox from 750MB to 1.5GB of RAM. Unfortunately, we've not managed to nail down a specific cause yet.

This is what we've worked out so far:

  • It appears unrelated to the recent code update
  • It's worse in Firefox than Chrome
  • It's worse when 'Enhanced/Grouped Recent Changes' is enabled

From using Firefox's about:memory page, it seems like each time it refreshes the page, old data is being held onto causing the 'dom --> orphan-nodes' value to increase each time (there might be other values doing the same).

Since you've been working on its code, have you noticed anything similar?

Thanks! Kirkburn (talk) @fandom 18:46, May 10, 2013 (UTC)

I was actually going to ask you why you switched over to your old one in your global.js :P. My assumption is that is related to the most recent code change. User:Mathmagician made some changes to loadPageData so it wouldn't strip formatting on pages like Special:Log (full explanation over at Portal:Code Review/AjaxRC and changed loadPageData from:
	function loadPageData() {
		var cC = '#mw-content-text';
		$( cC ).load( location.href + " " + cC + " > *", function () {
			if ( storage() ) {
				ajaxTimer = setTimeout( loadPageData, ajRefresh );
			}
		} );
	}

to

	function loadPageData() {
		var $temp = $( '<div>' );
		$temp.load( location.href + " #mw-content-text", function () {
			var $newContent = $temp.children( '#mw-content-text' );
			if ( $newContent.length ) {
				$( '#mw-content-text' ).replaceWith( $newContent );
			}
			ajaxTimer = setTimeout( loadPageData, ajRefresh );
		} );
	}

I think the problem is that $temp isn't being removed after the end of every call of loadPageData, leadign to that problem. I'll push an edit to fix that and then let's see how the memory's like. Best, --Kangaroopowah (Talk) 19:13, May 11, 2013 (UTC)

Since Kangaroo mentioned this to me, I thought I'd throw in my two cents:
  • I'm also seeing the memory leak under dom -> orphan nodes on Firefox's about:memory page
  • Seems to happen in older versions of AjaxRC as well
  • Another place the memory leak seems to be occurring is in the JavaScript jQuery.cache object (check the JavaScript console). After each Ajax refresh, additional keys keep getting added to that object, and its size seems to grow endlessly.
  • Another observation I made testing from the console is that commenting out the line $collapsibleElements.makeCollapsible(); seems to prevent jQuery.cache from getting those extra keys, and allows Firefox to recover memory so that dom -> orphan nodes doesn't continuously grow.
    • However, I'm not yet able to come up with a reduced test case to demonstrate that makeCollapsible is actually the source of the problem, so this observation doesn't make much sense at the moment. But it happens for me nonetheless. 20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 21:16 UTC, Saturday, 11 May 2013
While makeCollapsible may be one of the problems, I'm seeing a definite improvement in memory usage after I called $temp.remove(); in loadPageData. Your thoughts, Kirburn? --Kangaroopowah (Talk) 04:41, May 12, 2013 (UTC)

@Kangaropower: for reference, here are the test cases I performed while checking for memory leaks. If you have time, could you perform these test cases as well and let me know if you can confirm or deny my conclusions?


Setup:

  • Firefox web browser
  • Logged in to a Wikia account
  • "Use advanced recent changes" is enabled in Special:Preferences
  • One tab open on Special:RecentChanges on any wiki
  • Second tab open on Firefox's about:memory page

Test A)

Orphaned nodes about-memory

caption=orphaned nodes on Firefox's about:memory page

  1. On Firefox's "about:memory" page, look for the Special:RecentChanges tab, and look for memory usage under DOM -> orphaned nodes
  2. Write down or remember the value of orphaned nodes
  3. In your Special:RecentChanges tab, allow AjaxRC to do a couple dozen ajax refreshes (may take an hour or two while you're waiting, or you could just leave it running overnight and check in the morning).
  4. Check about:memory again and look at the value of orphaned nodes — you should see that the value has increased by dozens or hundreds of megabytes.

Test B)
(This test can be done in either Chrome or Firefox. I've tried both browsers with the same result on every attempt thus far.)

  1. Open the JavaScript console in your developer tools.
  2. Count the number of properties in the jQuery.cache object. For example, running this from the console will do the trick:
var count = 0;
for (var i in jQuery.cache) {
    count++;
}
console.log(count);
  1. Allow AjaxRC to do one (1) ajax refresh.
  2. Again count the number of properties in jQuery.cache. You should observe that the value has incremented by a small amount (1 – 15).
  3. Repeat this process enough times, until you have convinced yourself that every ajax refresh adds more nodes to jQuery.cache and the size of the object is growing without bound as more and more ajax refreshes are performed.

Test C) Demonstrating correlation between makeCollapsible and the memory leak

  1. Uninstall AjaxRC in your user scripts
  2. On Special:RecentChanges, run a customized version of AjaxRC/beta.js from your JavaScript console. Copy/paste all of the source code directly into your console, but delete or comment out the line $collapsibleElements.makeCollapsible(); before running the script.
  3. Repeat tests A) and B) with this version of AjaxRC that does not use makeCollapsible. Observe that orphaned nodes in A) and jQuery.cache in B) are not experiencing the symptoms of memory leak described in those test cases.
  4. This correlation points to makeCollapsible as a potential source of the memory leak. It also makes sense when taken together with the observation Kirkburn stated on Kangaroo's talkpage about the memory leak being worse when "Use advanced recent changes" is enabled in preferences. Advanced recent changes uses more collapsible elements, so this correlates with makeCollapsible being part of the issue.

20px_Rin_Tohsaka_Avatar.png Mathmagician ƒ(♫) 08:05 UTC, Saturday, 1 June 2013

Code

Hi, may I ask where did you learn JavaScript — OriginalAuthority 17:22, August 2, 2013 (UTC)

Honestly? I stared at code for a while. Then I looked at some tutorials around the web and then started using MDN (google it) as a reference. --Kangaroopowah (Talk) 22:36, August 2, 2013 (UTC)

Scope

Hi, have you ever though about integrating Scope, with monobook, it wouldcbe a nice feature to have for is monobook users?. --— OriginalAuthority 13:24, August 5, 2013 (UTC)

I'm working on it, but it's difficult because I need to figure out what events the monobook editor calls when it loads. When I've figured that out, it'll be pretty easy. --Kangaroopowah (Talk) 17:43, August 5, 2013 (UTC)

Re:

Coincedentially I am re writting QuickTools to be

A) More efficient

B) Cleaner

C) Work in Monobook

So I appreciate it. This was one of my first projects so it isn't all that good. Hopefully I can change that. I wrote the advanced version pretty well, if you could take a look at that also it would be much appreciated! Princess Platinum ]Open Source[ (talk)

Demo Scripts

Can you add Quicktools and Advancedtools to the demo scripts page so that way when users visit the QuickTools page they can try both of them out and see if they wish to use them? It would be much appreciated. Prinplat ]Open Source[ 14:29, November 19, 2013 (UTC)

Seeing as they overlap functionality wise, could you make a function that adds a way (Please, not a modal or an alert) that lets the user choose which version the user wants to see? Thanks, --Kangaroopowah (Talk) 05:06, November 21, 2013 (UTC)

thanks

Thank you, I was wondering how you make it look like that.

{{SUBST:User:ChaoticShadow/Sig|05:00,12/10/2013}} :D

Translator Fixed!

I tweaked the code of Translator and it worked! The problem is is that the URL direct wasn't properly syntaxed and the code:
url += text;
added the words on the site, causing the URL to be long so Google Translate can't function as it is supposed to. It also seemed to be missing this code I added that supposed to direct the URL of the site a user is on for Google to Translate it:
mw.config.get("wgServer");
. Fortunately, it is now fixed! Ismael Perez (talkcontribsblog) 14:44, February 17, 2014 (UTC)
That's weird. it worked when I shortened it originally. It looks like DeadCoder changed it after I did- that might have affected it. Best, Kangaroopowah (Talk) 18:21, February 17, 2014 (UTC)

Time zone converter

Hey, have you been working on the time zone converter that I brought up the other day? Just checking, like you asked me to do.

Just to clarify, the date and time are preset on the page, then automatically converted to the user's time zone. There is no user input.

Thanks for your help. - Kelerik (talk) 14:04, April 17, 2014 (UTC)

APICall Script

Hello, well, I understand your point. I used console.logs before made alerted as I think the end user doesn't use console. Well, I don't really know what you meen with callback but if it is functions that are fired after the API call, I don't know how it can informed the end user about the API request progress (fail or not). We can maybe execute a function that the user will create to let him do what he likes... Gguigui1 (discussion) @fandom 16:54, December 8, 2014 (UTC)

I've made it. Thanks a lot for your feedback. Gguigui1 (discussion) @fandom 07:11, December 13, 2014 (UTC)

Re: Script Manager

It is coded, I just have not fully put it up yet. I am merely getting it ready to put up. Shining-Armor (talk) 08:16, December 14, 2014 (UTC)

My Scripts

QuickTools/code.js is not the defacto version atm that would be QuickTools/advanced.js. The code.js version stopped working long ago and I just cleared it out in order to

  • Stop JS console errors
  • Make room for what is going to be known as QuickTools
  • Make it easier for users to preview/make suggestions.

As for Script Manager it is nearly finished but as I said earlier I was only able to complete creating documentation pages for it. I hope to get it up soon (work and all). Shining-Armor (talk) 03:42, December 17, 2014 (UTC)

AjaxRedirect

The script is now broken. – Ozuzanna 10:39, December 31, 2014 (UTC)

I've reverted your edits to it, should you want to revert back, the code should be working first. Also, "making indentation nicer" is subjective and personally I'm not fond of 4 spaces instead of 2. – Ozuzanna 21:23, December 31, 2014 (UTC)

AjaxRC

Hello. AjaxRC not working on some sites (For example:http://ru.harrypotter.wikia.com/wiki/Служебная:RecentChanges, http://fr.harrypotter.wikia.com/wiki/Spécial:Modifications_récentes, http://ru.community.wikia.com/wiki/Служебная:RecentChanges). Could you solve this problem? FANSG (talk) 12:07, October 3, 2016 (UTC)

Community content is available under CC-BY-SA unless otherwise noted.

Fandom may earn an affiliate commission on sales made from links on this page.

Stream the best stories.

Fandom may earn an affiliate commission on sales made from links on this page.

Get Disney+