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

fix: fix that element has loading image #3 #5

Merged
merged 4 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/ImReadyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ MIT license
import Component from "@egjs/component";
import { ElementLoader } from "./loaders/ElementLoader";
import { ArrayFormat, ElementInfo, ImReadyEvents, ImReadyLoaderOptions, ImReadyOptions } from "./types";
import { hasSkipAttribute, toArray, getContentElements } from "./utils";
import { hasSkipAttribute, toArray, getContentElements, hasLoadingAttribute } from "./utils";
/**
* @alias eg.ImReady
* @extends eg.Component
Expand Down Expand Up @@ -165,6 +165,9 @@ class ImReadyManager extends Component<ImReadyEvents> {
return new loaders[tagName](element, options);
}
const loader = new ElementLoader(element, options);
const children = toArray(element.querySelectorAll<HTMLElement>(tags.join(", ")));

loader.setHasLoading(children.some(el => hasLoadingAttribute(el)));
let withPreReady = false;

const childrenImReady = this.clone().on("error", e => {
Expand All @@ -175,9 +178,9 @@ class ImReadyManager extends Component<ImReadyEvents> {

loader.on("requestChildren", () => {
// has not data size
const children = getContentElements(element, tags, this.options.prefix);
const contentElements = getContentElements(element, tags, this.options.prefix);

childrenImReady.check(children).on("preReady", e => {
childrenImReady.check(contentElements).on("preReady", e => {
withPreReady = e.isReady;
if (!withPreReady) {
loader.onPreReady();
Expand All @@ -187,8 +190,6 @@ class ImReadyManager extends Component<ImReadyEvents> {
// has data size
// loader call preReady
// check only video, image elements
const children = toArray(element.querySelectorAll<HTMLElement>(tags.join(", ")));

childrenImReady.check(children);
}).on("requestDestroy", () => {
childrenImReady.destroy();
Expand Down
3 changes: 3 additions & 0 deletions src/loaders/ElementLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export class ElementLoader<T extends HTMLElement> extends Loader<T> {
public static EVENTS: string[] = [];
public options!: ImReadyLoaderOptions;

public setHasLoading(hasLoading: boolean) {
this.hasLoading = hasLoading;
}
public checkElement() {
if (!this.hasDataSize) {
// has not data size
Expand Down
6 changes: 1 addition & 5 deletions src/loaders/ImageLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ import Loader from "./Loader";

export default class ImageLoader extends Loader<HTMLImageElement> {
public static EVENTS = ["load", "error"];
public isPreReady() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has the interface changed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mixed

loader is a class that can only be used inside, this method is used internally.

const element = this.element;
return element.complete && (!IS_IE || (IS_IE && !!element.naturalWidth));
}
public checkElement() {
const element = this.element;
if (this.isPreReady()) {
if (element.complete && (!IS_IE || !!element.naturalWidth)) {
if (!element.naturalWidth) {
this.onAlreadyError(this.element);
}
Expand Down
16 changes: 12 additions & 4 deletions src/loaders/Loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default abstract class Loader<T extends HTMLElement = any> extends Compon
public abstract checkElement(): boolean;
protected element!: T;
protected isReady = false;
protected isPreReady = false;
protected hasDataSize = false;
protected hasLoading = false;

Expand All @@ -38,16 +39,13 @@ export default abstract class Loader<T extends HTMLElement = any> extends Compon
if (this.hasDataSize) {
addAutoSizer(this.element, this.options.prefix);
}
if (this.hasDataSize || this.hasLoading || this.isPreReady()) {
if (this.hasDataSize || this.hasLoading) {
// I'm Pre Ready
this.onAlreadyPreReady();
}
// Wati Pre Ready, Ready
return true;
}
public isPreReady() {
return false;
}
public addEvents() {
const element = this.element;
(this.constructor as typeof Loader).EVENTS.forEach(name => {
Expand Down Expand Up @@ -88,12 +86,22 @@ export default abstract class Loader<T extends HTMLElement = any> extends Compon
});
}
public onPreReady() {
if (this.isPreReady) {
return;
}
this.isPreReady = true;
this.trigger("preReady", {
element: this.element,
hasLoading: this.hasLoading,
});
}
public onReady(withPreReady: boolean) {
if (this.isReady) {
return;
}
if (withPreReady) {
this.isPreReady = true;
}
this.removeAutoSizer();
this.isReady = true;
this.trigger("ready", {
Expand Down
59 changes: 47 additions & 12 deletions test/unit/Image.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { sandbox, cleanup, waitEvent, waitFor, getSize, checkEventOrders, expectOrders } from "./utils";
import { sandbox, cleanup, waitEvent, getSize, checkEventOrders, expectOrders } from "./utils";
import ImReady from "../../src/index";
import { spy } from "sinon";
import { toArray, innerWidth, innerHeight } from "../../src/utils";

declare const viewport: any;

describe("Test image", () => {
let el: HTMLElement;
let im: ImReady;
Expand Down Expand Up @@ -227,7 +225,7 @@ describe("Test image", () => {
"readyElement", "readyElement", "ready",
]);
});
it("should check that call preReady if include the loading attribute.", async () => {
it("should check that call preReady if include the loading img.", async () => {
// Given
el.innerHTML = `
<img src="https://naver.github.io/egjs-infinitegrid/assets/image/15.jpg" loading="lazy"/>
Expand All @@ -236,6 +234,42 @@ describe("Test image", () => {
const img = el.querySelector("img");

// inject loading attribute for not supported browser
img.setAttribute("loading", "lazy");
Object.defineProperty(img, "loading", {
value: "lazy",
});

const events = checkEventOrders(im);

// When
im.check([el]);

await waitEvent(im, "preReady");
const loadingSize = getSize(img);

await waitEvent(im, "ready");


// Then
expect(loadingSize).to.be.deep.equals([0, 0]);
// preReadyElement
expect(events[0].hasLoading).to.be.equals(true);
// preReady
expect(events[1].hasLoading).to.be.equals(true);
expectOrders(events, [
"preReadyElement", "preReady", "readyElement", "ready",
]);
});
it("should check that call preReady if include the loading attribute.", async () => {
// Given
el.innerHTML = `
<img src="https://naver.github.io/egjs-infinitegrid/assets/image/18.jpg" loading="lazy"/>
`;

const img = el.querySelector("img");

// inject loading attribute for not supported browser
img.setAttribute("loading", "lazy");
Object.defineProperty(img, "loading", {
value: "lazy",
});
Expand Down Expand Up @@ -275,11 +309,11 @@ describe("Test image", () => {
// maybe 400 x 400
const size1 = getSize(img);

viewport.set(600, 400);
// When the network state is too early, an finish event occurs in an instant.
await waitFor(60);
// The resize event is fired synchronously.
el.style.width = "90%";
window.dispatchEvent(new Event("resize"));

// maybe 600 x 600
// maybe 360 x 360
const size2 = getSize(img);

await waitEvent(im, "ready");
Expand Down Expand Up @@ -315,10 +349,11 @@ describe("Test image", () => {
const width1 = innerWidth(img);
const height1 = innerHeight(img);

viewport.set(400, 600);
// When the network state is too early, an finish event occurs in an instant.
await waitFor(60);
// window size 600
// The resize event is fired synchronously.
el.style.height = "90%";
window.dispatchEvent(new Event("resize"));

// maybe 270 x 270
const width2 = innerWidth(img);
const height2 = innerHeight(img);

Expand Down
22 changes: 11 additions & 11 deletions test/unit/video.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { sandbox, cleanup, waitEvent, waitFor, getSize } from "./utils";
import { sandbox, cleanup, waitEvent, getSize } from "./utils";
import ImReady from "../../src/index";
import { spy } from "sinon";
import { toArray, innerWidth, innerHeight } from "../../src/utils";

declare const viewport: any;

describe("Test video", () => {
let el: HTMLElement;
let im: ImReady;
Expand Down Expand Up @@ -208,11 +206,12 @@ describe("Test video", () => {
// maybe 400 x 400
const size1 = getSize(video);

viewport.set(600, 400);
// When the network state is too early, an finish event occurs in an instant.
await waitFor(60);

// maybe 600 x 600
// The resize event is fired synchronously.
el.style.width = "90%";
window.dispatchEvent(new Event("resize"));

// maybe 360 x 360
const size2 = getSize(video);

await waitEvent(im, "ready");
Expand Down Expand Up @@ -248,10 +247,11 @@ describe("Test video", () => {
const width1 = innerWidth(video);
const height1 = innerHeight(video);

viewport.set(400, 600);
// When the network state is too early, an finish event occurs in an instant.
await waitFor(60);
// window size 600
// The resize event is fired synchronously.
el.style.height = "90%";
window.dispatchEvent(new Event("resize"));

// maybe 270 x 270
const width2 = innerWidth(video);
const height2 = innerHeight(video);

Expand Down