kopia lustrzana https://github.com/OpenBuilds/OpenBuilds-CONTROL
430 wiersze
16 KiB
JavaScript
430 wiersze
16 KiB
JavaScript
/*!
|
|
* IconPicker ('https://github.com/furcan/IconPicker')
|
|
* Version: 1.5.0
|
|
* Author: Furkan MT ('https://github.com/furcan')
|
|
* Dependencies: Font Awesome Free v5.11.2 (https://fontawesome.com/license/free)
|
|
* Copyright 2019 IconPicker, MIT Licence ('https://opensource.org/licenses/MIT')*
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
// IconPicker: Default Options on
|
|
var ipDefaultOptions = {
|
|
jsonUrl: null,
|
|
searchPlaceholder: 'Search Icon',
|
|
cancelButton: 'Cancel',
|
|
noResultsFound: 'No results found.',
|
|
borderRadius: '20px',
|
|
}
|
|
var ipNewOptions;
|
|
var ipGithubUrl = 'https://github.com/furcan/IconPicker';
|
|
// IconPicker: Default Options off
|
|
|
|
// IconPicker: Extend Options on
|
|
var extendIconPicker = function() {
|
|
var extended = {};
|
|
var deep = false;
|
|
var i = 0;
|
|
if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {
|
|
deep = arguments[0];
|
|
i++;
|
|
}
|
|
var merge = function(obj) {
|
|
for (var prop in obj) {
|
|
if (obj.hasOwnProperty(prop)) {
|
|
if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {
|
|
extended[prop] = extendIconPicker(extended[prop], obj[prop]);
|
|
} else {
|
|
extended[prop] = obj[prop];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
for (; i < arguments.length; i++) {
|
|
merge(arguments[i]);
|
|
}
|
|
return extended;
|
|
};
|
|
// IconPicker: Extend Options off
|
|
|
|
|
|
// IconPicker: Main on
|
|
var IconPicker = {
|
|
|
|
// init
|
|
Init: function(ipUserOptions) {
|
|
ipNewOptions = extendIconPicker(true, ipDefaultOptions, ipUserOptions);
|
|
},
|
|
|
|
// run
|
|
Run: function(theButton, theCallback) {
|
|
|
|
// IconPicker: Console Error Function on
|
|
var ipConsoleError = function(errorMessage) {
|
|
return console.error('%c IconPicker (Error) ', 'padding:2px;border-radius:20px;color:#fff;background:#f44336', '\n' + errorMessage);
|
|
}
|
|
// IconPicker: Console Error Function off
|
|
|
|
// IconPicker: Console Log Function on
|
|
var ipConsoleLog = function(errorMessage) {
|
|
return console.log('%c IconPicker (Info) ', 'padding:2px;border-radius:20px;color:#fff;background:#00bcd4', '\n' + errorMessage);
|
|
}
|
|
// IconPicker: Console Log Function off
|
|
|
|
// IconPicker: Check The Arguments For Proceed on
|
|
if (arguments && arguments.length <= 2) {
|
|
|
|
// query selector
|
|
var ipButtons = document.querySelectorAll(theButton);
|
|
|
|
// if button exist on the document
|
|
if (ipButtons && ipButtons.length > 0) {
|
|
for (var i = 0; i < ipButtons.length; i++) {
|
|
|
|
// IconPicker: Button Listeners -> Send XMLHttpRequest on
|
|
var ipButton = ipButtons[i];
|
|
ipButton.addEventListener('click', function() {
|
|
var jsonUrl = ipNewOptions.jsonUrl;
|
|
var inputElement = this.dataset.iconpickerInput;
|
|
var previewElement = this.dataset.iconpickerPreview;
|
|
var cancelButton = ipNewOptions.cancelButton;
|
|
if (!cancelButton || (cancelButton && cancelButton.length < 1)) {
|
|
cancelButton = ipDefaultOptions.cancelButton;
|
|
}
|
|
var searchPlaceholder = ipNewOptions.searchPlaceholder;
|
|
if (!searchPlaceholder || (searchPlaceholder && searchPlaceholder.length < 1)) {
|
|
searchPlaceholder = ipDefaultOptions.searchPlaceholder;
|
|
}
|
|
var borderRadius = ipNewOptions.borderRadius;
|
|
if (!borderRadius || (borderRadius && borderRadius.length < 1)) {
|
|
borderRadius = ipDefaultOptions.borderRadius;
|
|
}
|
|
|
|
// check the json url on
|
|
if (!jsonUrl) {
|
|
ipConsoleError('You have to set the path of IconPicker JSON file to "jsonUrl" option. \n\nVisit to learn how: ' + ipGithubUrl);
|
|
return false;
|
|
}
|
|
// check the json url off
|
|
|
|
// check the input on
|
|
var checkInput = document.querySelectorAll(inputElement);
|
|
if (checkInput.length <= 0) {
|
|
ipConsoleError('You must define your Input element with it\'s ID or Class Name to your Button element data attribute. \n\nExample: \ndata-iconpicker-input="#MyIconInput" or \ndata-iconpicker-input=".my-icon-input" \n\nVisit to learn how: ' + ipGithubUrl);
|
|
return false;
|
|
}
|
|
// check the input off
|
|
|
|
// check the preview icon on
|
|
var checkPreviewIcon = document.querySelectorAll(previewElement);
|
|
if (checkPreviewIcon.length <= 0) {
|
|
ipConsoleLog('You can define your Preview Icon element with it\'s ID or Class Name to your Button element data attribute. \n\nExample: \ndata-iconpicker-preview="i#MyIconElement" or \ndata-iconpicker-preview="i.my-icon-element" \n\nVisit to learn how: ' + ipGithubUrl);
|
|
}
|
|
// check the preview icon off
|
|
|
|
// check the callback on
|
|
if (!theCallback && typeof theCallback !== 'function') {
|
|
theCallback = undefined;
|
|
}
|
|
// check the callback off
|
|
|
|
getIconListXmlHttpRequest(jsonUrl, cancelButton, searchPlaceholder, borderRadius, inputElement, previewElement, theCallback);
|
|
|
|
});
|
|
// IconPicker: Button Listeners -> Send XMLHttpRequest off
|
|
|
|
}
|
|
}
|
|
// not exist
|
|
else {
|
|
ipConsoleError('You called the IconPicker with "' + theButton + '" selector, but there is no such element on the document.');
|
|
}
|
|
|
|
} else if (arguments && arguments.length > 2) {
|
|
ipConsoleError('More parameters than allowed.');
|
|
return false;
|
|
} else {
|
|
ipConsoleError('You have to call the IconPicker with an Element(Button or etc.) Class or ID. \n\nYou can also find the other required data attributes in the Documentation. \n\nVisit: ' + ipGithubUrl);
|
|
return false;
|
|
}
|
|
// IconPicker: Check The Arguments For Proceed off
|
|
|
|
|
|
// IconPicker: Get Library from JSON and AppendTo Body on
|
|
var getIconListXmlHttpRequest = function(jsonUrl, buttonCancel, searchPlaceholder, borderRadius, inputElement, previewElement, theCallback) {
|
|
|
|
// if chrome browser
|
|
if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
|
|
// check the protocol
|
|
if (window.location.protocol.indexOf('http') <= -1) {
|
|
ipConsoleLog('Chrome Browser blocked this request by CORS policy.');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// modal element
|
|
var ipElement = document.getElementById('IconPickerModal');
|
|
|
|
// if modal element doesn't exist on document send XMLHttpRequest
|
|
if (!ipElement) {
|
|
var xmlHttp = new XMLHttpRequest();
|
|
xmlHttp.open('GET', jsonUrl, true);
|
|
xmlHttp.setRequestHeader('Content-type', 'application/json; charset=utf-8');
|
|
xmlHttp.send();
|
|
xmlHttp.onreadystatechange = function() {
|
|
if (this.readyState === 4) {
|
|
if (this.status === 200) { // success
|
|
var data = this.responseText;
|
|
appendIconListToBody(data, buttonCancel, searchPlaceholder, borderRadius, inputElement, previewElement, theCallback);
|
|
} else {
|
|
ipConsoleError('XMLHttpRequest Failed.');
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
// IconPicker: Get Library from JSON and AppendTo Body off
|
|
|
|
|
|
// IconPicker: Append Library to Body on
|
|
var appendIconListToBody = function(data, buttonCancel, searchPlaceholder, borderRadius, inputElement, previewElement, theCallback) {
|
|
|
|
// data
|
|
var jsonData = JSON.parse(data);
|
|
|
|
// icons
|
|
var icons = '';
|
|
for (var key in jsonData) {
|
|
if (jsonData.hasOwnProperty(key)) {
|
|
var forObj = jsonData[key];
|
|
var icon = '<i data-search="' + forObj + '" data-class="' + forObj + '" class="first-icon select-icon ' + forObj + '"></i>';
|
|
icons += icon;
|
|
}
|
|
}
|
|
|
|
// loading indicator
|
|
var loadingIndicator = '<div id="IconPickerLoading"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="60" height="60" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"><g transform="translate(25 50)"><circle cx="0" cy="0" r="9" fill="#1e1e1e" transform="scale(0.24 0.24)"><animateTransform attributeName="transform" type="scale" begin="-0.2666s" calcMode="spline" keySplines="0.3 0 0.7 1;0.3 0 0.7 1" values="0;1;0" keyTimes="0;0.5;1" dur="0.8s" repeatCount="indefinite"/></circle></g><g transform="translate(50 50)"><circle cx="0" cy="0" r="9" fill="#1e1e1e" transform="scale(0.00153 0.00153)"><animateTransform attributeName="transform" type="scale" begin="-0.1333s" calcMode="spline" keySplines="0.3 0 0.7 1;0.3 0 0.7 1" values="0;1;0" keyTimes="0;0.5;1" dur="0.8s" repeatCount="indefinite"/></circle></g><g transform="translate(75 50)"><circle cx="0" cy="0" r="9" fill="#1e1e1e" transform="scale(0.3 0.3)"><animateTransform attributeName="transform" type="scale" begin="0s" calcMode="spline" keySplines="0.3 0 0.7 1;0.3 0 0.7 1" values="0;1;0" keyTimes="0;0.5;1" dur="0.8s" repeatCount="indefinite"/></circle></g></svg></div>';
|
|
|
|
// icons wrap
|
|
var iconWrap = '<div class="ip-icons-content" style="border-radius:' + borderRadius + ';">' +
|
|
'<div class="ip-icons-search"><input id="IconPickerSearch" type="text" spellcheck="false" autocomplete="off" placeholder="' + searchPlaceholder + '" style="border-radius:' + borderRadius + ';" /><i class="placeholder-icon fas fa-search"></i></div>' +
|
|
'<div class="ip-icons-search-results"></div>' +
|
|
'<div class="ip-icons-area">' +
|
|
loadingIndicator +
|
|
icons +
|
|
'</div>' +
|
|
'<div class="ip-icons-footer"><a class="cancel" style="border-radius:' + borderRadius + ';">' + buttonCancel + '</a></div>' +
|
|
'</div>';
|
|
|
|
// create the modal element
|
|
var IconPickerModal = document.createElement('div')
|
|
IconPickerModal.id = 'IconPickerModal';
|
|
IconPickerModal.innerHTML = iconWrap;
|
|
|
|
// body
|
|
var docBody = document.body;
|
|
|
|
// append to body
|
|
docBody.appendChild(IconPickerModal);
|
|
|
|
// get the modal element
|
|
var ipElement = document.getElementById(IconPickerModal.id);
|
|
|
|
// modal element display css
|
|
ipElement.style.display = 'block';
|
|
|
|
// heights
|
|
var ipHeight = parseInt(ipElement.offsetHeight);
|
|
var winHeight = parseInt(window.innerHeight);
|
|
|
|
// modal element position top css on
|
|
var liveScrollTop = parseInt(window.pageYOffset || document.documentElement.scrollTop);
|
|
var totalTopPos = liveScrollTop + ((winHeight - ipHeight) / 2);
|
|
if (winHeight + 20 <= ipHeight) {
|
|
totalTopPos = liveScrollTop;
|
|
}
|
|
ipElement.style.top = totalTopPos + 'px';
|
|
// modal element position top css off
|
|
|
|
// add css animation class to modal
|
|
ipElement.classList.add('animate');
|
|
|
|
// remove loading indicator on
|
|
var loadingElement = document.getElementById('IconPickerLoading');
|
|
var ltAnimate = setTimeout(function() {
|
|
loadingElement.classList.add('hide');
|
|
clearTimeout(ltAnimate);
|
|
}, 600);
|
|
var ltRemove = setTimeout(function() {
|
|
loadingElement.parentNode.removeChild(loadingElement);
|
|
clearTimeout(ltRemove);
|
|
}, 900);
|
|
// remove loading indicator off
|
|
|
|
|
|
// close and remove all on
|
|
var removeIpElement = function(delay) {
|
|
ipElement.classList.remove('animate');
|
|
setTimeout(function() {
|
|
docBody.removeChild(ipElement);
|
|
}, delay);
|
|
}
|
|
// close and remove all off
|
|
|
|
// cancel button click listener on
|
|
var cancelButtonElm = document.getElementById(IconPickerModal.id).getElementsByClassName('cancel')[0];
|
|
cancelButtonElm.addEventListener('click', function() {
|
|
removeIpElement(400);
|
|
}, false);
|
|
// cancel button click listener off
|
|
|
|
// search input keyup listener on
|
|
var searchInputElm = document.getElementById('IconPickerSearch');
|
|
searchInputElm.addEventListener('keyup', function(e) {
|
|
|
|
// keycodes
|
|
var eKeyCode = e.keyCode;
|
|
var eCode = e.code.toString().toLowerCase();
|
|
|
|
// check space and backspace keyup
|
|
var spaceOrBackspace = false;
|
|
if (eKeyCode === 32 || eCode === 'space' || eKeyCode === 8 || eCode === 'backspace') {
|
|
spaceOrBackspace = true;
|
|
}
|
|
|
|
// cant type space
|
|
if (eKeyCode === 32 || eCode === 'space') {
|
|
this.value = this.value.replace(' ', '');
|
|
return false;
|
|
}
|
|
|
|
// this val
|
|
var searchVal = this.value.toString().toLowerCase();
|
|
|
|
// define icons areas
|
|
var firstIconsArea = document.getElementById(IconPickerModal.id).getElementsByClassName('ip-icons-area')[0];
|
|
var searchResultArea = document.getElementById(IconPickerModal.id).getElementsByClassName('ip-icons-search-results')[0];
|
|
|
|
// clear old results
|
|
searchResultArea.innerHTML = '';
|
|
|
|
// (if not space or backspace) and (if typed at least one char) able to search
|
|
if (!spaceOrBackspace && searchVal.length > 0) {
|
|
|
|
// for "serch term" in Json
|
|
var tempIcons = '';
|
|
for (var key in jsonData) {
|
|
if (jsonData.hasOwnProperty(key)) {
|
|
var forObj = jsonData[key];
|
|
// if there is results create them
|
|
if (forObj.toString().indexOf(searchVal) > -1) {
|
|
firstIconsArea.style.display = 'none';
|
|
var tempIcon = '<i data-search="' + forObj + '" data-class="' + forObj + '" class="search-icon select-icon ' + forObj + '"></i>';
|
|
tempIcons += tempIcon;
|
|
}
|
|
}
|
|
}
|
|
|
|
// create a temp container
|
|
var tempResults = document.createElement('div');
|
|
tempResults.id = 'IconsTempResults';
|
|
tempResults.innerHTML = tempIcons;
|
|
|
|
// no results found on
|
|
if (tempIcons.length < 1) {
|
|
firstIconsArea.style.display = 'none';
|
|
var noResultsText = ipNewOptions.noResultsFound;
|
|
if (!noResultsText || (noResultsText && noResultsText.length < 1)) {
|
|
noResultsText = ipDefaultOptions.noResultsFound;
|
|
}
|
|
var noResultElm = '<p class="ip-no-results-found">' + noResultsText + '</p>';
|
|
tempResults.innerHTML = noResultElm;
|
|
}
|
|
// no results found off
|
|
|
|
// append temp container to results area
|
|
searchResultArea.appendChild(tempResults);
|
|
|
|
// event listener for each temp icon
|
|
eachIconEventListener('search');
|
|
|
|
}
|
|
// show first icons
|
|
else {
|
|
firstIconsArea.style.display = 'block';
|
|
}
|
|
|
|
}, false);
|
|
// search input keyup listener off
|
|
|
|
|
|
// each icon click listener on
|
|
function eachIconEventListener(firstOrSearch) {
|
|
|
|
var inputElm = document.querySelectorAll(inputElement);
|
|
var previewElm = document.querySelectorAll(previewElement);
|
|
|
|
// define icons on
|
|
var eachIconElm;
|
|
if (firstOrSearch === 'first') { // first
|
|
eachIconElm = document.getElementById(IconPickerModal.id).getElementsByClassName('first-icon');
|
|
} else if (firstOrSearch === 'search') { // search
|
|
eachIconElm = document.getElementById(IconPickerModal.id).getElementsByClassName('search-icon');
|
|
}
|
|
// define icons off
|
|
|
|
// add listeners each on
|
|
var wrapElem = document.querySelector('.ip-icons-content');
|
|
var config = {
|
|
attributes: true,
|
|
childList: true,
|
|
subtree: true
|
|
};
|
|
|
|
var callback = function(mutationsList, observer) {
|
|
attachClickEventForEachIcon(eachIconElm, inputElm, previewElm);
|
|
};
|
|
|
|
var observer = new MutationObserver(callback);
|
|
observer.observe(wrapElem, config);
|
|
|
|
attachClickEventForEachIcon(eachIconElm, inputElm, previewElm);
|
|
|
|
// add listeners each off
|
|
|
|
}
|
|
|
|
function attachClickEventForEachIcon(eachIconElm, inputElm, previewElm) {
|
|
|
|
for (var i = 0; i < eachIconElm.length; i++) {
|
|
var singleIconElm = eachIconElm[i];
|
|
singleIconElm.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
var iconClassName = this.dataset.class;
|
|
for (var i = 0; i < inputElm.length; i++) {
|
|
|
|
if (inputElm[i].tagName === 'INPUT') {
|
|
inputElm[i].value = iconClassName;
|
|
} else {
|
|
inputElm[i].innerHTML = iconClassName;
|
|
}
|
|
|
|
}
|
|
for (var i = 0; i < previewElm.length; i++) {
|
|
previewElm[i].setAttribute('class', iconClassName);
|
|
}
|
|
removeIpElement(400);
|
|
}, false);
|
|
}
|
|
}
|
|
|
|
// each icon click listener off
|
|
|
|
// first icons listeners
|
|
eachIconEventListener('first');
|
|
|
|
}
|
|
// IconPicker: Append Library to Body off
|
|
},
|
|
}
|
|
// IconPicker: Main off
|