%PDF- %PDF-
Direktori : /proc/self/root/home/bitrix/www/bitrix/js/landing/ui/field/ |
Current File : //proc/self/root/home/bitrix/www/bitrix/js/landing/ui/field/link_url_field.js |
;(function() { "use strict"; BX.namespace("BX.Landing.UI.Field"); var isBoolean = BX.Landing.Utils.isBoolean; var isArray = BX.Landing.Utils.isArray; var isString = BX.Landing.Utils.isString; var isEmpty = BX.Landing.Utils.isEmpty; var isPlainObject = BX.Landing.Utils.isPlainObject; var append = BX.Landing.Utils.append; var remove = BX.Landing.Utils.remove; var data = BX.Landing.Utils.data; var attr = BX.Landing.Utils.attr; var addClass = BX.Landing.Utils.addClass; var removeClass = BX.Landing.Utils.removeClass; var proxy = BX.Landing.Utils.proxy; var htmlToElement = BX.Landing.Utils.htmlToElement; var bind = BX.Landing.Utils.bind; var unbind = BX.Landing.Utils.unbind; var join = BX.Landing.Utils.join; var fireEvent = BX.Landing.Utils.fireEvent; var hash = BX.Landing.Utils.hash; var encodeDataValue = BX.Landing.Utils.encodeDataValue; var capitalize = BX.Landing.Utils.capitalize; var style = BX.Landing.Utils.style; var BaseButton = BX.Landing.UI.Button.BaseButton; var Dropdown = BX.Landing.UI.Field.Dropdown; var Menu = BX.Landing.UI.Tool.Menu; var Cache = BX.Landing.Cache; /** @type {string} */ var TYPE_BLOCK = "block"; /** @type {string} */ var TYPE_ALIAS = "alias"; /** @type {string} */ var TYPE_PAGE = "landing"; /** @type {string} */ var TYPE_SYSTEM = "system"; /** @type {string} */ var TYPE_CATALOG = "catalog"; /** @type {string} */ var TYPE_CATALOG_ELEMENT = "element"; /** @type {string} */ var TYPE_CATALOG_SECTION = "section"; /** @type {string} */ var TYPE_HREF_LINK = ""; /** @type {string} */ var TYPE_HREF_TEL = "tel:"; /** @type {string} */ var TYPE_HREF_SKYPE = "skype:"; /** @type {string} */ var TYPE_HREF_SMS = "sms:"; /** @type {string} */ var TYPE_HREF_MAILTO = "mailto:"; /** * Href value matchers * @type {{ * catalog: RegExp, * catalogElement: RegExp, * catalogSection: RegExp, * block: RegExp, * page: RegExp, * system: RegExp, * alias: RegExp * }} */ var matchers = { catalog: new RegExp("^#catalog#(Element|Section)([0-9]+)"), catalogElement: new RegExp("^#catalogElement([0-9]+)"), catalogSection: new RegExp("^#catalogSection([0-9]+)"), block: new RegExp("^#block([0-9]+)"), page: new RegExp("^#landing([0-9]+)"), system: new RegExp("^#system_[a-z_-]+"), alias: new RegExp("^#.*") }; /** * Implements interface for works with url href list * @extends {BX.Landing.UI.Field.Text} * @constructor */ BX.Landing.UI.Field.LinkURL = function(data) { BX.Landing.UI.Field.Text.apply(this, arguments); addClass(this.layout, "landing-ui-field-link-url"); this.requestOptions = data.options || {}; this.allowedTypes = isArray(data.allowedTypes) ? data.allowedTypes : [TYPE_BLOCK, TYPE_PAGE]; this.disableBlocks = isBoolean(data.disableBlocks) ? data.disableBlocks : false; this.disableCustomURL = isBoolean(data.disableCustomURL) ? data.disableCustomURL : false; this.disallowType = isBoolean(data.disallowType) ? data.disallowType : false; this.iblocks = isArray(data.iblocks) ? data.iblocks : null; this.allowedCatalogEntityTypes = isArray(data.allowedCatalogEntityTypes) ? data.allowedCatalogEntityTypes : null; this.enableAreas = data.enableAreas; this.onListShow = this.onListShow.bind(this, this.requestOptions); this.onSelectButtonClick = this.onSelectButtonClick.bind(this); this.onTypeChange = this.onTypeChange.bind(this); this.onListItemClick = this.onListItemClick.bind(this); this.popup = null; this.dynamic = null; this.value = null; this.button = this.createButton(); this.hrefTypeSwithcer = this.createTypeSwitcher(); this.grid = this.createGridLayout(); this.gridLeftCell = this.grid.querySelector("[class*=\"left\"]"); this.gridCenterCell = this.grid.querySelector("[class*=\"center\"]"); this.gridRightCell = this.grid.querySelector("[class*=\"right\"]"); remove(this.hrefTypeSwithcer.header); append(this.hrefTypeSwithcer.layout, this.gridLeftCell); append(this.input, this.gridCenterCell); append(this.button.layout, this.gridRightCell); append(this.grid, this.layout); this.setHrefPlaceholderByType(this.getHrefStringType()); this.setHrefTypeSwitcherValue(this.getHrefStringType()); this.removeHrefTypeFromHrefString(); this.makeDisplayedHrefValue(); if (this.disallowType) { void style(this.gridLeftCell, { "display": "none" }); } }; BX.Landing.UI.Field.LinkURL.TYPE_BLOCK = TYPE_BLOCK; BX.Landing.UI.Field.LinkURL.TYPE_PAGE = TYPE_PAGE; BX.Landing.UI.Field.LinkURL.TYPE_CATALOG = TYPE_CATALOG; BX.Landing.UI.Field.LinkURL.TYPE_CATALOG_ELEMENT = TYPE_CATALOG_ELEMENT; BX.Landing.UI.Field.LinkURL.TYPE_CATALOG_SECTION = TYPE_CATALOG_SECTION; BX.Landing.UI.Field.LinkURL.matchers = matchers; BX.Landing.UI.Field.LinkURL.prototype = { constructor: BX.Landing.UI.Field.LinkURL, __proto__: BX.Landing.UI.Field.Text.prototype, /** * Sets iblocks list * @param {{name: string, value: int|string}[]} iblocks */ setIblocks: function(iblocks) { this.iblocks = isArray(iblocks) ? iblocks : null; }, /** * Makes displayed value placeholder */ makeDisplayedHrefValue: function() { var hrefValue = this.getValue(); var placeholderType = this.getPlaceholderType(); var valuePromise; switch (placeholderType) { case TYPE_BLOCK: valuePromise = this.getBlockData(hrefValue); break; case TYPE_PAGE: valuePromise = this.getPageData(hrefValue); break; case TYPE_CATALOG_ELEMENT: valuePromise = this.getCatalogElementData(hrefValue); break; case TYPE_CATALOG_SECTION: valuePromise = this.getCatalogSectionData(hrefValue); break; case TYPE_SYSTEM: valuePromise = this.getSystemPage(hrefValue); break; } if (valuePromise) { valuePromise .then(proxy(this.createPlaceholder, this)) .then(proxy(this.setValue, this)) .catch(function() {}); this.disableHrefTypeSwitcher(); this.setHrefTypeSwitcherValue(TYPE_HREF_LINK); } this.enableHrefTypeSwitcher(); }, /** * Gets placeholder data * @param {string} [hrefValue] * @return {Promise<Object>} */ getPlaceholderData: function(hrefValue) { hrefValue = hrefValue || this.getValue(); var placeholderType = this.getPlaceholderType(hrefValue); var valuePromise = Promise.resolve({}); switch (placeholderType) { case TYPE_BLOCK: valuePromise = this.getBlockData(hrefValue); break; case TYPE_PAGE: valuePromise = this.getPageData(hrefValue); break; case TYPE_CATALOG_ELEMENT: valuePromise = this.getCatalogElementData(hrefValue); break; case TYPE_CATALOG_SECTION: valuePromise = this.getCatalogSectionData(hrefValue); break; case TYPE_SYSTEM: valuePromise = this.getSystemPage(hrefValue); break; } return valuePromise; }, /** * Removes type prefix from href value */ removeHrefTypeFromHrefString: function() { var clearHref = this.getValue() .replace(new RegExp(this.getHrefStringType(), "g"), ""); this.setValue(clearHref, true); }, /** * Sets type switcher value * @param type */ setHrefTypeSwitcherValue: function(type) { this.hrefTypeSwithcer.setValue(type); }, /** * Disables type switcher */ disableHrefTypeSwitcher: function() { this.hrefTypeSwithcer.disable(); }, /** * Enables type switcher */ enableHrefTypeSwitcher: function() { this.hrefTypeSwithcer.enable(); }, /** * Gets selected href type (From type switcher) * @return {string} */ getSelectedHrefType: function() { return this.hrefTypeSwithcer.getValue(); }, /** * Gets href string type * @return {string} */ getHrefStringType: function() { var segment = this.getValue().split(":")[0]; var type = TYPE_HREF_LINK; switch (join(segment, ":")) { case TYPE_HREF_TEL: type = TYPE_HREF_TEL; break; case TYPE_HREF_SMS: type = TYPE_HREF_SMS; break; case TYPE_HREF_SKYPE: type = TYPE_HREF_SKYPE; break; case TYPE_HREF_MAILTO: type = TYPE_HREF_MAILTO; break; } return type; }, /** * Sets placeholder by href type * @param {string} type */ setHrefPlaceholderByType: function(type) { var placeholder = this.placeholder || BX.message("FIELD_LINK_HREF_PLACEHOLDER"); switch (type) { case TYPE_HREF_LINK: if (this.disableBlocks && this.disableCustomURL) { placeholder = BX.message("FIELD_LINK_HREF_PLACEHOLDER_PAGES_ONLY"); } if (!this.disableBlocks && this.disableCustomURL) { placeholder = BX.message("FIELD_LINK_HREF_PLACEHOLDER_WITHOUT_CUSTOM_URL"); } if (this.allowedTypes.length === 1 && this.allowedTypes[0] === TYPE_CATALOG) { placeholder = BX.message("FIELD_LINK_HREF_PLACEHOLDER_CATALOG_ONLY"); } break; case TYPE_HREF_TEL: placeholder = BX.message("LANDING_LINK_FIELD_URL_TYPE_PHONE_PLACEHOLDER"); break; case TYPE_HREF_SKYPE: placeholder = BX.message("LANDING_LINK_FIELD_URL_TYPE_SKYPE_PLACEHOLDER"); break; case TYPE_HREF_SMS: placeholder = BX.message("LANDING_LINK_FIELD_URL_TYPE_SMS_PLACEHOLDER"); break; case TYPE_HREF_MAILTO: placeholder = BX.message("LANDING_LINK_FIELD_URL_TYPE_EMAIL_PLACEHOLDER"); break; } data(this.input, "data-placeholder", placeholder); }, /** * Gets placeholder type * @param {string} [hrefValue] * @return {string} */ getPlaceholderType: function(hrefValue) { hrefValue = hrefValue || this.getValue(); if (matchers.block.test(hrefValue)) { return TYPE_BLOCK; } if (matchers.page.test(hrefValue)) { return TYPE_PAGE; } if (matchers.catalogElement.test(hrefValue)) { return TYPE_CATALOG_ELEMENT; } if (matchers.catalogSection.test(hrefValue)) { return TYPE_CATALOG_SECTION; } if (matchers.system.test(hrefValue)) { return TYPE_SYSTEM; } if (matchers.alias.test(hrefValue)) { return TYPE_ALIAS; } return TYPE_HREF_LINK; }, /** * Checks that this field contains url placeholder * @return {boolean} */ containsPlaceholder: function() { return this.input.innerHTML.indexOf("span") !== -1; }, /** * Creates field grid layout * @return {Element} */ createGridLayout: function() { return htmlToElement( "<div class=\"landing-ui-field-link-url-grid\">" + "<div class=\"landing-ui-field-link-url-grid-left\"></div>" + "<div class=\"landing-ui-field-link-url-grid-center\"></div>" + "<div class=\"landing-ui-field-link-url-grid-right\"></div>" + "</div>" ); }, /** * Creates type switcher dropdown * @return {BX.Landing.UI.Field.Dropdown} */ createTypeSwitcher: function() { return new Dropdown({ items: [ {name: BX.message("LANDING_LINK_FIELD_URL_TYPE_LINK"), value: TYPE_HREF_LINK}, {name: BX.message("LANDING_LINK_FIELD_URL_TYPE_PHONE"), value: TYPE_HREF_TEL}, {name: BX.message("LANDING_LINK_FIELD_URL_TYPE_SKYPE"), value: TYPE_HREF_SKYPE}, {name: BX.message("LANDING_LINK_FIELD_URL_TYPE_SMS"), value: TYPE_HREF_SMS}, {name: BX.message("LANDING_LINK_FIELD_URL_TYPE_EMAIL"), value: TYPE_HREF_MAILTO} ], onValueChange: this.onTypeChange }); }, /** * Creates select button * @return {BX.Landing.UI.Button.BaseButton} */ createButton: function() { return new BaseButton("dropdown_button", { text: BX.message("LINK_URL_SUGGESTS_SELECT"), className: "landing-ui-button-select-link", onClick: this.onSelectButtonClick }) }, /** * Handles link type change event * @param {BX.Landing.UI.Field.Dropdown} field */ onTypeChange: function(field) { var type = field.getValue(); switch (type) { case TYPE_HREF_LINK: unbind(this.gridRightCell, "mouseover", proxy(this.onButtonMouseover, this)); unbind(this.gridRightCell, "mouseout", proxy(this.onButtonMouseout, this)); this.button.enable(); break; case TYPE_HREF_TEL: case TYPE_HREF_SMS: case TYPE_HREF_SKYPE: case TYPE_HREF_MAILTO: bind(this.gridRightCell, "mouseover", proxy(this.onButtonMouseover, this)); bind(this.gridRightCell, "mouseout", proxy(this.onButtonMouseout, this)); this.button.disable(); break; } this.setHrefPlaceholderByType(type); }, /** * Handles mouse over event on button */ onButtonMouseover: function() { this.customTypeSuggestTimeout = setTimeout(function() { BX.Landing.UI.Tool.Suggest.getInstance() .show(this.button.layout, { description: BX.message("LANDING_LINK_FIELD_URL_TYPE_CUSTOM_BUTTON_TITLE") }); this.pulseTimeout = setTimeout(function() { addClass(this.hrefTypeSwithcer.input, "landing-ui-pulse"); }.bind(this), 1000); }.bind(this), 100); }, /** * Handles mouse up event on button */ onButtonMouseout: function() { clearTimeout(this.customTypeSuggestTimeout); BX.Landing.UI.Tool.Suggest.getInstance().hide(); clearTimeout(this.pulseTimeout); removeClass(this.hrefTypeSwithcer.input, "landing-ui-pulse"); }, /** * Gets block data * @param {string} block - (#block123) * @return {Promise<T>} */ getBlockData: function(block) { return BX.Landing.UI.Panel.URLList.getInstance() .getBlock(block.replace("#block", "")) .then(function(result) { return (result.type = "block"), result; }); }, /** * Gets page data * @param {string} page - (#landing123) * @return {Promise<T>} */ getPageData: function(page) { if (Cache.has(hash(page))) { var cacheResult = Cache.get(hash(page)); if (cacheResult && typeof cacheResult === "object" && typeof cacheResult.then === "function") { return cacheResult; } return Promise.resolve(cacheResult); } var pageId = parseInt(page.replace("#landing", "")); var resultPromise = BX.Landing.UI.Panel.URLList.getInstance() .getLanding(pageId, this.requestOptions) .then(function(landing) { landing = landing[0]; if (landing) { var resultData = { type: "landing", id: landing.ID, name: landing.TITLE }; Cache.set(hash(page), resultData); return resultData; } }); Cache.set(hash(page), resultPromise); return resultPromise; }, /** * Gets system page data * @param {string} page - (#system_([a-z])) * @return Promise<T> */ getSystemPage: function(page) { if (Cache.has(hash(page))) { var cacheResult = Cache.get(hash(page)); if (cacheResult && typeof cacheResult === "object" && typeof cacheResult.then === "function") { return cacheResult; } return Promise.resolve(cacheResult); } var systemCode = this.content.replace("#system_", ""); var systemPages = BX.Landing.Main.getInstance().options.syspages; if (systemCode in systemPages) { var resultData = { type: "system", id: "_" + systemCode, name: systemPages[systemCode].name }; Cache.set(hash(page), resultData); return Promise.resolve(resultData); } return Promise.reject(); }, /** * Gets catalog element data * @param {string} element * @return {Promise<T>} */ getCatalogElementData: function(element) { if (Cache.has(hash(element))) { var cacheResult = Cache.get(hash(element)); if (cacheResult && typeof cacheResult === "object" && typeof cacheResult.then === "function") { return cacheResult; } return Promise.resolve(cacheResult); } var elementId = element.match(matchers.catalogElement)[1]; var requestBody = {elementId: elementId}; return BX.Landing.Backend.getInstance() .action("Utils::getCatalogElement", requestBody) .then(function(response) { Cache.set(hash(element), response); return response; }); }, /** * Gets catalog section data * @param {string} section * @return {Promise<T>} */ getCatalogSectionData: function(section) { if (Cache.has(hash(section))) { var cacheResult = Cache.get(hash(section)); if (cacheResult && typeof cacheResult === "object" && typeof cacheResult.then === "function") { return cacheResult; } return Promise.resolve(cacheResult); } var sectionId = section.match(matchers.catalogSection)[1]; var requestBody = {sectionId: sectionId}; return BX.Landing.Backend.getInstance() .action("Utils::getCatalogSection", requestBody) .then(function(response) { Cache.set(hash(section), response); return response; }); }, /** * Creates popup menu * @return {BX.Landing.UI.Tool.Menu} */ createPopup: function() { var buttons = []; if (this.allowedTypes.includes(TYPE_BLOCK)) { buttons.push({ text: BX.message("LANDING_LINKS_BUTTON_BLOCKS"), onclick: this.onListShow.bind(this, TYPE_BLOCK) }); } if (this.allowedTypes.includes(TYPE_PAGE)) { buttons.push({ text: BX.message("LANDING_LINKS_BUTTON_LANDINGS"), onclick: this.onListShow.bind(this, TYPE_PAGE) }); } if (this.allowedTypes.includes(TYPE_CATALOG)) { buttons.push({ text: BX.message("LANDING_LINKS_BUTTON_CATALOG"), onclick: this.onListShow.bind(this, TYPE_CATALOG) }); } this.popup = new Menu({ id: "link_list_" + (+new Date()), bindElement: this.button.layout, items: buttons, autoHide: true, events: { onPopupClose: this.button.deactivate.bind(this.button) } }); append(this.popup.popupWindow.popupContainer, this.button.layout.parentNode); return this.popup; }, onSelectButtonClick: function() { if (this.allowedTypes.length === 1 && this.allowedTypes[0] === TYPE_CATALOG) { this.onListShow(TYPE_CATALOG); return; } this.popup = this.popup || this.createPopup(); this.button.enable(); this.popup.show(); var rect = BX.pos(this.button.layout, this.button.layout.parentNode); this.popup.popupWindow.popupContainer.style.top = rect.bottom + "px"; this.popup.popupWindow.popupContainer.style.left = "auto"; this.popup.popupWindow.popupContainer.style.right = "0"; }, onListShow: function(options, type) { if (this.popup) { this.popup.close(); } if (type === TYPE_CATALOG) { var iblocks = this.iblocks; if (!isArray(iblocks)) { iblocks = BX.Landing.Main.getInstance().options.iblocks; } void BX.Landing.UI.Panel.Catalog.getInstance() .show(iblocks, this.allowedCatalogEntityTypes) .then(this.onListItemClick); return; } options.enableAreas = this.enableAreas; void BX.Landing.UI.Panel.URLList.getInstance() .show(type, options) .then(this.onListItemClick); }, /** * Checks that edit mode is prevented * @return {boolean} */ isEditPrevented: function() { if (!isBoolean(this.editPrevented)) { this.editPrevented = this.disableCustomURL || this.containsPlaceholder(); } return this.editPrevented; }, /** * Sets edit prevented value * @param {boolean} value */ setEditPrevented: function(value) { this.editPrevented = value; }, /** * Enables edit */ enableEdit: function() { if (!this.isEditPrevented() && !this.disableCustomURL) { BX.Landing.UI.Field.Text.prototype.enableEdit.apply(this); } }, /** * Creates internal url placeholder * @param {{[type]: string, [id]: string|number, name: string, [url]: string, [image]: string, [subType]: string, [chain]: string[]}} options * @returns {Element} */ createPlaceholder: function(options) { if (isString(options)) { return options; } var placeholder = htmlToElement( "<span class=\"landing-ui-field-url-placeholder\">" + "<span class=\"landing-ui-field-url-placeholder-preview\"></span>" + "<span class=\"landing-ui-field-url-placeholder-text\">" + encodeDataValue(options.name) + "</span>" + "<span class=\"landing-ui-field-url-placeholder-delete\"></span>" + "</span>" ); var placeholderRemove = placeholder .querySelector("[class*=\"delete\"]"); bind(placeholderRemove, "click", proxy(this.onPlaceholderRemoveClick, this)); if (!isEmpty(options.image) && isString(options.image)) { var placeholderPreview = placeholder .querySelector("[class*=\"preview\"]"); attr(placeholderPreview, { "style": "background-image: url('"+options.image+"')" }); if (options.subType === TYPE_CATALOG_SECTION) { addClass(placeholderPreview, "section"); } } if (options.type === TYPE_CATALOG) { options.chain.push(options.name); var title = join(options.name, "\n", options.chain.join(' / ')); attr(placeholder, { "data-dynamic": { type: join(TYPE_CATALOG, capitalize(options.subType)), value: options.id }, "data-placeholder": join("#", options.type, capitalize(options.subType), options.id), "data-url": join("#", options.type, capitalize(options.subType), options.id) }); placeholder.setAttribute("title", title); return placeholder; } attr(placeholder, { "data-placeholder": join("#", options.type, options.id), "data-url": join("#", options.type, options.id) }); placeholder.setAttribute("title", options.name); return placeholder; }, /** * Handles click event on placeholder remove button * @param event */ onPlaceholderRemoveClick: function(event) { this.setEditPrevented(false); this.enableEdit(); remove(event.target.parentNode); this.setValue(""); fireEvent(this.layout, "input"); this.onInputHandler(this.input.innerText); }, /** * Handles click event on catalog panel item * @param {object} item */ onListItemClick: function(item) { var resultPromise = Promise.resolve(item); if (item.type === "block") { resultPromise = this.getBlockData("#block" + item.id); } resultPromise.then(function(item) { this.setValue(this.createPlaceholder(item)); this.disableHrefTypeSwitcher(); this.setHrefTypeSwitcherValue(TYPE_HREF_LINK); fireEvent(this.layout, "input"); }.bind(this)); }, /** * Sets value * @param {object|string} value * @param {boolean} [preventEvent] - Prevents onChange event */ setValue: function(value, preventEvent) { if (typeof value === "object") { this.disableEdit(); this.setEditPrevented(true); this.input.innerHTML = ""; append(value, this.input); this.value = value.dataset.placeholder; this.dynamic = value.dataset.dynamic; if (!preventEvent) { this.onInputHandler(this.input.innerText); } } else { this.setEditPrevented(false); this.input.innerText = value.toString().trim(); this.value = null; this.dynamic = null; this.enableHrefTypeSwitcher(); } if (!preventEvent) { this.onValueChangeHandler(); } }, /** * Gets dynamic data * @return {?object} */ getDynamic: function() { return this.dynamic; }, /** * Gets value * @return {string} */ getValue: function() { return this.getSelectedHrefType() + (this.value ? this.value : this.input.innerText); } }; })();