PageSourceSearch

https://www.planesculptors.net/js/spoiler.js?v=7

js planesculptors.net collected 2026-09-24 11:33:39 UTC 19,972 bytes, 859 lines download raw bytes

1function Alea(seed) {
2
3    if(seed === undefined) {seed = +new Date() + Math.random();}
4
5    function Mash() {
6
7        var n = 4022871197;
8
9        return function(r) {
10
11            for(var t, s, u = 0, e = 0.02519603282416938; u < r.length; u++)
12
13            s = r.charCodeAt(u), f = (e * (n += s) - (n*e|0)),
14
15            n = 4294967296 * ((t = f * (e*n|0)) - (t|0)) + (t|0);
16
17            return (n|0) * 2.3283064365386963e-10;
18
19        }
20
21    }
22
23    return function() {
24
25        var m = Mash(), a = m(" "), b = m(" "), c = m(" "), x = 1, y;
26
27        seed = seed.toString(), a -= m(seed), b -= m(seed), c -= m(seed);
28
29        a < 0 && a++, b < 0 && b++, c < 0 && c++;
30
31        return function() {
32
33            var y = x * 2.3283064365386963e-10 + a * 2091639; a = b, b = c;
34
35            return c = y - (x = y|0);
36
37        };
38
39    }();
40
41}
42
43
44
45function isMobileView() { return window.innerWidth <= 800 }
46
47
48
49var Spoiler = function (options){
50
51    this.data = options.data;    
52
53    this.mainElement = options.element;
54
55    this.enableControl = options.enableControl != null ? options.enableControl : true;
56
57    this.enableLinks = options.enableLinks != null ? options.enableLinks : true;
58
59    this.showVersion = options.showVersion != null ? options.showVersion : false;
60
61    
62
63    this.resetSeed();
64
65    this.initializeStructure();
66
67    this.initializeCardElements();
68
69    this.initializeSorting();
70
71    this.redraw();   
72
73
74
75    var spoiler = this;
76
77    //$(window).resize(function() {
78
79      //  spoiler.redraw();
80
81    //});
82
83};
84
85
86
87Spoiler.prototype.resetSeed = function() {    
88
89    var seed = parseInt(this.getUrlVars().seed) || new Date().getTime();
90
91    console.log("seed", seed)
92
93    this.alea = Alea(seed);
94
95}
96
97
98
99Spoiler.prototype.getUrlVars = function () {
100
101    var vars = [];
102
103    var locationWithoutHash = window.location.href.split('#')[0];
104
105    var hashes = locationWithoutHash.slice(locationWithoutHash.indexOf('?') + 1).split('&');
106
107    for (let i = 0; i < hashes.length; i++) {
108
109      let hash = hashes[i].split('=');
110
111      vars.push(decodeURIComponent(hash[0]));
112
113      vars[hash[0]] = decodeURIComponent(hash[1]);
114
115    }
116
117    return vars;
118
119}
120
121
122
123Spoiler.prototype.initializeStructure = function () {
124
125	if(this.enableControl)
126
127	{
128
129		this.mainElement.html(
130
131	        //"<div class='spoler-cards-no'>Number of cards: " + this.data.length + "</div>" +
132
133            "<div class='spoiler-filters-and-sorts'>" +
134
135                (!isMobileView() ? "<div class='spoiler-mode'>" +
136
137	        "      Display: <a href='javascript:void(0)' onclick='spoiler.setMode(\"spoiler\")' mode='spoiler' class='activeSort' title='Display all card information'>Spoiler</a>" +
138
139	        "      <a href='javascript:void(0)' onclick='spoiler.setMode(\"images\")' mode='images' title='Display card images only'>Images</a>" +
140
141            "   </div>" : "" ) +
142
143	        "   <div class='spoiler-sort'>" +
144
145	        "      Sort by: <a href='javascript:void(0)' onclick='spoiler.sort(\"color\")' sort='color' title='Sort by color, then name'>Color</a>" +
146
147	        "      <a href='javascript:void(0)' onclick='spoiler.sort(\"rarity\")' sort='rarity' title='Sort by rarity, then color and name'>Rarity</a>" +
148
149	        "      <a href='javascript:void(0)' onclick='spoiler.sort(\"cmc\")' sort='cmc' title='Sort by converted mana cost, then color and name'>CMC</a>" +
150
151	        "      <a href='javascript:void(0)' onclick='spoiler.sort(\"name\")' class='activeSort' sort='name' title='Sort by name'>Name</a>" +
152
153	        "      <a href='javascript:void(0)' onclick='spoiler.sort(\"random\")' sort='random' title='Sort randomly'>Randomly</a>" +
154
155	        "   </div>" +
156
157	        "   <div class='spoiler-filters spoiler-filters-rarity'>" +
158
159	        "      Rarity filter: <a href='javascript:void(0)' onclick='spoiler.filterByRarity(\"M\")' filter='M' title='Mythic rares only'>M</a>" +
160
161	        "      <a href='javascript:void(0)' onclick='spoiler.filterByRarity(\"R\")' filter='R' title='Rares only'>R</a>" +
162
163	        "      <a href='javascript:void(0)' onclick='spoiler.filterByRarity(\"U\")' filter='U' title='Uncommons only'>U</a>" +
164
165	        "      <a href='javascript:void(0)' onclick='spoiler.filterByRarity(\"C\")' filter='C' title='Commons only'>C</a>" +
166
167	        "      <a href='javascript:void(0)' onclick='spoiler.filterByRarity(\"S\")' filter='S' title='Special only'>S</a>" +
168
169	        "   </div>" +
170
171	        "   <div class='spoiler-filters spoiler-filters-color'>" +
172
173	        "      Color filter: <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"W\")' filter='W' title='White cards only'><span class='icon-wrapper'><i class='mtg white'></i></span></a>" +
174
175	        "      <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"U\")' filter='U' title='Blue cards only'><span class='icon-wrapper'><i class='mtg blue'></i></span></a>" +
176
177	        "      <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"B\")' filter='B' title='Black cards only'><span class='icon-wrapper'><i class='mtg black'></i></span></a>" +
178
179	        "      <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"R\")' filter='R' title='Red cards only'><span class='icon-wrapper'><i class='mtg red'></i></span></a>" +
180
181	        "      <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"G\")' filter='G' title='Green cards only'><span class='icon-wrapper'><i class='mtg green'></i></span></a>" +
182
183	        "      <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"M\")' filter='M' title='Multicolor cards only'><span class='icon-wrapper'><i class='mtg hybrid-wu'></i></span></a>" +
184
185	        "      <a href='javascript:void(0)' onclick='spoiler.filterByColor(\"1\")' filter='1' title='Colorless cards only'><span class='icon-wrapper'><i class='mtg mana-1'></i></span></a>" +
186
187	        "   </div>" +
188
189	        "   <div class='spoiler-filters spoiler-filters-type'>" +
190
191	        "      Type filter: <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Artifact\")' filter='Artifact' title='Artifacts only'>Artifact</a>" +
192
193	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Creature\")' filter='Creature' title='Creatures only'>Creature</a>" +
194
195	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Enchantment\")' filter='Enchantment' title='Enchantments only'>Enchantment</a>" +
196
197	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Instant\")' filter='Instant' title='Instants only'>Instant</a>" +
198
199	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Land\")' filter='Land' title='Lands only'>Land</a>" +
200
201	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Planeswalker\")' filter='Planeswalker' title='Planeswalkers only'>Planeswalker</a>" +
202
203	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Sorcery\")' filter='Sorcery' title='Sorceries only'>Sorcery</a>" +
204
205	        "      <a href='javascript:void(0)' onclick='spoiler.filterByType(\"Token\")' filter='Token' title='Tokens only'>Token</a>" +
206
207	        "   </div>" +
208
209	        "</div>" +
210
211	        "<br />" +
212
213	        "<hr class='card-separator' />" +
214
215	        "<div class='spoiler-cards'></div>");
216
217	}
218
219	else {
220
221		this.mainElement.html("<div class='spoiler-cards'></div>");
222
223	}
224
225
226
227    this.cardsElement = $(".spoiler-cards", this.mainElement);
228
229}
230
231
232
233Spoiler.prototype.initializeCardElements = function () {
234
235    this.imageCardElements = new Array();
236
237    this.spoilerCardElements = new Array();
238
239    
240
241    this.mode = "spoiler";
242
243    
244
245    for (var i = 0; i < this.data.length; i++) {
246
247        var card = this.data[i];
248
249
250
251        this.imageCardElements[card.cardId] = $("" +
252
253        	"<a href='" + card.url + "'><img src='" + card.artUrl + "' alt='" + card.name + "' class='card-image card-image-" + card.shape + "' /></a>");
254
255        
256
257        this.spoilerCardElements[card.cardId] = $("" +
258
259            "<table class='card-detail shape-" + card.shape + "'>" +
260
261            "   <tr>" +
262
263            "       <td class='card-image-day card-front' rowspan='15'><div class='lazyload' data-original='" + card.artUrl + "'></td>" +
264
265            (card.shape == "flip" || card.shape == "double" ? "<td class='card-image-night card-back' rowspan='15'><div class='lazyload' data-original='" + card.artUrl + "'></td>" : "") +
266
267            "       <td class='card-main-row card-front'><div class='card-name'><a href='" + card.url + "'>" + card.name + "</a> " + (this.showVersion ? "<span class='card-set-version'>(" + card.setVersionLink + ")</span>" : "") +"</div>" + (card.manaCost != null ?"<div class='card-cost'>" + card.manaCost + "</div></td>" : "</td>")+            
268
269            "   </tr>" +
270
271            "   <tr>" +
272
273            "       <td class='card-type-row card-front'><div class='card-types'>" + card.types + "</div><div class='card-rarity card-rarity-" + card.rarity.toLowerCase() +"'>" + card.rarityName + "</div></td>" +
274
275            "   </tr>" +
276
277            "   <tr>" +
278
279            "       <td class='card-rules-row card-front'><div class='card-rules'>" + card.rulesText + "</div></td>" +
280
281            "   </tr>" +
282
283            (card.flavorText != null ? "   <tr>" +
284
285            "       <td class='card-flavor-row card-front'><div class='card-flavor'>" + card.flavorText + "</div></td>" +
286
287            "   </tr>" : "") +
288
289            (card.ptString != null ? "   <tr>" +
290
291            "       <td class='card-pt-row card-front'><div class='card-pt'>" + card.ptString + "</div></td>" +
292
293            "   </tr>" : "") +
294
295            (card.name2 != "" ?
296
297                "   <tr>" +
298
299                "       <td class='card-separator-row'><hr /></td>" +
300
301                "   </tr>" +
302
303                "   <tr>" +
304
305                "       <td class='card-main-row card-back'><div class='card-name'><a href='" + card.url + "'>" + card.name2 + "</a></div>" + (card.manaCost2 != null ?"<div class='card-cost'>" + card.manaCost2 + "</div></td>" : "</td>")+
306
307                "   </tr>" +
308
309                "   <tr>" +
310
311                "       <td class='card-type-row card-back'><div class='card-types'>" + card.types2 + "</div><div class='card-rarity card-rarity-" + card.rarity.toLowerCase() +"'>" + card.rarityName + "</div></td>" +
312
313                "   </tr>" +
314
315                "   <tr>" +
316
317                "       <td class='card-rules-row card-back'><div class='card-rules'>" + card.rulesText2 + "</div></td>" +
318
319                "   </tr>" +
320
321                (card.flavorText2 != null ? "   <tr>" +
322
323                "       <td class='card-flavor-row card-back'><div class='card-flavor'>" + card.flavorText2 + "</div></td>" +
324
325                "   </tr>" : "") +
326
327                (card.ptString2 != null ? "   <tr>" +
328
329                "       <td class='card-pt-row card-back'><div class='card-pt'>" + card.ptString2 + "</div></td>" +
330
331                "   </tr>" : "")
332
333            : "") +
334
335            (this.enableLinks ?
336
337	            "   <tr>" +
338
339	            "       <td class='card-filler-row'>" +
340
341	            "			<a href='javascript:void(0)' onclick='spoiler.copyAsBBCode(\"" + card.name + "\")'>Copy as forum code</a>" + 
342
343	    		"			<a href='javascript:void(0)' onclick='spoiler.copyUrl(\"" + card.name + "\")'>Copy permalink</a>" +
344
345	    		"			<a href='javascript:void(0)' onclick='spoiler.copyArtUrl(\"" + card.name + "\")'>Copy image URL</a>" +
346
347	    		"		</td>" +
348
349	            "   </tr>"
350
351            : "") +
352
353            "</table><hr class='card-separator' />"
354
355
356
357        );
358
359        
360
361        if(!this.enableLinks){
362
363        	$('a', this.spoilerCardElements[card.cardId]).each(function(){
364
365                $(this).replaceWith( this.childNodes );
366
367            });
368
369        }
370
371    }
372
373}
374
375
376
377Spoiler.prototype.initializeSorting = function () {
378
379	if(this.enableControl){
380
381		this.order = "color";
382
383	}    
384
385	else {
386
387		this.order = "sequence";
388
389	}
390
391
392
393	var modifierFunction = function(x) {
394
395    	var modifier = 0;
396
397    	if(x.types.indexOf("Basic") !== -1 && x.types.indexOf("Land") !== -1) modifier = 50;
398
399    	if(x.types.indexOf("Token") !== -1 || x.types.indexOf("Emblem") !== -1) modifier = 100;
400
401    	return modifier;
402
403	}
404
405	
406
407    this.sortFunctions = {
408
409        "color": function(spoiler, a, b) {
410
411            var rate = function(x) {
412
413            	var modifier = modifierFunction(x);
414
415            	if (x.colors.length == 0 && x.rarity == 'B') return 8 + modifier;
416
417            	else if (x.colors.length == 0 && x.types.indexOf("Artifact") == -1) return 7 + modifier;
418
419                else if (x.colors.length == 0 && x.types.indexOf("Artifact") != -1) return 6 + modifier;
420
421                else if (x.colors.length > 1) return 5 + modifier;
422
423                else if (x.colors[0] == 'G') return 4 + modifier;
424
425                else if (x.colors[0] == 'R') return 3 + modifier;
426
427                else if (x.colors[0] == 'B') return 2 + modifier;
428
429                else if (x.colors[0] == 'U') return 1 + modifier;
430
431                else if (x.colors[0] == 'W') return 0 + modifier;
432
433                else throw "Not reached " + x.colors[0];
434
435            }
436
437
438
439            var ratingA = rate(a);
440
441            var ratingB = rate(b);
442
443
444
445            if (ratingA == ratingB) return a.name.localeCompare(b.name);
446
447            else return ratingA - ratingB;
448
449        },
450
451        "rarity": function (spoiler, a, b) {
452
453            var rate = function (x) {
454
455            	var modifier = modifierFunction(x);
456
457                if (x.rarity == 'T') return 7 + modifier;
458
459                else if (x.rarity == 'B') return 6 + modifier;
460
461                else if (x.rarity == 'S') return 5 + modifier;
462
463                else if (x.rarity == 'C') return 4 + modifier;
464
465                else if (x.rarity == 'U') return 3 + modifier;
466
467                else if (x.rarity == 'R') return 2 + modifier;
468
469                else if (x.rarity == 'M') return 1 + modifier;
470
471                else throw "Not reached \"" + x.rarity + "\"";
472
473            }
474
475
476
477            var ratingA = rate(a);
478
479            var ratingB = rate(b);
480
481
482
483
484
485            if (ratingA == ratingB) return spoiler.sortFunctions["color"](spoiler, a, b);
486
487            else return ratingA - ratingB;
488
489        },
490
491        "cmc": function (spoiler, a, b) {
492
493            var ratingA = a.cmc != null ? (a.rarity != 'B' ? a.cmc : -2) : -1;
494
495            var ratingB = b.cmc != null ? (b.rarity != 'B' ? b.cmc : -2) : -1;
496
497
498
499            if (ratingA == ratingB) return spoiler.sortFunctions["color"](spoiler, a, b);
500
501            else return ratingA - ratingB;
502
503        },
504
505        "name": function (spoiler, a, b) {
506
507            return a.name.localeCompare(b.name);
508
509        },
510
511        "sequence": function (spoiler, a, b) {
512
513            return a.id - b.id;
514
515        },
516
517        "random": function (spoiler, a, b) {
518
519            return spoiler.alea() - spoiler.alea();
520
521        },
522
523    };
524
525
526
527}
528
529
530
531Spoiler.prototype.initializeFilters = function() {
532
533    this.rarityFilter = null;
534
535    this.typeFilter = null;
536
537    this.colorFilter = null;
538
539}
540
541
542
543Spoiler.prototype.sort = function (sortFunction) {
544
545    this.order = sortFunction;
546
547    this.redraw();
548
549    $('.activeSort', $(".spoiler-sort", this.mainElement)).removeClass('activeSort');
550
551    $("[sort='" + this.order + "']", $(".spoiler-sort", this.mainElement)).addClass('activeSort');
552
553}
554
555
556
557Spoiler.prototype.filterByRarity = function (filterValue) {
558
559    if (filterValue == this.rarityFilter) {
560
561        this.rarityFilter = null;
562
563    } else {
564
565        this.rarityFilter = filterValue;
566
567    }
568
569
570
571    this.redraw();
572
573
574
575    $('.activeSort', $(".spoiler-filters-rarity", this.mainElement)).removeClass('activeSort');
576
577    $("[filter='" + this.rarityFilter + "']", $(".spoiler-filters-rarity", this.mainElement)).addClass('activeSort');
578
579}
580
581
582
583Spoiler.prototype.filterByType = function (filterValue) {
584
585    if (filterValue == this.typeFilter) {
586
587        this.typeFilter = null;
588
589    } else {
590
591        this.typeFilter = filterValue;
592
593    }
594
595
596
597    this.redraw();
598
599
600
601    $('.activeSort', $(".spoiler-filters-type", this.mainElement)).removeClass('activeSort');
602
603    $("[filter='" + this.typeFilter + "']", $(".spoiler-filters-type", this.mainElement)).addClass('activeSort');
604
605}
606
607
608
609Spoiler.prototype.filterByColor = function (filterValue) {
610
611    if (filterValue == this.colorFilter) {
612
613        this.colorFilter = null;
614
615    } else {
616
617        this.colorFilter = filterValue;
618
619    }
620
621
622
623    this.redraw();
624
625
626
627    $('.activeSort', $(".spoiler-filters-color", this.mainElement)).removeClass('activeSort');
628
629    $("[filter='" + this.colorFilter + "']", $(".spoiler-filters-color", this.mainElement)).addClass('activeSort');
630
631}
632
633
634
635Spoiler.prototype.setMode = function (mode) {
636
637    this.mode = mode;
638
639
640
641    this.redraw();
642
643
644
645    $('.activeSort', $(".spoiler-mode", this.mainElement)).removeClass('activeSort');
646
647    $("[mode='" + this.mode + "']", $(".spoiler-mode", this.mainElement)).addClass('activeSort');
648
649}
650
651
652
653Spoiler.prototype.getCardByName = function (cardName) {
654
655    var card;
656
657    for (var i = 0; i < this.data.length; i++) {
658
659        if (this.data[i].name == cardName) return this.data[i];
660
661    }
662
663
664
665    return null;
666
667}
668
669
670
671Spoiler.prototype.copyArtUrl = function(cardName) {
672
673	var card = this.getCardByName(cardName);
674
675    showCopyable(card.artUrl);
676
677    return false;
678
679};
680
681
682
683
684
685Spoiler.prototype.copyUrl = function(cardName) {
686
687	var card = this.getCardByName(cardName);
688
689    showCopyable(card.url);
690
691    return false;
692
693};
694
695
696
697//In-built replace is dumb and replaces only one occurence
698
699Spoiler.prototype.smartReplace = function (haystack, needle, replace) {
700
701    return haystack.replace(new RegExp(needle, 'g'), replace);
702
703}
704
705
706
707Spoiler.prototype.copyAsBBCode = function (cardName) {
708
709	var card = this.getCardByName(cardName);
710
711
712
713    showCopyable(card.bbCode);
714
715}
716
717
718
719Spoiler.prototype.copyAsBBLink = function (cardName) {
720
721    var bbCode = (this.localUrl != null ? "[url=" + this.localUrl + "#" + cardName + "]" + cardName + "[/url]" : cardName);
722
723    showCopyable(bbCode);
724
725}
726
727
728
729Spoiler.prototype.redraw = function () {
730
731    console.log("redraw mobile: ", isMobileView());
732
733
734
735    this.cardsElement.empty();
736
737
738
739    var spoiler = this;
740
741
742
743    this.resetSeed();
744
745
746
747    // Presort the data so that random sort has predicatable initial state
748
749    this.data.sort(function(a, b) { return a.name.localeCompare(b.name); });
750
751
752
753    this.data.sort(function (a, b) {
754
755        return spoiler.sortFunctions[spoiler.order](spoiler, a, b);
756
757    });
758
759
760
761    for (var i = 0; i < this.data.length; i++) {
762
763        var card = this.data[i];
764
765
766
767        var include = true;
768
769
770
771        if (this.rarityFilter != null) {
772
773            if (this.rarityFilter != card.rarity) {
774
775                include = false;
776
777            }
778
779        }
780
781
782
783        if (this.typeFilter != null) {
784
785            if (card.types.indexOf(this.typeFilter) == -1 && card.types2.indexOf(this.typeFilter) == -1) {
786
787                include = false;
788
789            }
790
791        }
792
793
794
795        if (this.colorFilter != null) {
796
797            if (this.colorFilter == "1") {
798
799                if (card.colors.length > 0) include = false;
800
801            }
802
803            else if (this.colorFilter == "M") {
804
805                if (card.colors.length < 2) include = false;
806
807            } else {
808
809                if (card.colors.indexOf(this.colorFilter) == -1) {
810
811                    include = false;
812
813                }
814
815            }
816
817        }
818
819        
820
821        if (include) {
822
823        	if(this.mode == "spoiler" && !isMobileView()){
824
825        		this.cardsElement.append(this.spoilerCardElements[card.cardId]);
826
827        	}            
828
829        	else {
830
831        		this.cardsElement.append(this.imageCardElements[card.cardId]);
832
833        	}
834
835        }        
836
837    }
838
839    
840
841    this.lazyload = $(".lazyload", this.mainElement).lazyload({
842
843    	effect : "fadeIn",
844
845        skip_invisible : true
846
847	});
848
849    
850
851    $(window).scroll();
852
853    
854
855    //if(this.lazyload) this.lazyload.update();
856
857    //$(window).trigger('resize');
858
859}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.