@salla.sa/twilight-components
Version:
Salla Web Component
554 lines (553 loc) • 25.4 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import anime from "animejs";
import { h } from "@stencil/core";
import Images from "../../assets/svg/images.svg";
import LeftArrow from "../../assets/svg/arrow-left.svg";
import Cancel from "../../assets/svg/cancel.svg";
import GiftSharing from "../../assets/svg/gift-sharing.svg";
/**
* @slot widget-btn-content - Used to customize widget button content.
*/
export class SallaGifting {
constructor() {
this.defaultEvent = "gifting:open";
this.sectionTitle = undefined;
this.sectionSubtitle = undefined;
this.sectionBtnText = undefined;
this.giftDetails = undefined;
this.selectImageForYourGift = salla.lang.get('blocks.buy_as_gift.select_image_or_upload');
this.selectImageOrUpload = undefined;
this.selectGiftMessage = undefined;
this.giftCustomText = undefined;
this.textId = undefined;
this.incorrectGiftText = undefined;
this.nextStep = undefined;
this.senderNameLabel = undefined;
this.receiverNameFieldLabel = undefined;
this.receiverMobileFieldLabel = undefined;
this.receiverEmailFieldLabel = undefined;
this.emailPlaceholder = undefined;
this.sendLater = undefined;
this.selectSendDateAndTime = undefined;
this.canNotEditOrderAfterSelectDate = undefined;
this.sendGift = undefined;
this.donationRequired = undefined;
this.currentStep = 1;
this.showCalendar = false;
this.showGiftText = false;
this.currentLang = '';
this.parentClass = "is-current-step-1";
this.errors = {};
this.gift = undefined;
this.selectedGiftTextOption = undefined;
this.showTextArea = false;
this.selectedImage = undefined;
this.uploadedImage = undefined;
this.selectedText = undefined;
this.senderName = undefined;
this.errorMessage = undefined;
this.hasError = false;
this.quantity = undefined;
this.deliveryDate = undefined;
this.timeZone = null;
this.receiverName = undefined;
this.receiverMobile = undefined;
this.receiverCountryCode = undefined;
this.receiverEmail = undefined;
this.hostId = `salla-gifting-${Math.random().toString(36).slice(2, 10)}`;
this.productId = undefined;
this.widgetTitle = undefined;
this.widgetSubtitle = undefined;
salla.lang.onLoaded(() => {
this.selectImageOrUpload = salla.lang.get('blocks.buy_as_gift.select_image_or_upload');
this.selectImageForYourGift = salla.lang.get('blocks.buy_as_gift.select_image_for_your_gift');
this.sectionTitle = salla.lang.get('blocks.buy_as_gift.gift_the_one_you_love');
this.sectionSubtitle = salla.lang.get('blocks.buy_as_gift.gift_the_one_you_love_message');
this.sectionBtnText = salla.lang.get('blocks.buy_as_gift.send_as_a_gift');
this.giftDetails = salla.lang.get('blocks.buy_as_gift.gift_details');
this.selectGiftMessage = salla.lang.get('blocks.buy_as_gift.select_gift_message');
this.giftCustomText = salla.lang.get('blocks.buy_as_gift.gift_custom_text');
this.textId = salla.lang.get('blocks.buy_as_gift.text_id');
this.incorrectGiftText = salla.lang.get('blocks.buy_as_gift.incorrect_gift_text');
this.nextStep = salla.lang.get('blocks.buy_as_gift.next_step');
this.senderNameLabel = salla.lang.get('blocks.buy_as_gift.sender_name');
this.receiverNameFieldLabel = salla.lang.get('blocks.buy_as_gift.receiver_name');
this.receiverMobileFieldLabel = salla.lang.get('blocks.buy_as_gift.receiver_mobile');
this.receiverEmailFieldLabel = salla.lang.get('blocks.buy_as_gift.receiver_email');
this.emailPlaceholder = salla.lang.get('common.elements.email_placeholder');
this.sendLater = salla.lang.get('blocks.buy_as_gift.send_later');
this.selectSendDateAndTime = salla.lang.get('blocks.buy_as_gift.select_send_date_and_time');
this.canNotEditOrderAfterSelectDate = salla.lang.get('blocks.buy_as_gift.can_not_edit_order_after_select_date');
this.sendGift = salla.lang.get('blocks.buy_as_gift.send_gift');
this.donationRequired = salla.lang.get('pages.products.donation_amount_required');
this.currentLang = salla.lang.locale;
});
salla.event.on(this.defaultEvent, () => {
this.open();
});
}
componentDidLoad() {
salla.event.product.onPriceUpdated(() => {
const quantityInput = document.querySelector(`.s-quantity-input-input`);
// @ts-ignore
this.quantity = quantityInput === null || quantityInput === void 0 ? void 0 : quantityInput.value;
});
}
/**
* Show / Open the gifting modal window
*/
async open() {
if (salla.config.isGuest()) {
salla.api.auth.setAfterLoginEvent(this.defaultEvent);
salla.event.dispatch('login::open');
return;
}
await this.modal.open();
return await salla.api.withoutNotifier(() => salla.product.getGiftDetails(this.productId))
.then((response) => {
this.gift = response.data;
this.senderName = this.gift.sender_name;
})
.catch(e => {
var _a, _b, _c, _d;
this.hasError = true;
this.errorMessage = ((_c = (_b = (_a = e.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.message) || ((_d = e.response) === null || _d === void 0 ? void 0 : _d.data);
})
.finally(() => this.modal.stopLoading());
}
/**
*
* Hide / close the gifting modal window
*/
async close() {
return this.modal.close();
}
/**
* Update the modal height based on the changes on the inner elements height for a specific step OR just a pass a new fixed height
*/
async setWrapperHeight(asStep = 1, delay = 250, additionSpace = 0, newHeight = 0) {
let currentStep = document.querySelector(`#${this.hostId} .gift-step-${asStep}`);
setTimeout(() => {
let currentStepHeight = currentStep.offsetHeight;
if (newHeight) {
this.stepsWrapper.style.height = `${newHeight}px`;
}
else {
this.stepsWrapper.style.height = currentStepHeight + additionSpace + 'px';
}
}, delay);
}
toggleCalendar() {
this.showCalendar = !this.showCalendar;
this.setWrapperHeight(2, 150, 0);
}
toggleGiftText(event) {
var _a;
(_a = this.textSelect) === null || _a === void 0 ? void 0 : _a.classList.remove('s-form-has-error');
let dataID = event.target.children[event.target.selectedIndex].getAttribute('data-id');
let customID = dataID == "custom";
this.showGiftText = customID;
if (dataID) {
this.selectedGiftTextOption = dataID;
customID ? this.selectedText = undefined : this.selectedText = event.target.value;
this.setWrapperHeight(1, 150, 5);
}
else {
// empty textarea value
this.textArea.value = '';
this.selectedText = undefined;
this.selectedGiftTextOption = undefined;
this.setWrapperHeight(1, 150, -15);
}
}
/**
*
* Go to the step 2
*/
async goToStep2() {
if (!this.selectedGiftTextOption) {
this.textSelect.classList.add('s-form-has-error');
this.customTextArea.classList.remove('s-form-has-error');
return;
}
else if (this.selectedGiftTextOption == 'custom' && !this.selectedText) {
this.textSelect.classList.remove('s-form-has-error');
this.customTextArea.classList.add('s-form-has-error');
return;
}
else {
this.textSelect.classList.remove('s-form-has-error');
this.customTextArea.classList.remove('s-form-has-error');
}
this.setWrapperHeight(2, 600, 0);
let stepNextAnime = new anime.timeline();
stepNextAnime.add({
targets: this.step1Elems.querySelectorAll(`#${this.hostId} .anime-item`),
opacity: [1, 0],
translateX: [0, 50],
delay: anime.stagger(70),
// easing: 'easeOutExpo',
duration: 1200,
})
.add({
targets: '.gift-step-2',
translateX: ['-110%', 0],
opacity: [0, 1],
}, '-=1800')
.add({
targets: this.step2Elems.querySelectorAll(`#${this.hostId} .anime-item`),
opacity: [0, 1],
translateX: [-50, 0],
delay: anime.stagger(70),
duration: 1200,
complete: () => {
this.step2Elems.querySelectorAll(`#${this.hostId} .anime-item`).forEach(item => {
item.classList.remove('opacity-0');
item.removeAttribute('style');
});
}
}, '-=1200');
this.currentStep = 2;
this.parentClass = `is-current-step-${this.currentStep}`;
}
/**
*
* Go to the step 1
*/
goToStep1(e) {
e.preventDefault();
let stepBackAnime = new anime.timeline({
autoplay: false,
});
stepBackAnime.add({
targets: this.step2Elems.querySelectorAll(`#${this.hostId} .anime-item`),
opacity: [1, 0],
translateX: [0, -50],
delay: anime.stagger(70),
// easing: 'easeOutExpo',
duration: 1200,
})
.add({
targets: '.gift-step-1',
translateX: ['110%', 0],
opacity: [0, 1],
}, '-=1800')
.add({
targets: this.step1Elems.querySelectorAll(`#${this.hostId} .anime-item`),
opacity: [0, 1],
translateX: [50, 0],
delay: anime.stagger(70),
duration: 1200,
complete: () => {
this.step1Elems.querySelectorAll(`#${this.hostId} .anime-item`).forEach(item => {
item.classList.remove('opacity-0');
item.removeAttribute('style');
});
}
}, '-=1200');
stepBackAnime.play();
this.setWrapperHeight(1, 600, 0);
this.currentStep = 1;
this.parentClass = `is-current-step-${this.currentStep}`;
}
getFilepondPlaceholder() {
return `<div class="s-gifting-filepond-placeholder"><span class="s-gifting-filepond-placeholder-icon">${Images}</span><p class="s-gifting-filepond-placeholder-text">${this.selectImageOrUpload ? this.selectImageOrUpload : ''}</p></div>`;
}
setPreview(image) {
var _a, _b, _c;
(_a = this.uploader) === null || _a === void 0 ? void 0 : _a.classList.add('has-bg');
var bg = document.querySelector(`#${this.hostId}.filepond-bg`) ? document.querySelector(`#${this.hostId} .filepond-bg`) : document.createElement('div');
bg.classList.add('filepond-bg');
bg.classList.remove('s-hidden');
bg.style.backgroundImage = "url('" + image.url + "')";
(_c = (_b = this.uploader) === null || _b === void 0 ? void 0 : _b.querySelector('.filepond--root')) === null || _c === void 0 ? void 0 : _c.appendChild(bg);
this.uploadedImage = image.url;
if (!!this.gift && this.gift.gift_images.length) {
this.setWrapperHeight(1, 150, 0);
}
}
removePreview() {
this.uploader.classList.remove('has-bg');
let bg = document.querySelector(`#${this.hostId} .filepond-bg`);
bg.removeAttribute('style');
bg.classList.add('s-hidden');
this.handleRemoveImage();
}
handleTextAreaChange(event) {
this.selectedText = event.target.value;
this.customTextArea.classList.remove('s-form-has-error');
}
handleSenderName(event) {
this.senderName = event.target.value;
}
handleReceiverName(event) {
this.receiverName = event.target.value;
}
handleUploadImage(img) {
this.uploadedImage = img;
if (!!this.gift && this.gift.gift_images.length) {
this.setWrapperHeight(1, 150, 0);
}
}
handleRemoveImage() {
this.uploadedImage = '';
if (!!this.gift && this.gift.gift_images.length) {
this.setWrapperHeight(1, 150, 0);
}
}
// private handleReceiverEmail(event) {
// this.receiverEmail = event.target.value;
// }
handlePhoneInputChange(event) {
let phone = event.detail;
this.receiverMobile = phone.number;
this.receiverCountryCode = phone.country_code;
}
handleDateTimePicker(event) {
this.deliveryDate = event.detail;
}
getCalendarClasses() {
return {
"s-form-group": true,
"anime-item": true,
"s-gifting-calendar": true,
"shown": this.showCalendar,
"hide": !this.showCalendar,
"s-form-has-error": !!this.errors && this.errors['deliver_at']
};
}
async submitForm() {
var _a, _b;
// @ts-ignore
const donatingAmount = (_a = document.querySelector(`#donating-amount`)) === null || _a === void 0 ? void 0 : _a.value;
this.calendarFormGroup.classList.remove('s-form-has-error');
if (!!this.errors) {
this.errors = {};
this.setWrapperHeight(2, 150, 0);
}
if (this.showCalendar && !this.deliveryDate) {
this.calendarFormGroup.classList.add('s-form-has-error');
return;
}
let payload = {
text: this.selectedText,
sender_name: this.senderName,
quantity: this.quantity,
deliver_at: this.showCalendar ? this.deliveryDate : null,
image_url: (_b = this.uploadedImage) !== null && _b !== void 0 ? _b : this.selectedImage,
donation_amount: donatingAmount ? donatingAmount : null,
receiver: {
name: this.receiverName,
country_code: this.receiverCountryCode,
mobile: this.receiverMobile
},
has_apple_pay: salla.helpers.hasApplePay()
};
return await salla.product.addGiftToCart(this.productId, payload, true)
.then(() => this.modal.close())
.catch((e) => {
if (e.response.status == 422) {
this.errors = e.response.data.error.fields;
}
else {
console.log(e);
}
this.setWrapperHeight(2, 150, 0);
});
}
render() {
var _a, _b;
return [
h("div", null, h("salla-list-tile", { class: "s-gifting-widget" }, h("div", { slot: "title" }, h("h3", null, !!this.widgetTitle ? this.widgetTitle : this.sectionTitle)), h("div", { slot: "subtitle" }, h("div", null, !!this.widgetSubtitle ? this.widgetSubtitle : this.sectionSubtitle)), h("div", { slot: "action" }, h("salla-button", { class: "s-gifting-widget-action", color: "gray", onClick: () => this.open() }, h("slot", { name: "widget-btn-content" }, h("div", { class: "s-gifting-widget-action-content" }, h("span", { innerHTML: GiftSharing }), " \u00A0", h("span", null, this.sectionBtnText)))))), h("salla-modal", { id: this.hostId, isLoading: true, class: "s-gifting-modal", width: "sm", ref: modal => this.modal = modal }, h("div", { slot: "loading" }, h("div", { class: "s-gifting-skeleton" }, h("div", { class: "s-gifting-modal-header" }, h("salla-skeleton", { type: 'circle', height: '5rem', width: '5rem' }), h("h2", { class: "s-gifting-modal-title" }, h("div", { class: "s-gifting-modal-badge-wrapper" }, h("salla-skeleton", { height: '15px', width: '150px' })))), h("div", { class: "s-gifting-skeleton-content" }, h("salla-skeleton", { height: '10px', width: '150px' }), h("salla-skeleton", { height: '230px' }), h("salla-skeleton", { height: '10px', width: '150px' }), h("salla-skeleton", { height: '30px' }), h("salla-skeleton", { height: '40px' })))), h("slot", { name: "header" }), !!this.hasError ?
h("salla-placeholder", { alignment: "center" }, h("span", { slot: "title" }, this.errorMessage || salla.lang.get('common.errors.empty_results')), h("span", { slot: "description" }, " "))
:
[
h("div", { class: "s-gifting-modal-header" }, h("span", { class: "s-gifting-modal-icon" }, h("span", { innerHTML: GiftSharing })), h("h2", { class: "s-gifting-modal-title" }, h("div", { class: "s-gifting-modal-badge-wrapper" }, h("div", { class: "s-gifting-modal-badge" }, h("span", null, h("span", null, this.currentStep), "/2")), h("span", null, this.giftDetails)))),
h("div", { class: "s-gifting-steps-wrapper " + this.parentClass, ref: el => this.stepsWrapper = el }, h("div", { class: "s-gifting-step-one gift-step-1", ref: el => this.step1Elems = el }, h("div", { class: "s-gifting-modal-uploader-title anime-item" }, this.selectImageForYourGift), h("div", { class: "s-gifting-modal-uploader anime-item", ref: el => this.uploader = el }, h("span", { class: "s-gifting-remove-preview", onClick: () => this.removePreview(), innerHTML: Cancel }), this.selectImageOrUpload && h("salla-file-upload", { "instant-upload": true, name: "image_url", url: salla.url.api(salla.product.api.getUrl('giftImage')), onUploaded: event => this.handleUploadImage(event.detail), labelIdle: this.getFilepondPlaceholder(), onRemoved: () => this.handleRemoveImage() })), h("div", { class: "anime-item" }, !this.uploadedImage && !!this.gift && !!this.gift.gift_images && this.gift.gift_images.length > 0 ?
h("salla-slider", { id: "gifting-slider", loop: false, "controls-outer": true, class: "s-gifting-slider", type: "carousel" }, h("div", { slot: "items" }, this.gift && this.gift.gift_images ?
(_a = this.gift) === null || _a === void 0 ? void 0 : _a.gift_images.map((item) => h("img", { class: "s-gifting-image s-gifting-clickable", src: item.url, onClick: () => this.setPreview(item), alt: `${item.id}` })) : ''))
: ""), h("div", { class: "anime-item" }, h("div", { class: "s-form-group s-gifting-selectText", ref: el => this.textSelect = el }, h("select", { id: "gift-text-selection", name: "gift-text-selection", class: "s-form-control s-gifting-select", onChange: e => this.toggleGiftText(e) }, h("option", { "data-id": null, selected: true }, this.selectGiftMessage), this.gift && this.gift.gift_texts ?
(_b = this.gift) === null || _b === void 0 ? void 0 : _b.gift_texts.map((txt) => h("option", { "data-id": txt.id, value: txt.text, key: txt.id }, txt.text)) : '', h("option", { "data-id": "custom" }, this.giftCustomText))), h("div", { class: this.showGiftText ? "s-form-group s-gifting-textarea shown" : "s-form-group s-gifting-textarea hide", ref: (el) => this.customTextArea = el }, h("label", { htmlFor: "gift-custom-text", class: "s-form-label" }, this.giftCustomText), h("div", { class: "mt-1" }, h("textarea", { onInput: (event) => this.handleTextAreaChange(event), rows: 4, ref: (el) => this.textArea = el, name: "gift-custom-text", id: "gift-custom-text", class: "s-form-control" })))), h("div", { class: "anime-item" }, h("salla-button", { color: "primary", width: "wide", onClick: () => this.goToStep2() }, h("span", null, this.nextStep)))), h("div", { class: "s-gifting-step-two gift-step-2", ref: el => this.step2Elems = el }, h("div", { class: this.errors && this.errors['sender_name'] ? "s-form-group s-form-has-error anime-item opacity-0" : "s-form-group anime-item opacity-0" }, h("label", { htmlFor: "sender_name", class: "s-form-label" }, this.senderNameLabel), h("input", { type: "text", class: "s-form-control", name: "sender_name", id: "sender_name", value: this.senderName, onInput: (event) => this.handleSenderName(event), placeholder: "" }), this.errors && this.errors['sender_name'] ?
h("span", { class: "text-danger text-xs" }, this.errors['sender_name']) : ''), h("div", { class: this.errors && this.errors['receiver.name'] ? "s-form-group s-form-has-error anime-item opacity-0" : "s-form-group anime-item opacity-0" }, h("label", { htmlFor: "receiver_name", class: "s-form-label" }, this.receiverNameFieldLabel), h("input", { type: "text", class: "s-form-control", name: "receiver_name", id: "receiver_name", value: "", onInput: (event) => this.handleReceiverName(event), placeholder: "" }), this.errors && this.errors['receiver.name'] ?
h("span", { class: "text-danger text-xs" }, this.errors['receiver.name']) : ''), h("div", { class: this.errors && this.errors['receiver.mobile'] ? "s-form-group s-form-has-error anime-item opacity-0" : "s-form-group anime-item opacity-0" }, h("label", { class: "s-form-label" }, this.receiverMobileFieldLabel), h("salla-tel-input", { class: "s-gifting-tel-input", phone: this.receiverMobile, countryCode: this.receiverCountryCode, onPhoneEntered: (e) => this.handlePhoneInputChange(e) }), this.errors && this.errors['receiver.mobile'] ?
h("span", { class: "text-danger text-xs" }, this.errors['receiver.mobile']) : ''), h("div", { class: "anime-item opacity-0" }, h("label", { class: "s-gifting-schedule s-gifting-clickable", htmlFor: `schedule-${this.hostId}` }, h("input", { type: "checkbox", name: 'schedule', id: `schedule-${this.hostId}`, onChange: () => this.toggleCalendar(), class: "s-checkbox" }), h("span", { class: "s-form-label" }, " ", this.sendLater, " "))), h("div", { class: this.getCalendarClasses(), ref: (el) => this.calendarFormGroup = el }, h("label", { class: "s-form-label" }, this.selectSendDateAndTime), h("salla-datetime-picker", { value: this.deliveryDate, placeholder: this.selectSendDateAndTime, "enable-time": true, "date-format": "Y-m-d h:i K", onPicked: (event) => this.handleDateTimePicker(event) }), h("span", { class: "s-gifting-calendar-hint" }, this.canNotEditOrderAfterSelectDate)), h("div", { class: "s-gifting-step-two-footer anime-item opacity-0" }, h("a", { href: "#!", innerHTML: LeftArrow, onClick: (e) => this.goToStep1(e) }), h("salla-button", { onClick: () => this.submitForm(), color: "primary", width: 'wide' }, h("span", null, this.sendGift)))))
], h("slot", { name: "footer" })))
];
}
static get is() { return "salla-gifting"; }
static get originalStyleUrls() {
return {
"$": ["salla-gifting.scss"]
};
}
static get styleUrls() {
return {
"$": ["salla-gifting.css"]
};
}
static get properties() {
return {
"productId": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "The product id for which the gifting system is required."
},
"attribute": "product-id",
"reflect": false
},
"widgetTitle": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Widget title"
},
"attribute": "widget-title",
"reflect": false
},
"widgetSubtitle": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Widget subtitle"
},
"attribute": "widget-subtitle",
"reflect": false
}
};
}
static get states() {
return {
"sectionTitle": {},
"sectionSubtitle": {},
"sectionBtnText": {},
"giftDetails": {},
"selectImageForYourGift": {},
"selectImageOrUpload": {},
"selectGiftMessage": {},
"giftCustomText": {},
"textId": {},
"incorrectGiftText": {},
"nextStep": {},
"senderNameLabel": {},
"receiverNameFieldLabel": {},
"receiverMobileFieldLabel": {},
"receiverEmailFieldLabel": {},
"emailPlaceholder": {},
"sendLater": {},
"selectSendDateAndTime": {},
"canNotEditOrderAfterSelectDate": {},
"sendGift": {},
"donationRequired": {},
"currentStep": {},
"showCalendar": {},
"showGiftText": {},
"currentLang": {},
"parentClass": {},
"errors": {},
"gift": {},
"selectedGiftTextOption": {},
"showTextArea": {},
"selectedImage": {},
"uploadedImage": {},
"selectedText": {},
"senderName": {},
"errorMessage": {},
"hasError": {},
"quantity": {},
"deliveryDate": {},
"timeZone": {},
"receiverName": {},
"receiverMobile": {},
"receiverCountryCode": {},
"receiverEmail": {},
"hostId": {}
};
}
static get methods() {
return {
"open": {
"complexType": {
"signature": "() => Promise<any>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<any>"
},
"docs": {
"text": "Show / Open the gifting modal window",
"tags": []
}
},
"close": {
"complexType": {
"signature": "() => Promise<HTMLElement>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
},
"HTMLElement": {
"location": "global",
"id": "global::HTMLElement"
}
},
"return": "Promise<HTMLElement>"
},
"docs": {
"text": "\nHide / close the gifting modal window",
"tags": []
}
},
"goToStep2": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "\nGo to the step 2",
"tags": []
}
}
};
}
}
//# sourceMappingURL=salla-gifting.js.map