Skip to content
This repository was archived by the owner on Feb 25, 2018. It is now read-only.

Commit 8ef64e8

Browse files
committed
Improve JS performance.
This improves performance of the polyfill a lot further. Still, the polyfill doesn’t really behave well when a huge CSS is applied or a huge amount of images is selected as target. This also adds a medium stylesheet that performs relatively well now.
1 parent 474e8fd commit 8ef64e8

10 files changed

+11103
-79
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@
66

77
node_modules
88
components
9-
tests
109
index.html
1110

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ For example you need to set the header to:
8585

8686
This should fix [the issue](https://github.com/anselmh/object-fit/issues/7). If you also need to support credentials, [you can’t use `*`](#25) but need the server reply with two headers (server needs also to reply with `Access-Control-Allow-Credentials: true`), one of which includes the origin in question.
8787

88-
It is recommended to add the attribute `crossorigin="use-credentials"` to your CSS `link` element that is called from the external resource to indicate what type of CORS the server should reply with.
88+
It is recommended to add the attribute `crossorigin=""` to your CSS `link` element that is called from the external resource to indicate what type of CORS the server should reply with.
8989

9090
In case you can’t alter the CSP / CORS settings of the server in question, you can disable parsing external CSS files in the config of the call:
9191

dist/polyfill.object-fit.js

+67-36
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@
2727
// convert an array-like object to array
2828
var toArray = function (list) {
2929
var items = [];
30-
var i;
30+
var i = 0;
31+
var listLength = list.length;
3132

32-
for (i in list) {
33+
for (; i < listLength; i++) {
3334
items.push(list[i]);
3435
}
3536

@@ -39,7 +40,9 @@
3940
// get host of stylesheet
4041
var getCSSHost = function (href) {
4142
var fakeLinkOfSheet = document.createElement('a');
43+
4244
fakeLinkOfSheet.href = href;
45+
4346
return fakeLinkOfSheet.host;
4447
};
4548

@@ -148,19 +151,19 @@
148151
return rules.sort(compareSpecificity);
149152
};
150153

151-
// Find correct matchesSelector implementation
152-
var _matchesSelector = function (element, selector) {
153-
if (!element.matches || !element.matchesSelector || !element.webkitMatchesSelector || !element.mozMatchesSelector || !element.msMatchesSelector) {
154-
var matches = (element.document || element.ownerDocument).querySelectorAll(selector);
155-
var i = 0;
154+
var customMatchesSelector = function (element, selector) {
155+
var matches = (element.document || element.ownerDocument).querySelectorAll(selector);
156+
var i = 0;
156157

157-
while (matches[i] && matches[i] !== element) {
158-
i++;
159-
}
160-
161-
matches[i] ? true : false;
158+
while (matches[i] && matches[i] !== element) {
159+
i++;
162160
}
163161

162+
return matches[i] ? true : false;
163+
};
164+
165+
// Find correct matchesSelector implementation
166+
var _matchesSelector = function (element, selector) {
164167
var matcher = function (selector) {
165168
if (element.matches) {
166169
return element.matches(selector);
@@ -172,6 +175,8 @@
172175
return element.webkitMatchesSelector(selector);
173176
} else if (element.msMatchesSelector) {
174177
return element.msMatchesSelector(selector);
178+
} else {
179+
return customMatchesSelector(element, selector);
175180
}
176181
};
177182

@@ -310,9 +315,16 @@
310315

311316
var defaultElement = iframe.contentWindow.document.querySelectorAll(element.nodeName.toLowerCase())[0];
312317
var defaultComputedStyle = this.getComputedStyle(defaultElement, iframe.contentWindow);
318+
var value;
319+
var property;
320+
321+
for (property in defaultComputedStyle) {
322+
if (defaultComputedStyle.getPropertyValue === true) {
323+
value = defaultComputedStyle.getPropertyValue(property);
324+
} else {
325+
value = defaultComputedStyle[property];
326+
}
313327

314-
for (var property in defaultComputedStyle) {
315-
var value = defaultComputedStyle.getPropertyValue ? defaultComputedStyle.getPropertyValue(property) : defaultComputedStyle[property];
316328
if (value !== null) {
317329
switch (property) {
318330
default:
@@ -348,14 +360,16 @@
348360

349361
// get matched rules
350362
var rules = window.getMatchedCSSRules(element);
363+
var i = rules.length;
364+
var r;
365+
var important;
351366

352-
if (rules.length) {
367+
if (i) {
353368
// iterate the rules backwards
354369
// rules are ordered by priority, highest last
355-
for (var i = rules.length; i --> 0;){
356-
var r = rules[i];
357-
358-
var important = r.style.getPropertyPriority(property);
370+
for (; i --> 0;) {
371+
r = rules[i];
372+
important = r.style.getPropertyPriority(property);
359373

360374
// if set, only reset if important
361375
if (val === null || important) {
@@ -365,7 +379,6 @@
365379
if (important) {
366380
break;
367381
}
368-
//return val;
369382
}
370383
}
371384
}
@@ -390,6 +403,7 @@
390403
if (replacedElement.getAttribute('data-x-object-relation') !== 'wider') {
391404
replacedElement.setAttribute('data-x-object-relation','wider');
392405
replacedElement.className = 'x-object-fit-wider';
406+
393407
if (this._debug && window.console) {
394408
console.log('x-object-fit-wider');
395409
}
@@ -398,6 +412,7 @@
398412
if (replacedElement.getAttribute('data-x-object-relation') !== 'taller') {
399413
replacedElement.setAttribute('data-x-object-relation','taller');
400414
replacedElement.className = 'x-object-fit-taller';
415+
401416
if (this._debug && window.console) {
402417
console.log('x-object-fit-taller');
403418
}
@@ -441,24 +456,26 @@
441456
};
442457

443458
objectFit.processElement = function(replacedElement, args) {
444-
var property, value;
445-
459+
var property;
460+
var value;
446461
var replacedElementStyles = objectFit.getComputedStyle(replacedElement);
447462
var replacedElementDefaultStyles = objectFit.getDefaultComputedStyle(replacedElement);
448-
449463
var wrapperElement = document.createElement('x-object-fit');
450464

451465
if (objectFit._debug && window.console) {
452466
console.log('Applying to WRAPPER-------------------------------------------------------');
453467
}
468+
454469
for (property in replacedElementStyles) {
455470
switch (property) {
456471
default:
457-
value = objectFit.getMatchedStyle(replacedElement,property);
472+
value = objectFit.getMatchedStyle(replacedElement, property);
473+
458474
if (value !== null && value !== '') {
459475
if (objectFit._debug && window.console) {
460476
console.log(property + ': ' + value);
461477
}
478+
462479
wrapperElement.style[property] = value;
463480
}
464481
break;
@@ -484,6 +501,7 @@
484501
console.log('Indexed style properties (`' + property + '`) not supported in: ' + window.navigator.userAgent);
485502
}
486503
}
504+
487505
if (replacedElement.style[property]) {
488506
replacedElement.style[property] = value; // should work in Firefox 35+ and all other browsers
489507
} else {
@@ -504,7 +522,7 @@
504522
objectFit.orientation(replacedElement);
505523

506524
var resizeTimer = null;
507-
var resizeAction = function(){
525+
var resizeAction = function () {
508526
if (resizeTimer !== null) {
509527
window.cancelAnimationFrame(resizeTimer);
510528
}
@@ -531,24 +549,28 @@
531549
}
532550
};
533551

534-
objectFit.listen = function(args) {
535-
var domInsertedAction = function(element){
536-
for (var i = 0, argsLength = args.length; i < argsLength; i++) {
552+
objectFit.listen = function (args) {
553+
var domInsertedAction = function (element){
554+
var i = 0;
555+
var argsLength = args.length;
556+
557+
for (; i < argsLength; i++) {
537558
if ((element.mozMatchesSelector && element.mozMatchesSelector(args[i].selector)) ||
538559
(element.msMatchesSelector && element.msMatchesSelector(args[i].selector)) ||
539560
(element.oMatchesSelector && element.oMatchesSelector(args[i].selector)) ||
540561
(element.webkitMatchesSelector && element.webkitMatchesSelector(args[i].selector))
541562
) {
542563
args[i].replacedElements = [element];
543564
objectFit.process(args[i]);
565+
544566
if (objectFit._debug && window.console) {
545567
console.log('Matching node inserted: ' + element.nodeName);
546568
}
547569
}
548570
}
549571
};
550572

551-
var domInsertedObserverFunction = function(element){
573+
var domInsertedObserverFunction = function (element) {
552574
objectFit.observer.disconnect();
553575
domInsertedAction(element);
554576
objectFit.observer.observe(document.documentElement, {
@@ -557,22 +579,23 @@
557579
});
558580
};
559581

560-
var domInsertedEventFunction = function(event){
582+
var domInsertedEventFunction = function (event) {
561583
window.removeEventListener('DOMNodeInserted', domInsertedEventFunction, false);
562584
domInsertedAction(event.target);
563585
window.addEventListener('DOMNodeInserted', domInsertedEventFunction, false);
564586
};
565587

566-
var domRemovedAction = function(element){
588+
var domRemovedAction = function (element) {
567589
if (element.nodeName.toLowerCase() === 'x-object-fit') {
568590
element.parentNode.removeChild(element);
591+
569592
if (objectFit._debug && window.console) {
570593
console.log('Matching node removed: ' + element.nodeName);
571594
}
572595
}
573596
};
574597

575-
var domRemovedObserverFunction = function(element){
598+
var domRemovedObserverFunction = function (element) {
576599
objectFit.observer.disconnect();
577600
domRemovedAction(element);
578601
objectFit.observer.observe(document.documentElement, {
@@ -581,7 +604,7 @@
581604
});
582605
};
583606

584-
var domRemovedEventFunction = function(event){
607+
var domRemovedEventFunction = function (event) {
585608
window.removeEventListener('DOMNodeRemoved', domRemovedEventFunction, false);
586609
domRemovedAction(event.target.parentNode);
587610
window.addEventListener('DOMNodeRemoved', domRemovedEventFunction, false);
@@ -591,6 +614,7 @@
591614
if (objectFit._debug && window.console) {
592615
console.log('DOM MutationObserver');
593616
}
617+
594618
this.observer = new MutationObserver(function(mutations) {
595619
mutations.forEach(function(mutation) {
596620
if (mutation.addedNodes && mutation.addedNodes.length) {
@@ -604,6 +628,7 @@
604628
}
605629
});
606630
});
631+
607632
this.observer.observe(document.documentElement, {
608633
childList: true,
609634
subtree: true
@@ -612,32 +637,38 @@
612637
if (objectFit._debug && window.console) {
613638
console.log('DOM Mutation Events');
614639
}
640+
615641
window.addEventListener('DOMNodeInserted', domInsertedEventFunction, false);
616642
window.addEventListener('DOMNodeRemoved', domRemovedEventFunction, false);
617643
}
618644
};
619645

620-
objectFit.init = function(args) {
646+
objectFit.init = function (args) {
621647
if (!args) {
622648
return;
623649
}
650+
624651
if (!(args instanceof Array)) {
625652
args = [args];
626653
}
627654

628-
for (var i = 0, argsLength = args.length; i < argsLength; i++) {
655+
var i = 0;
656+
var argsLength = args.length;
657+
658+
for (; i < argsLength; i++) {
629659
args[i].replacedElements = document.querySelectorAll(args[i].selector);
630660
this.process(args[i]);
631661
}
632662

633663
this.listen(args);
634664
};
635665

636-
objectFit.polyfill = function(args) {
666+
objectFit.polyfill = function (args) {
637667
if('objectFit' in document.documentElement.style === false) {
638668
if (objectFit._debug && window.console) {
639669
console.log('object-fit not natively supported');
640670
}
671+
641672
// If the library is loaded after document onload event
642673
if (document.readyState === 'complete') {
643674
objectFit.init(args);

0 commit comments

Comments
 (0)