in src/VisualMain.ts [54:188]
constructor(options: VisualConstructorOptions) {
this.host = options.host;
this.selectionManager = options.host.createSelectionManager();
this.context = {
enableBlurFix: true,
// enableBlurFix: (anyData.dsr.wireContracts !== undefined), // this check isn't working in sand-box mode
previewId: "preview-" + this.host.instanceId,
metadataId: "metadata-" + this.host.instanceId
};
this.$element = $(visualTemplate(this.context)).appendTo(options.element);
this.$loaderElement = $(loaderTemplate());
this.cards = new Cards();
this.$container = this.$element.find(".container");
this.$container.append(this.cards.render());
this.cards.on(`${EVENTS.CARD_CLICK}`, card => {
if (!card.isExpanded) {
this.cards.updateReaderContent(card, card.data);
this.cards.openReader(card);
this.applySelection(card.data);
}
});
this.cards.on(EVENTS.VERTICAL_READER_NAVIGATE_CARD, card => {
this.cards.updateReaderContent(card, card.data);
});
this.cards.on(
`${EVENTS.READER_CONTENT_CLICK_CLOSE} ${EVENTS.CARDS_CLICK_BACKGROUND} ${
EVENTS.VERTICAL_READER_CLICK_BACKGROUND
}`,
() => {
this.cards.closeReader();
this.applySelection(null);
}
);
// close the reader when clicked above
this.$element.find(".flip-panel").on("click", event => {
if ($(event.target).hasClass("flip-panel")) {
// When the outside portion of the flip panel (that centers the switch) is clicked,
// close the reader
this.cards.closeReader();
}
});
// Flipping cards involves two hacks:
// ... 1. IE11 doesn't behave well, so we skip the transition altogether there
const isIE11 = !!navigator.userAgent.match(/Trident\/7\./);
const isSafari = /.*AppleWebKit(?!.*Chrome)/i.test(navigator.userAgent);
const isIOS = /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent);
const isNativeAndroidApp = /AppName\/[0-9\.]+$/.test(navigator.userAgent);
const onChange =
isIE11 || isSafari || isIOS
? () => {
this.cards.cardInstances.forEach(card => card.flip(this.isFlipped));
}
: () => {
// ... 2. Text is blurry if certain animation-oriented CSS fx are permanently set, so only turn them on during the transition
this.$container.toggleClass("cards-flipped", !this.isFlipped);
this.$container.addClass("animating");
setTimeout(() => {
this.cards.cardInstances.forEach(card =>
card.flip(this.isFlipped)
);
setTimeout(
() => this.$container.removeClass("animating cards-flipped"),
constants.FLIP_ANIMATION_DURATION
);
}, 50);
};
const onInput = event => {
if (this.cards.cardInstances && this.cards.cardInstances.length) {
this.isFlipped = event.currentTarget.id === this.context.metadataId;
this.updateFlipButton();
onChange();
return false;
}
};
this.$element.find("input").on("change", onInput);
if (isIOS || isNativeAndroidApp) {
this.$element.toggleClass("mobile", true);
}
// set up infinite scroll
let infiniteScrollTimeoutId: any;
const findApi = methodName => {
return this.host[methodName]
? arg => {
this.host[methodName](arg);
}
: this.host && this.host[methodName]
? arg => {
this.host[methodName](arg);
}
: null;
};
this.loadMoreData = findApi("fetchMoreData");
this.launchUrl = findApi("launchUrl");
this.launchUrl &&
this.cards.on(
`${EVENTS.CARD_CLICK_LINK} ${EVENTS.READER_CONTENT_CLICK_LINK}`,
event => {
this.launchUrl(event.currentTarget.href);
}
);
this.cards.on(
`${EVENTS.INLINE_CARDS_VIEW_SCROLL_END} ${
EVENTS.WRAPPED_CARDS_VIEW_SCROLL_END
}`,
debounce(() => {
infiniteScrollTimeoutId = setTimeout(() => {
clearTimeout(infiniteScrollTimeoutId);
if (!this.isLoadingMore && this.hasMoreData && this.loadMoreData) {
this.isLoadingMore = true;
this.showLoader();
this.loadMoreData();
}
}, constants.INFINITE_SCROLL_DELAY);
})
);
this.selectionManager["registerOnSelectCallback"]((ids: ISelectionId[]) => {
this.loadSelectionFromPowerBI(ids);
});
}