${
+ data.selectBacktolistTitle
+ }`
+ );
+ }
+
+ if (selectModal) {
+ $body
+ .find(".qor-button--new")
+ .data("ingoreSubmit", true)
+ .data("selectId", resourseData.selectId)
+ .data("loadInline", true);
+ if (
+ selectModal != "one" &&
+ !data.selectNohint &&
+ (typeof resourseData.maxItem === "undefined" ||
+ resourseData.maxItem != "1")
+ ) {
+ $body.addClass("has-hint");
+ }
+ if (selectModal == "mediabox" && !this.mediaScriptAdded) {
+ this.loadMedialibraryJS($response);
+ }
+ }
+
+ $header.find(".qor-button--new").remove();
+ this.$title.after($body.find(".qor-button--new"));
+
+ if (hasSearch) {
+ $bottomsheets.addClass("has-search");
+ $header.find(".qor-bottomsheets__search").remove();
+ $header.prepend(QorBottomSheets.TEMPLATE_SEARCH);
+ }
+
+ if (actionData && actionData.length) {
+ this.bindActionData(actionData);
+ }
+
+ if (resourseData.bottomsheetClassname) {
+ $bottomsheets.addClass(resourseData.bottomsheetClassname);
+ }
+
+ $bottomsheets.trigger("enable");
+
+ $bottomsheets.one(EVENT_HIDDEN, function() {
+ $(this).trigger("disable");
+ });
+
+ this.addHeaderClass();
+ $bottomsheets.data(data);
+
+ // handle after opened callback
+ if (callback && $.isFunction(callback)) {
+ callback(this.$bottomsheets);
+ }
+
+ // callback for after bottomSheets loaded HTML
+ $bottomsheets.trigger(EVENT_BOTTOMSHEET_LOADED, [url, response]);
+ } else {
+ if (data.returnUrl) {
+ this.load(data.returnUrl);
+ } else {
+ this.refresh();
+ }
+ }
+ }, this),
+
+ error: $.proxy(function() {
+ this.$bottomsheets.remove();
+ if (!$(".qor-bottomsheets").is(":visible")) {
+ $("body").removeClass(CLASS_OPEN);
+ }
+ var errors;
+ if ($(".qor-error span").length > 0) {
+ errors = $(".qor-error span")
+ .map(function() {
+ return $(this).text();
+ })
+ .get()
+ .join(", ");
+ } else {
+ errors = QOR_Translations.serverError;
+ }
+ window.alert(errors);
+ }, this)
+ });
+ }, this);
+
+ load();
+ },
+
+ open: function(options, callback) {
+ if (!options.loadInline) {
+ this.init();
+ }
+ this.resourseData = options;
+ this.load(options.url, options, callback);
+ },
+
+ show: function() {
+ this.$bottomsheets.addClass(CLASS_IS_SHOWN).get(0).offsetHeight;
+ this.$bottomsheets.addClass(CLASS_IS_SLIDED);
+ $("body").addClass(CLASS_OPEN);
+ },
+
+ hide: function(e) {
+ let $bottomsheets = $(e.target).closest(".qor-bottomsheets"),
+ $datePicker = $(".qor-datepicker").not(".hidden");
+
+ if ($datePicker.length) {
+ $datePicker.addClass("hidden");
+ }
+
+ $bottomsheets.qorSelectCore("destroy");
+
+ $bottomsheets.trigger(EVENT_BOTTOMSHEET_CLOSED).remove();
+ if (!$(".qor-bottomsheets").is(":visible")) {
+ $("body").removeClass(CLASS_OPEN);
+ }
+ return false;
+ },
+
+ refresh: function() {
+ this.$bottomsheets.remove();
+ $("body").removeClass(CLASS_OPEN);
+
+ setTimeout(function() {
+ window.location.reload();
+ }, 350);
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorBottomSheets.DEFAULTS = {
+ title: ".qor-form-title, .mdl-layout-title",
+ content: false
+ };
+
+ QorBottomSheets.TEMPLATE_ERROR = `
`;
+ QorBottomSheets.TEMPLATE_LOADING = `
`;
+ QorBottomSheets.TEMPLATE_SEARCH = `
+
+
+
`;
+
+ QorBottomSheets.TEMPLATE = `
`;
+
+ QorBottomSheets.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorBottomSheets(this, options)));
+ }
+
+ if (typeof options === "string" && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $.fn.qorBottomSheets = QorBottomSheets.plugin;
+
+ return QorBottomSheets;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-chooser.js b/app/views/qor/assets/javascripts/qor/qor-chooser.js
new file mode 100644
index 0000000..2fa4adb
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-chooser.js
@@ -0,0 +1,131 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ var NAMESPACE = 'qor.chooser';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+
+ function QorChooser(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorChooser.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorChooser.prototype = {
+ constructor: QorChooser,
+
+ init: function() {
+ let $this = this.$element,
+ select2Data = $this.data(),
+ resetSelect2Width,
+ option = {
+ minimumResultsForSearch: 8,
+ dropdownParent: $this.parent()
+ };
+ let getSelect2AjaxDynamicURL = window.getSelect2AjaxDynamicURL;
+ let remoteImage = select2Data.remoteImage;
+
+ if (select2Data.remoteData) {
+ option.ajax = $.fn.select2.ajaxCommonOptions(select2Data);
+ if (getSelect2AjaxDynamicURL && $.isFunction(getSelect2AjaxDynamicURL)) {
+ option.ajax.url = function() {
+ return getSelect2AjaxDynamicURL(select2Data);
+ };
+ } else {
+ option.ajax.url = select2Data.remoteUrl;
+ }
+
+ option.templateResult = function(data) {
+ let tmpl = $this.parents('.qor-field').find('[name="select2-result-template"]');
+ return $.fn.select2.ajaxFormatResult(data, tmpl, remoteImage);
+ };
+
+ option.templateSelection = function(data) {
+ if (data.loading) return data.text;
+ let tmpl = $this.parents('.qor-field').find('[name="select2-selection-template"]');
+ return $.fn.select2.ajaxFormatResult(data, tmpl, remoteImage);
+ };
+ }
+
+ $this
+ .on('select2:select', function(evt) {
+ $(evt.target).attr('chooser-selected', 'true');
+ })
+ .on('select2:unselect', function(evt) {
+ $(evt.target).attr('chooser-selected', '');
+ });
+
+ $this.select2(option);
+
+ // reset select2 container width
+ this.resetSelect2Width();
+ resetSelect2Width = window._.debounce(this.resetSelect2Width.bind(this), 300);
+ $(window).resize(resetSelect2Width);
+
+ if ($this.val()) {
+ $this.attr('chooser-selected', 'true');
+ }
+ },
+
+ resetSelect2Width: function() {
+ var $container,
+ select2 = this.$element.data().select2;
+ if (select2 && select2.$container) {
+ $container = select2.$container;
+ $container.width($container.parent().width());
+ }
+ },
+
+ destroy: function() {
+ this.$element.select2('destroy').removeData(NAMESPACE);
+ }
+ };
+
+ QorChooser.DEFAULTS = {};
+
+ QorChooser.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorChooser(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = 'select[data-toggle="qor.chooser"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorChooser.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorChooser.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorChooser;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-common.js b/app/views/qor/assets/javascripts/qor/qor-common.js
new file mode 100644
index 0000000..7ee7744
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-common.js
@@ -0,0 +1,218 @@
+$(function() {
+ let _ = window._,
+ QOR = window.QOR,
+ QOR_Translations = window.QOR_Translations,
+ html = `
+
+
+
+
+
+
+
+
+
`,
+ $dialog = $(html).appendTo("body");
+
+ // ************************************ Refactor window.confirm ************************************
+ $(document)
+ .on("keyup.qor.confirm", function(e) {
+ if (!$dialog.is(":visible")) {
+ return;
+ }
+ if (e.which === 27) {
+ setTimeout(function() {
+ $dialog.hide();
+ QOR.qorConfirmCallback = undefined;
+ }, 100);
+ }
+ if (e.which === 13) {
+ setTimeout(function() {
+ $('.dialog-button[data-type="confirm"]').click();
+ }, 100);
+ }
+ })
+ .on("click.qor.confirm", ".dialog-button", function() {
+ let value = $(this).data("type"),
+ callback = QOR.qorConfirmCallback;
+
+ $.isFunction(callback) && callback(value);
+ $dialog.hide();
+ QOR.qorConfirmCallback = undefined;
+ return false;
+ });
+
+ QOR.qorConfirm = function(data, callback) {
+ let okBtn = $dialog.find(".dialog-ok"),
+ cancelBtn = $dialog.find(".dialog-cancel");
+
+ if (_.isString(data)) {
+ $dialog.find(".dialog-message").text(data);
+ okBtn.text(QOR_Translations.okButton);
+ cancelBtn.text(QOR_Translations.cancelButton);
+ } else if (_.isObject(data)) {
+ if (data.confirmOk && data.confirmCancel) {
+ okBtn.text(data.confirmOk);
+ cancelBtn.text(data.confirmCancel);
+ } else {
+ okBtn.text(QOR_Translations.okButton);
+ cancelBtn.text(QOR_Translations.cancelButton);
+ }
+
+ if(data.icon){
+ $dialog.find('i.material-icons').addClass(data.icon).html(data.icon);
+ }
+
+ $dialog.find(".dialog-message").text(data.confirm);
+ }
+
+ $dialog.show();
+ QOR.qorConfirmCallback = callback;
+ return false;
+ };
+
+ // *******************************************************************************
+
+ // ****************Handle download file from AJAX POST****************************
+ let objectToFormData = function(obj, form) {
+ let formdata = form || new FormData(),
+ key;
+
+ for (var variable in obj) {
+ if (obj.hasOwnProperty(variable) && obj[variable]) {
+ key = variable;
+ }
+
+ if (obj[variable] instanceof Date) {
+ formdata.append(key, obj[variable].toISOString());
+ } else if (
+ typeof obj[variable] === "object" &&
+ !(obj[variable] instanceof File)
+ ) {
+ objectToFormData(obj[variable], formdata);
+ } else {
+ formdata.append(key, obj[variable]);
+ }
+ }
+
+ return formdata;
+ };
+
+ QOR.qorAjaxHandleFile = function(url, contentType, fileName, data) {
+ let request = new XMLHttpRequest();
+
+ request.responseType = "arraybuffer";
+ request.open("POST", url, true);
+ request.onload = function() {
+ if (this.status === 200) {
+ let blob = new Blob([this.response], {
+ type: contentType
+ }),
+ url = window.URL.createObjectURL(blob),
+ a = document.createElement("a");
+
+ document.body.appendChild(a);
+ a.href = url;
+ a.download = fileName || "download-" + $.now();
+ a.click();
+ } else {
+ window.alert(QOR_Translations.serverError);
+ }
+ };
+
+ if (_.isObject(data)) {
+ if (Object.prototype.toString.call(data) != "[object FormData]") {
+ data = objectToFormData(data);
+ }
+
+ request.send(data);
+ }
+ };
+
+ // ********************************convert video link********************
+ // linkyoutube: /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig,
+ // linkvimeo: /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/,
+
+ let converVideoLinks = function() {
+ let $ele = $(".qor-linkify-object"),
+ linkyoutube = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/gi;
+
+ if (!$ele.length) {
+ return;
+ }
+
+ $ele.each(function() {
+ let url = $(this).data("video-link");
+ if (url.match(linkyoutube)) {
+ $(this).html(
+ `
`
+ );
+ }
+ });
+ };
+
+ $.fn.qorSliderAfterShow.converVideoLinks = converVideoLinks;
+ converVideoLinks();
+
+ // ********************************Qor Handle AJAX error********************
+ QOR.handleAjaxError = function(err) {
+ let $body = $("body"),
+ rJSON = err.responseJSON,
+ rText = err.responseText,
+ $error = $(`
`);
+
+ $body.find(".qor-alert").remove();
+
+ if (err.status === 422) {
+ if (rJSON) {
+ let errors = rJSON.errors,
+ $errorContent = "";
+
+ if ($.isArray(errors)) {
+ for (let i = 0; i < errors.length; i++) {
+ $errorContent += `
+ error
+ ${errors[i]}
+ `;
+ }
+ } else {
+ $errorContent = `
+ error
+ ${errors}
+ `;
+ }
+ $error.append($errorContent);
+ } else {
+ $error = $(rText).find(".qor-error");
+ }
+ } else {
+ $error.append(`
+ error
+ ${err.statusText}
+ `);
+ }
+
+ $error.prependTo($body);
+ setTimeout(function() {
+ $error.addClass("qor-alert__active");
+ }, 50);
+
+ setTimeout(function() {
+ $('.qor-alert[data-dismissible="true"]').removeClass("qor-alert__active");
+ $("#qor-submit-loading").remove();
+ }, 6000);
+ };
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-config.js b/app/views/qor/assets/javascripts/qor/qor-config.js
new file mode 100644
index 0000000..439ac80
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-config.js
@@ -0,0 +1,126 @@
+// init for slideout after show event
+$.fn.qorSliderAfterShow = $.fn.qorSliderAfterShow || {};
+window.QOR = {
+ $formLoading: '
'
+};
+
+String.prototype.escapeSymbol = function() {
+ var tagsToReplace = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"' : '"',
+ "'" : ''',
+ '/' : '/'
+ };
+ return this.replace(/[&<>"']/g, function(tag) {
+ return tagsToReplace[tag] || tag;
+ });
+};
+
+// change Mustache tags from {{}} to [[]]
+window.Mustache && (window.Mustache.tags = ['[[', ']]']);
+
+// clear close alert after ajax complete
+$(document).ajaxComplete(function(event, xhr, settings) {
+ if (settings.type == 'POST' || settings.type == 'PUT') {
+ if ($.fn.qorSlideoutBeforeHide) {
+ $.fn.qorSlideoutBeforeHide = null;
+ window.onbeforeunload = null;
+ }
+ }
+});
+
+// select2 ajax common options
+// $.fn.select2 = $.fn.select2 || function(){};
+$.fn.select2.ajaxCommonOptions = function(select2Data) {
+ let remoteDataPrimaryKey = select2Data.remoteDataPrimaryKey;
+
+ return {
+ dataType: 'json',
+ headers: getSelect2Header(select2Data),
+ cache: true,
+ delay: 250,
+ data: function(params) {
+ return {
+ keyword: params.term, // search term
+ page: params.page,
+ per_page: 20
+ };
+ },
+ processResults: function(data, params) {
+ // parse the results into the format expected by Select2
+ // since we are using custom formatting functions we do not need to
+ // alter the remote JSON data, except to indicate that infinite
+ // scrolling can be used
+ params.page = params.page || 1;
+
+ var processedData = $.map(data, function(obj) {
+ obj.id = obj[remoteDataPrimaryKey] || obj.primaryKey || obj.Id || obj.ID;
+ return obj;
+ });
+
+ return {
+ results: processedData,
+ pagination: {
+ more: processedData.length >= 20
+ }
+ };
+ }
+ };
+};
+
+// select2 ajax common options
+// format ajax template data
+$.fn.select2.ajaxFormatResult = function(data, tmpl, remoteDataImage) {
+ var result = '';
+
+ if (data.loading) {
+ return data.text;
+ }
+
+ console.log('select2.ajaxFormatResult: Data');
+ console.log(data);
+
+ console.log('select2.ajaxFormatResult: has remote image');
+ console.log(remoteDataImage);
+
+ if (remoteDataImage) {
+ var resultName = data.text || data.Name || data.Title || data.Code || data[Object.keys(data)[0]];
+ var imageUrl = data.Image;
+ if (imageUrl) {
+ result = '
' + '

' + '
' + resultName + '';
+ } else {
+ result = '
' + resultName + '
';
+ }
+
+ return $(result);
+ } else {
+ if (tmpl.length > 0) {
+ result = window.Mustache.render(tmpl.html().replace(/{{(.*?)}}/g, '[[$1]]'), data);
+ } else {
+ result = data.text || data.Name || data.Title || data.Code || data[Object.keys(data)[0]];
+ }
+
+ // if is HTML
+ if (/<(.*)(\/>|<\/.+>)/.test(result)) {
+ return $(result);
+ }
+
+ return result;
+ }
+};
+
+function getSelect2Header() {
+ let data = $('body').data();
+ let selectAjaxHeader = data.selectAjaxHeader;
+ let getSelect2HeaderFunction = window.getSelect2HeaderFunction;
+ let headers = {};
+
+ if (selectAjaxHeader && getSelect2HeaderFunction && $.isFunction(getSelect2HeaderFunction)) {
+ headers[selectAjaxHeader] = getSelect2HeaderFunction();
+ return headers;
+ } else {
+ return {};
+ }
+}
diff --git a/app/views/qor/assets/javascripts/qor/qor-cropper.js b/app/views/qor/assets/javascripts/qor/qor-cropper.js
new file mode 100644
index 0000000..7f43cb3
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-cropper.js
@@ -0,0 +1,766 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let URL = window.URL || window.webkitURL,
+ NAMESPACE = 'qor.cropper',
+ // Events
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_CHANGE = 'change.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_SHOWN = 'shown.qor.modal',
+ EVENT_HIDDEN = 'hidden.qor.modal',
+ // Classes
+ CLASS_TOGGLE = '.qor-cropper__toggle',
+ CLASS_CANVAS = '.qor-cropper__canvas',
+ CLASS_WRAPPER = '.qor-cropper__wrapper',
+ CLASS_OPTIONS = '.qor-cropper__options',
+ CLASS_SAVE = '.qor-cropper__save',
+ CLASS_DELETE = '.qor-cropper__toggle--delete',
+ CLASS_CROP = '.qor-cropper__toggle--crop',
+ CLASS_UNDO = '.qor-fieldset__undo',
+ HIDDEN_DATA_INPUT = 'input[name="QorResource.MediaOption"]:hidden';
+
+ function capitalize(str) {
+ if (typeof str === 'string') {
+ str = str.charAt(0).toUpperCase() + str.substr(1);
+ }
+
+ return str;
+ }
+
+ function getLowerCaseKeyObject(obj) {
+ let newObj = {},
+ key;
+
+ if ($.isPlainObject(obj)) {
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ newObj[String(key).toLowerCase()] = obj[key];
+ }
+ }
+ }
+
+ return newObj;
+ }
+
+ function getValueByNoCaseKey(obj, key) {
+ let originalKey = String(key),
+ lowerCaseKey = originalKey.toLowerCase(),
+ upperCaseKey = originalKey.toUpperCase(),
+ capitalizeKey = capitalize(originalKey);
+
+ if ($.isPlainObject(obj)) {
+ return obj[lowerCaseKey] || obj[capitalizeKey] || obj[upperCaseKey];
+ }
+ }
+
+ function replaceText(str, data) {
+ if (typeof str === 'string') {
+ if (typeof data === 'object') {
+ $.each(data, function(key, val) {
+ str = str.replace('$[' + String(key).toLowerCase() + ']', val);
+ });
+ }
+ }
+
+ return str;
+ }
+
+ function isSVG(url) {
+ return /.svg$/.test(url);
+ }
+
+ function QorCropper(element, options) {
+ this.$element = $(element);
+ this.options = $.extend(true, {}, QorCropper.DEFAULTS, $.isPlainObject(options) && options);
+ this.data = null;
+ this.init();
+ }
+
+ QorCropper.prototype = {
+ constructor: QorCropper,
+
+ init: function() {
+ let options = this.options,
+ $this = this.$element,
+ $parent = $this.closest(options.parent),
+ data,
+ outputValue,
+ fetchUrl,
+ _this = this,
+ imageData;
+
+ if (!$parent.length) {
+ $parent = $this.parent();
+ }
+
+ this.$parent = $parent;
+ this.$output = $parent.find(options.output);
+ this.$formCropInput = $parent.closest('form').find(HIDDEN_DATA_INPUT);
+ this.$list = $parent.find(options.list);
+
+ fetchUrl = this.$output.data('fetchSizedata');
+
+ if (fetchUrl) {
+ $.getJSON(fetchUrl, function(data) {
+ imageData = JSON.parse(data.MediaOption);
+ _this.$output.val(JSON.stringify(data));
+ _this.$formCropInput.val(JSON.stringify(data));
+ _this.data = imageData || {};
+ if (isSVG(imageData.URL || imageData.Url)) {
+ _this.resetImage();
+ }
+ _this.build();
+ _this.bind();
+ });
+ } else {
+ outputValue = $.trim(this.$output.val());
+ if (outputValue) {
+ data = JSON.parse(outputValue);
+ if (isSVG(data.URL || data.Url)) {
+ this.resetImage();
+ }
+ }
+
+ this.data = data || {};
+
+ this.build();
+ this.bind();
+ }
+ },
+
+ resetImage: function() {
+ this.$parent.addClass('is-svg');
+ },
+
+ build: function() {
+ let textData = this.$output.data(),
+ text = {},
+ replaceTexts;
+
+ if (textData) {
+ text = {
+ title: textData.cropperTitle,
+ ok: textData.cropperOk,
+ cancel: textData.cropperCancel
+ };
+ replaceTexts = this.options.text;
+ }
+
+ if (text.ok && text.title && text.cancel) {
+ replaceTexts = text;
+ }
+
+ this.wrap();
+ this.$modal = $(replaceText(QorCropper.MODAL, replaceTexts)).appendTo('body');
+ },
+
+ unbuild: function() {
+ this.$modal.remove();
+ this.unwrap();
+ },
+
+ wrap: function() {
+ let $list = this.$list,
+ $img;
+
+ $img = $list.find('img').not('.is-svg');
+
+ if ($img.length) {
+ $list.find('li').append(QorCropper.TOGGLE);
+ $img.wrap(QorCropper.CANVAS);
+ this.center($img);
+ } else {
+ $list.find(CLASS_CROP).remove();
+ }
+ },
+
+ unwrap: function() {
+ let $list = this.$list;
+
+ $list.find(CLASS_TOGGLE).remove();
+ $list.find(CLASS_CANVAS).each(function() {
+ let $this = $(this);
+
+ $this.before($this.html()).remove();
+ });
+ },
+
+ bind: function() {
+ this.$element.on(EVENT_CHANGE, $.proxy(this.read, this));
+ this.$list.on(EVENT_CLICK, $.proxy(this.click, this));
+ this.$modal.on(EVENT_SHOWN, $.proxy(this.start, this)).on(EVENT_HIDDEN, $.proxy(this.stop, this));
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CHANGE, this.read);
+ this.$list.off(EVENT_CLICK, this.click);
+ this.$modal.off(EVENT_SHOWN, this.start).off(EVENT_HIDDEN, this.stop);
+ },
+
+ click: function(e) {
+ let target = e.target,
+ $target,
+ data = this.data,
+ $alert;
+
+ if (target === this.$list[0]) {
+ return;
+ }
+
+ $target = $(target);
+
+ if ($target.closest(CLASS_DELETE).length) {
+ data.Delete = true;
+
+ this.$output.val(JSON.stringify(data));
+ this.$formCropInput.val(JSON.stringify(data));
+
+ this.$list.hide();
+
+ $alert = $(QorCropper.ALERT);
+ $alert.find(CLASS_UNDO).one(
+ EVENT_CLICK,
+ function() {
+ $alert.remove();
+ this.$list.show();
+ delete data.Delete;
+ this.$output.val(JSON.stringify(data));
+ this.$formCropInput.val(JSON.stringify(data));
+ }.bind(this)
+ );
+ this.$parent.find('.qor-fieldset').append($alert);
+ }
+
+ if ($target.closest(CLASS_CROP).length) {
+ $target = $target.closest('li').find('img');
+ this.$target = $target;
+ this.$modal.qorModal('show');
+ }
+ },
+
+ read: function(e) {
+ let files = e.target.files,
+ file,
+ $list = this.$list,
+ $alert = this.$parent.find('.qor-fieldset__alert');
+
+ $list.show();
+
+ if ($alert.length) {
+ $alert.remove();
+ }
+
+ if (files && files.length) {
+ file = files[0];
+
+ if (/^image\//.test(file.type) && URL) {
+ this.fileType = file.type;
+ this.load(URL.createObjectURL(file));
+ this.$parent.find('.qor-medialibrary__image-desc').show();
+ } else {
+ $list.empty().html(QorCropper.FILE_LIST.replace('{{filename}}', file.name));
+ }
+ }
+ },
+
+ load: function(url, fromExternal, callback) {
+ let options = this.options,
+ _this = this,
+ $list = this.$list,
+ $ul = $(QorCropper.LIST),
+ data = this.data || {},
+ outputOriginalData = this.$output.val() ? JSON.parse(this.$output.val()) : {},
+ outputOriginalDataType = ['Video', 'SelectedType', 'Description'],
+ fileType = this.fileType,
+ $image,
+ imageLength;
+
+ // media box will use load method, has it's own html structure.
+ if (!fromExternal) {
+ $list.find('ul').remove();
+ $list.html($ul);
+ }
+
+ $image = $list.find('img');
+ this.wrap();
+
+ imageLength = $image.length;
+ $image
+ .one('load', function() {
+ if (fileType === 'image/svg+xml') {
+ $list.find(CLASS_TOGGLE).remove();
+ return false;
+ }
+
+ let $this = $(this),
+ naturalWidth = this.naturalWidth,
+ naturalHeight = this.naturalHeight,
+ sizeData = $this.data(),
+ sizeResolution = sizeData.sizeResolution,
+ sizeName = sizeData.sizeName,
+ emulateImageData = {},
+ emulateCropData = {},
+ aspectRatio,
+ width = sizeData.sizeResolutionWidth,
+ height = sizeData.sizeResolutionHeight;
+
+ if (sizeResolution) {
+ if (!width && !height) {
+ width = getValueByNoCaseKey(sizeResolution, 'width');
+ height = getValueByNoCaseKey(sizeResolution, 'height');
+ }
+ if (height && width) {
+ aspectRatio = width / height;
+ } else {
+ aspectRatio = naturalWidth / naturalHeight;
+ }
+
+ if (naturalHeight * aspectRatio > naturalWidth) {
+ width = naturalWidth;
+ height = width / aspectRatio;
+ } else {
+ height = naturalHeight;
+ width = height * aspectRatio;
+ }
+
+ emulateImageData = {
+ naturalWidth: naturalWidth,
+ naturalHeight: naturalHeight
+ };
+
+ emulateCropData = {
+ x: Math.round((naturalWidth - width) / 2),
+ y: Math.round((naturalHeight - height) / 2),
+ width: Math.round(width),
+ height: Math.round(height)
+ };
+
+ _this.preview($this, emulateImageData, emulateCropData);
+
+ if (sizeName) {
+ data.Crop = true;
+
+ if (!data[options.key]) {
+ data[options.key] = {};
+ }
+
+ if (sizeName != 'original') {
+ data[options.key][sizeName] = emulateCropData;
+ }
+ }
+ } else {
+ _this.center($this);
+ }
+
+ // Crop, CropOptions and Delete should be BOOL type, if empty should delete,
+ if (data.Crop === '' || !fromExternal) {
+ delete data.Crop;
+ }
+
+ if (!fromExternal) {
+ data.CropOptions = null;
+ delete data.Sizes;
+ }
+
+ delete data.Delete;
+
+ // Fix media upload image other property missing bug: ["Video", "SelectedType", "Description"]
+ outputOriginalDataType.forEach((type) => {
+ if (outputOriginalData[type]) {
+ data[type] = outputOriginalData[type];
+ }
+ });
+
+ _this.$output.val(JSON.stringify(data));
+ _this.$formCropInput.val(JSON.stringify(data));
+
+ // callback after load complete
+ if (sizeName && data[options.key] && Object.keys(data[options.key]).length >= imageLength) {
+ if (callback && $.isFunction(callback)) {
+ callback();
+ }
+ }
+ })
+ .attr('src', url)
+ .data('originalUrl', url);
+
+ $list.show();
+ },
+
+ start: function() {
+ let options = this.options,
+ $modal = this.$modal,
+ $target = this.$target,
+ sizeData = $target.data(),
+ sizeName = sizeData.sizeName || 'original',
+ sizeResolution = sizeData.sizeResolution,
+ originalUrl = (sizeData && sizeData.originalUrl && $target.attr('data-original-url'))
+ ? (/\.original\./.test(sizeData.originalUrl) ? sizeData.originalUrl
+ : /\.original\./.test($target.attr('data-original-url'))
+ ? $target.attr('data-original-url')
+ : $target.attr('data-original-url').replace(/file\./, 'file.original.'))
+ : $target.attr('src'),
+ $clone = $(`

`),
+ data = this.data || {},
+ _this = this,
+ sizeAspectRatio = NaN,
+ sizeWidth = sizeData.sizeResolutionWidth,
+ sizeHeight = sizeData.sizeResolutionHeight,
+ list;
+
+ if (sizeResolution) {
+ if (!sizeWidth && !sizeHeight) {
+ sizeWidth = getValueByNoCaseKey(sizeResolution, 'width');
+ sizeHeight = getValueByNoCaseKey(sizeResolution, 'height');
+ }
+ sizeAspectRatio = sizeWidth / sizeHeight;
+ }
+
+ if (!data[options.key]) {
+ data[options.key] = {};
+ }
+
+ $modal
+ .trigger('enable.qor.material')
+ .find(CLASS_WRAPPER)
+ .html($clone);
+
+ list = this.getList(sizeAspectRatio);
+
+ if (list) {
+ $modal
+ .find(CLASS_OPTIONS)
+ .show()
+ .append(list);
+ }
+
+ $clone.cropper({
+ aspectRatio: sizeAspectRatio,
+ data: getLowerCaseKeyObject(data[options.key][sizeName]),
+ background: false,
+ movable: false,
+ zoomable: false,
+ scalable: false,
+ rotatable: false,
+ autoCropArea: 1,
+
+ ready: function() {
+ $modal
+ .find('.qor-cropper__options-toggle')
+ .on(EVENT_CLICK, function() {
+ $modal.find('.qor-cropper__options-input').prop('checked', $(this).prop('checked'));
+ })
+ .prop('checked', true);
+
+ $modal.find(CLASS_SAVE).one(EVENT_CLICK, function() {
+ let cropData = $clone.cropper('getData', true),
+ croppedCanvas = $clone.cropper('getCroppedCanvas'),
+ syncData = [],
+ url;
+
+ data.Crop = true;
+ data[options.key][sizeName] = cropData;
+ _this.imageData = $clone.cropper('getImageData');
+ _this.cropData = cropData;
+
+ if (croppedCanvas) {
+ try {
+ url = croppedCanvas.toDataURL();
+ } catch (error) {
+ console.log(error);
+ console.log('Please check image Cross-origin setting');
+ }
+ }
+
+ $modal.find(CLASS_OPTIONS + ' input').each(function() {
+ let $this = $(this);
+
+ if ($this.prop('checked')) {
+ syncData.push($this.attr('name'));
+ }
+ });
+
+ _this.output(url, syncData);
+ $modal.qorModal('hide');
+ });
+ }
+ });
+ },
+
+ stop: function() {
+ this.$modal
+ .trigger('disable.qor.material')
+ .find(CLASS_WRAPPER + ' > img')
+ .cropper('destroy')
+ .remove()
+ .end()
+ .find(CLASS_OPTIONS)
+ .hide()
+ .find('ul')
+ .remove();
+ },
+
+ getList: function(aspectRatio) {
+ let list = [];
+
+ this.$list
+ .find('img')
+ .not(this.$target)
+ .each(function() {
+ let data = $(this).data(),
+ resolution = data.sizeResolution,
+ name = data.sizeName,
+ width = data.sizeResolutionWidth,
+ height = data.sizeResolutionHeight;
+
+ if (resolution) {
+ if (!width && !height) {
+ width = getValueByNoCaseKey(resolution, 'width');
+ height = getValueByNoCaseKey(resolution, 'height');
+ }
+
+ if (width / height === aspectRatio) {
+ list.push(
+ '
'
+ );
+ }
+ }
+ });
+
+ return list.length ? '
' : '';
+ },
+
+ output: function(url, data) {
+ let $target = this.$target;
+
+ if (url) {
+ this.center($target.attr('src', url), true);
+ } else {
+ this.preview($target);
+ }
+
+ if ($.isArray(data) && data.length) {
+ this.autoCrop(url, data);
+ }
+
+ this.$output.val(JSON.stringify(this.data)).trigger(EVENT_CHANGE);
+ this.$formCropInput.val(JSON.stringify(this.data));
+ },
+
+ preview: function($target, emulateImageData, emulateCropData) {
+ let $canvas = $target.parent(),
+ $container = $canvas.parent(),
+ containerWidth = $container.width(),
+ containerHeight = $container.height(),
+ imageData = emulateImageData || this.imageData,
+ cropData = $.extend({}, emulateCropData || this.cropData), // Clone one to avoid changing it
+ aspectRatio = cropData.width / cropData.height,
+ canvasWidth = containerWidth,
+ scaledRatio;
+
+ if (canvasWidth == 0 || imageData.naturalWidth == 0 || imageData.naturalHeight == 0) {
+ return;
+ }
+
+ if (containerHeight * aspectRatio <= containerWidth) {
+ canvasWidth = containerHeight * aspectRatio;
+ }
+
+ scaledRatio = cropData.width / canvasWidth;
+
+ $target.css({
+ maxWidth: imageData.naturalWidth / scaledRatio,
+ maxHeight: imageData.naturalHeight / scaledRatio
+ });
+
+ this.center($target);
+ },
+
+ center: function($target, reset) {
+ $target.each(function() {
+ let $this = $(this),
+ $canvas = $this.parent(),
+ $container = $canvas.parent();
+
+ function center() {
+ let containerHeight = $container.height(),
+ canvasHeight = $canvas.height(),
+ marginTop = 'auto';
+
+ if (canvasHeight < containerHeight) {
+ marginTop = (containerHeight - canvasHeight) / 2;
+ }
+
+ $canvas.css('margin-top', marginTop);
+ }
+
+ if (reset) {
+ $canvas.add($this).removeAttr('style');
+ }
+
+ if (this.complete) {
+ center.call(this);
+ } else {
+ this.onload = center;
+ }
+ });
+ },
+
+ autoCrop: function(url, data) {
+ let cropData = this.cropData,
+ cropOptions = this.data[this.options.key],
+ _this = this;
+
+ this.$list
+ .find('img')
+ .not(this.$target)
+ .each(function() {
+ let $this = $(this),
+ sizeName = $this.data('sizeName');
+
+ if ($.inArray(sizeName, data) > -1) {
+ cropOptions[sizeName] = $.extend({}, cropData);
+
+ if (url) {
+ _this.center($this.attr('src', url), true);
+ } else {
+ _this.preview($this);
+ }
+ }
+ });
+ },
+
+ destroy: function() {
+ if (!isSVG) {
+ this.unbind();
+ this.unbuild();
+ }
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorCropper.DEFAULTS = {
+ parent: false,
+ output: false,
+ list: false,
+ key: 'data',
+ data: null,
+ text: {
+ title: 'Crop the image',
+ ok: 'OK',
+ cancel: 'Cancel'
+ }
+ };
+
+ QorCropper.TOGGLE = `
`;
+
+ QorCropper.ALERT = `
+
+
`;
+
+ QorCropper.CANVAS = '
';
+ QorCropper.LIST = '
';
+ QorCropper.FILE_LIST = `
`;
+ QorCropper.MODAL = `
+
+
+
$[title]
+
+
+
+
+
Sync cropping result to:
+
+
+
+
+
+
`;
+
+ QorCropper.plugin = function(option) {
+ return this.each(function() {
+ let $this = $(this),
+ data = $this.data(NAMESPACE),
+ options,
+ fn;
+
+ if (!data) {
+ if (!$.fn.cropper) {
+ return;
+ }
+
+ if (/destroy/.test(option)) {
+ return;
+ }
+
+ options = $.extend(true, {}, $this.data(), typeof option === 'object' && option);
+ $this.data(NAMESPACE, (data = new QorCropper(this, options)));
+ }
+
+ if (typeof option === 'string' && $.isFunction((fn = data[option]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ let selector = '.qor-file__input',
+ options = {
+ parent: '.qor-file',
+ output: '.qor-file__options',
+ list: '.qor-file__list',
+ key: 'CropOptions'
+ };
+
+ $(document)
+ .on(EVENT_ENABLE, function(e) {
+ QorCropper.plugin.call($(selector, e.target), options);
+ })
+ .on(EVENT_DISABLE, function(e) {
+ QorCropper.plugin.call($(selector, e.target), 'destroy');
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorCropper;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-datepicker.js b/app/views/qor/assets/javascripts/qor/qor-datepicker.js
new file mode 100644
index 0000000..70153fd
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-datepicker.js
@@ -0,0 +1,242 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let NAMESPACE = 'qor.datepicker',
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_CHANGE = 'pick.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ CLASS_EMBEDDED = '.qor-datepicker__embedded',
+ CLASS_SAVE = '.qor-datepicker__save',
+ CLASS_PARENT = '[data-picker-type]';
+
+ function replaceText(str, data) {
+ if (typeof str === 'string') {
+ if (typeof data === 'object') {
+ $.each(data, function(key, val) {
+ str = str.replace('$[' + String(key).toLowerCase() + ']', val);
+ });
+ }
+ }
+
+ return str;
+ }
+
+ function QorDatepicker(element, options) {
+ this.$element = $(element);
+ this.options = $.extend(true, {}, QorDatepicker.DEFAULTS, $.isPlainObject(options) && options);
+ this.date = null;
+ this.formatDate = null;
+ this.built = false;
+ this.pickerData = this.$element.data();
+ this.$parent = this.$element.closest(CLASS_PARENT);
+ this.isDateTimePicker = this.$parent.data('picker-type') == 'datetime';
+ this.$targetInput = this.$parent.find(this.pickerData.targetInput || (this.isDateTimePicker ? '.qor-datetimepicker__input' : '.qor-datepicker__input'));
+ this.init();
+ }
+
+ QorDatepicker.prototype = {
+ init: function() {
+ if (this.$targetInput.is(':disabled')) {
+ this.$element.remove();
+ return;
+ }
+ this.bind();
+ },
+
+ bind: function() {
+ this.$element.on(EVENT_CLICK, $.proxy(this.show, this));
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK, this.show);
+ },
+
+ build: function() {
+ let $modal,
+ $ele = this.$element,
+ $targetInput = this.$targetInput,
+ defaultDate = $targetInput.val(),
+ datepickerOptions = {
+ date: new Date(),
+ inline: true
+ };
+
+ if (this.built) {
+ return;
+ }
+
+ if ($ele.is(':input') && Date.parse($ele.val())) {
+ datepickerOptions.date = new Date($ele.val());
+ } else if (defaultDate && Date.parse(defaultDate)) {
+ datepickerOptions.date = new Date(defaultDate);
+ }
+
+ this.$modal = $modal = $(replaceText(QorDatepicker.TEMPLATE, this.options.text)).appendTo('body');
+
+ if ($targetInput.data('start-date')) {
+ datepickerOptions.startDate = new Date($targetInput.data('start-date'));
+ }
+
+ if ($targetInput.data('end-date')) {
+ datepickerOptions.endDate = new Date($targetInput.data('end-date'));
+ }
+
+
+ $modal
+ .find(CLASS_EMBEDDED)
+ .on(EVENT_CHANGE, $.proxy(this.change, this))
+ .qorDatepicker(datepickerOptions)
+ .triggerHandler(EVENT_CHANGE);
+
+ $modal.find(CLASS_SAVE).on(EVENT_CLICK, $.proxy(this.pick, this));
+
+ this.built = true;
+ },
+
+ unbuild: function() {
+ if (!this.built) {
+ return;
+ }
+
+ this.$modal
+ .find(CLASS_EMBEDDED)
+ .off(EVENT_CHANGE, this.change)
+ .qorDatepicker('destroy')
+ .end()
+ .find(CLASS_SAVE)
+ .off(EVENT_CLICK, this.pick)
+ .end()
+ .remove();
+ },
+
+ change: function(e) {
+ var $modal = this.$modal;
+ var $target = $(e.target);
+ var date;
+
+ this.date = date = $target.qorDatepicker('getDate');
+ this.formatDate = $target.qorDatepicker('getDate', true);
+
+ $modal.find('.qor-datepicker__picked-year').text(date.getFullYear());
+ $modal
+ .find('.qor-datepicker__picked-date')
+ .text(
+ [$target.qorDatepicker('getDayName', date.getDay(), true) + ',', String($target.qorDatepicker('getMonthName', date.getMonth(), true)), date.getDate()].join(' ')
+ );
+ },
+
+ show: function() {
+ if (!this.built) {
+ this.build();
+ }
+
+ this.$modal.qorModal('show');
+ },
+
+ pick: function() {
+ let $targetInput = this.$targetInput,
+ newValue = this.formatDate;
+
+ if (this.isDateTimePicker) {
+ var regDate = /^\d{4}-\d{1,2}-\d{1,2}/;
+ var oldValue = $targetInput.val();
+ var hasDate = regDate.test(oldValue);
+
+ if (hasDate) {
+ newValue = oldValue.replace(regDate, newValue);
+ } else {
+ newValue = newValue + ' 00:00';
+ }
+ }
+
+ $targetInput.val(newValue).trigger('change');
+ this.$modal.qorModal('hide');
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.unbuild();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorDatepicker.DEFAULTS = {
+ text: {
+ title: 'Pick a date',
+ ok: 'OK',
+ cancel: 'Cancel'
+ }
+ };
+
+ QorDatepicker.TEMPLATE = `
`;
+
+ QorDatepicker.plugin = function(option) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var options;
+ var fn;
+
+ if (!data) {
+ if (!$.fn.qorDatepicker) {
+ return;
+ }
+
+ if (/destroy/.test(option)) {
+ return;
+ }
+
+ options = $.extend(true, {}, $this.data(), typeof option === 'object' && option);
+ $this.data(NAMESPACE, (data = new QorDatepicker(this, options)));
+ }
+
+ if (typeof option === 'string' && $.isFunction((fn = data[option]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.datepicker"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorDatepicker.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorDatepicker.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorDatepicker;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-dirtyform.js b/app/views/qor/assets/javascripts/qor/qor-dirtyform.js
new file mode 100644
index 0000000..4814168
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-dirtyform.js
@@ -0,0 +1,106 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ var dirtyForm = function(ele, options) {
+ var hasChangedObj = false;
+
+ if (this instanceof jQuery) {
+ options = ele;
+ ele = this;
+ } else if (!(ele instanceof jQuery)) {
+ ele = $(ele);
+ }
+
+ ele.each(function(item, element) {
+ var $ele = $(element);
+
+ if ($ele.is('form')) {
+ if ($ele.hasClass('ignore-dirtyform')) {
+ return false;
+ }
+ hasChangedObj = dirtyForm(
+ $ele.find(
+ 'input:not([type="hidden"]):not(".search-field input"):not(".chosen-search input"):not(".ignore-dirtyform"), textarea, select'
+ ),
+ options
+ );
+ if (hasChangedObj) {
+ return false;
+ }
+ } else if ($ele.is(':checkbox') || $ele.is(':radio')) {
+ if ($ele.hasClass('ignore-dirtyform')) {
+ return false;
+ }
+
+ if (element.checked != element.defaultChecked) {
+ hasChangedObj = true;
+ return false;
+ }
+ } else if ($ele.is('input') || $ele.is('textarea')) {
+ if ($ele.hasClass('ignore-dirtyform')) {
+ return false;
+ }
+
+ if (element.value != element.defaultValue) {
+ hasChangedObj = true;
+ return false;
+ }
+ } else if ($ele.is('select')) {
+ if ($ele.hasClass('ignore-dirtyform')) {
+ return false;
+ }
+
+ var option;
+ var defaultSelectedIndex = 0;
+ var numberOfOptions = element.options.length;
+
+ for (var i = 0; i < numberOfOptions; i++) {
+ option = element.options[i];
+ hasChangedObj = hasChangedObj || option.selected != option.defaultSelected;
+ if (option.defaultSelected) {
+ defaultSelectedIndex = i;
+ }
+ }
+
+ if (hasChangedObj && !element.multiple) {
+ hasChangedObj = defaultSelectedIndex != element.selectedIndex;
+ }
+
+ if (hasChangedObj) {
+ return false;
+ }
+ }
+ });
+
+ return hasChangedObj;
+ };
+
+ $.fn.extend({
+ dirtyForm: dirtyForm
+ });
+
+ $(function() {
+ $(document).on('submit', 'form', function() {
+ $.fn.qorSlideoutBeforeHide = null;
+ });
+
+ $(document).on('change', 'form', function() {
+ if ($(this).dirtyForm()) {
+ $.fn.qorSlideoutBeforeHide = true;
+ } else {
+ $.fn.qorSlideoutBeforeHide = null;
+ }
+ });
+ });
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-filter-time.js b/app/views/qor/assets/javascripts/qor/qor-filter-time.js
new file mode 100644
index 0000000..c8455ab
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-filter-time.js
@@ -0,0 +1,302 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let location = window.location,
+ $document = $(document),
+ NAMESPACE = 'qor.filter',
+ EVENT_FILTER_CHANGE = 'filterChanged.' + NAMESPACE,
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ CLASS_BOTTOMSHEETS = '.qor-bottomsheets',
+ CLASS_DATE_START = '.qor-filter__start',
+ CLASS_DATE_END = '.qor-filter__end',
+ CLASS_SEARCH_PARAM = '[data-search-param]',
+ CLASS_FILTER_SELECTOR = '.qor-filter__dropdown',
+ CLASS_FILTER_TOGGLE = '.qor-filter-toggle',
+ CLASS_IS_SELECTED = 'is-selected';
+
+ function QorFilterTime(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorFilterTime.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorFilterTime.prototype = {
+ constructor: QorFilterTime,
+
+ init: function() {
+ this.bind();
+ let $element = this.$element,
+ lcoal_moment = window.moment();
+
+ this.$timeStart = $element.find(CLASS_DATE_START);
+ this.$timeEnd = $element.find(CLASS_DATE_END);
+ this.$searchParam = $element.find(CLASS_SEARCH_PARAM);
+ this.$searchButton = $element.find(this.options.button);
+
+ this.startWeekDate = lcoal_moment.startOf('isoweek').toDate();
+ this.endWeekDate = lcoal_moment.endOf('isoweek').toDate();
+
+ this.startMonthDate = lcoal_moment.startOf('month').toDate();
+ this.endMonthDate = lcoal_moment.endOf('month').toDate();
+ this.initActionTemplate();
+ },
+
+ bind: function() {
+ var options = this.options;
+
+ this.$element
+ .on(EVENT_CLICK, options.trigger, this.show.bind(this))
+ .on(EVENT_CLICK, options.label, this.setFilterTime.bind(this))
+ .on(EVENT_CLICK, options.clear, this.clear.bind(this))
+ .on(EVENT_CLICK, options.button, this.search.bind(this));
+
+ $document.on(EVENT_CLICK, this.close);
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK);
+ },
+
+ initActionTemplate: function() {
+ let paramFrom = this.$element.data('schedule-from');
+ let paramTo = this.$element.data('schedule-to');
+
+
+ let scheduleStartAt = this.getUrlParameter(paramFrom || 'schedule_start_at');
+ let scheduleEndAt = this.getUrlParameter(paramTo || 'schedule_end_at');
+ let $filterToggle = $(this.options.trigger);
+
+ if (scheduleStartAt || scheduleEndAt) {
+ this.$timeStart.val(scheduleStartAt);
+ this.$timeEnd.val(scheduleEndAt);
+
+ scheduleEndAt = !scheduleEndAt ? '' : ' - ' + scheduleEndAt;
+ $filterToggle
+ .addClass('active clearable')
+ .find('.qor-selector-label')
+ .html(scheduleStartAt + scheduleEndAt);
+ $filterToggle.append('
clear');
+ }
+ },
+
+ show: function() {
+ this.$element.find(CLASS_FILTER_SELECTOR).toggle();
+ },
+
+ close: function(e) {
+ var $target = $(e.target),
+ $filter = $(CLASS_FILTER_SELECTOR),
+ filterVisible = $filter.is(':visible'),
+ isInFilter = $target.closest(CLASS_FILTER_SELECTOR).length,
+ isInToggle = $target.closest(CLASS_FILTER_TOGGLE).length,
+ isInModal = $target.closest('.qor-modal').length,
+ isInTimePicker = $target.closest('.ui-timepicker-wrapper').length;
+
+ if (filterVisible && (isInFilter || isInToggle || isInModal || isInTimePicker)) {
+ return;
+ }
+ $filter.hide();
+ },
+
+ setFilterTime: function(e) {
+ let $target = $(e.target),
+ data = $target.data(),
+ range = data.filterRange,
+ startTime,
+ endTime,
+ startDate,
+ endDate;
+
+ if (!range) {
+ return false;
+ }
+
+ $(this.options.label).removeClass(CLASS_IS_SELECTED);
+ $target.addClass(CLASS_IS_SELECTED);
+
+ if (range == 'events') {
+ this.$timeStart.val(data.scheduleStartAt || '');
+ this.$timeEnd.val(data.scheduleEndAt || '');
+ this.$searchButton.click();
+ return false;
+ }
+
+ switch (range) {
+ case 'today':
+ startDate = endDate = new Date();
+ break;
+ case 'week':
+ startDate = this.startWeekDate;
+ endDate = this.endWeekDate;
+ break;
+ case 'month':
+ startDate = this.startMonthDate;
+ endDate = this.endMonthDate;
+ break;
+ }
+
+ if (!startDate || !endDate) {
+ return false;
+ }
+
+ startTime = this.getTime(startDate) + ' 00:00';
+ endTime = this.getTime(endDate) + ' 23:59';
+
+ this.$timeStart.val(startTime);
+ this.$timeEnd.val(endTime);
+ this.$searchButton.click();
+ },
+
+ getTime: function(dateNow) {
+ var month = dateNow.getMonth() + 1,
+ date = dateNow.getDate();
+
+ month = month < 10 ? '0' + month : month;
+ date = date < 10 ? '0' + date : date;
+
+ return dateNow.getFullYear() + '-' + month + '-' + date;
+ },
+
+ clear: function() {
+ var $trigger = $(this.options.trigger),
+ $label = $trigger.find('.qor-selector-label');
+
+ $trigger.removeClass('active clearable');
+ $label.html($label.data('label'));
+ this.$timeStart.val('');
+ this.$timeEnd.val('');
+
+ this.$searchButton.click();
+ return false;
+ },
+
+ getUrlParameter: function(name) {
+ let search = decodeURIComponent(location.search),
+ parameterName = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'),
+ regex = new RegExp('[\\?&]' + parameterName + '=([^]*)'),
+ results = regex.exec(search);
+
+ return results === null ? '' : results[1].replace(/\+/g, ' ');
+ },
+
+ updateQueryStringParameter: function(key, value, url) {
+ let href = url || location.href,
+ local_hash = href.match(/#\S*$/) || '',
+ escapedkey = String(key).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&'),
+ re = new RegExp('([?&])' + escapedkey + '=.*?(&|$)', 'i'),
+ separator = href.indexOf('?') !== -1 ? '&' : '?';
+
+ if (local_hash) {
+ local_hash = local_hash[0];
+ href = href.replace(local_hash, '');
+ }
+
+ if (href.match(re)) {
+ if (value) {
+ href = href.replace(re, '$1' + key + '=' + value + '$2');
+ } else {
+ if (RegExp.$1 === '?' || RegExp.$1 === RegExp.$2) {
+ href = href.replace(re, '$1');
+ } else {
+ href = href.replace(re, '');
+ }
+ }
+ } else if (value) {
+ href = href + separator + key + '=' + value;
+ }
+
+ return href + local_hash;
+ },
+
+ search: function() {
+ var $searchParam = this.$searchParam,
+ href = location.href,
+ _this = this,
+ type = 'qor.filter.time';
+
+ if (!$searchParam.length) {
+ return;
+ }
+
+ $searchParam.each(function() {
+ var $this = $(this),
+ searchParam = $this.data().searchParam,
+ val = $this.val();
+
+ href = _this.updateQueryStringParameter(searchParam, val, href);
+ });
+
+ if (this.$element.closest(CLASS_BOTTOMSHEETS).length) {
+ $(CLASS_BOTTOMSHEETS).trigger(EVENT_FILTER_CHANGE, [href, type]);
+ } else {
+ location.href = href;
+ }
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorFilterTime.DEFAULTS = {
+ label: false,
+ trigger: false,
+ button: false,
+ clear: false
+ };
+
+ QorFilterTime.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorFilterTime(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.filter.time"]';
+ var options = {
+ label: '.qor-filter__block-buttons button',
+ trigger: 'a.qor-filter-toggle',
+ button: '.qor-filter__button-search',
+ clear: '.qor-selector-clear'
+ };
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorFilterTime.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorFilterTime.plugin.call($(selector, e.target), options);
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorFilterTime;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-filter.js b/app/views/qor/assets/javascripts/qor/qor-filter.js
new file mode 100644
index 0000000..ad9d0d5
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-filter.js
@@ -0,0 +1,237 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let location = window.location,
+ NAMESPACE = 'qor.filter',
+ EVENT_FILTER_CHANGE = 'filterChanged.' + NAMESPACE,
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_CHANGE = 'change.' + NAMESPACE,
+ CLASS_IS_ACTIVE = 'is-active',
+ CLASS_BOTTOMSHEETS = '.qor-bottomsheets';
+
+ function encodeSearch(data, detached) {
+ var search = decodeURI(location.search);
+ var per_page = location.search.match(/per_page=\d+/);
+ var params;
+
+ search = search.replace(/per_page=\d+/g,'').replace(/page=\d+/,'page=1');
+
+
+ if(per_page && per_page.length){
+ search = search + "&" + per_page[0];
+ }
+
+
+ if ($.isArray(data)) {
+ params = decodeSearch(search);
+
+ $.each(data, function(i, param) {
+ i = $.inArray(param, params);
+
+ if (i === -1) {
+ params.push(param);
+ } else if (detached) {
+ params.splice(i, 1);
+ }
+ });
+
+ search = '?' + params.join('&');
+ }
+
+ return search;
+ }
+
+ function decodeSearch(search) {
+ var data = [];
+
+ if (search && search.indexOf('?') > -1) {
+ search = search.replace(/\+/g, ' ').split('?')[1];
+
+ if (search && search.indexOf('#') > -1) {
+ search = search.split('#')[0];
+ }
+
+ if (search) {
+ // search = search.toLowerCase();
+ data = $.map(search.split('&'), function(n) {
+ var param = [];
+ var value;
+
+ n = n.split('=');
+ value = n[1];
+ param.push(n[0]);
+
+ if (value) {
+ value = $.trim(decodeURIComponent(value));
+
+ if (value) {
+ param.push(value);
+ }
+ }
+
+ return param.join('=');
+ });
+ }
+ }
+
+ return data;
+ }
+
+ function QorFilter(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorFilter.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorFilter.prototype = {
+ constructor: QorFilter,
+
+ init: function() {
+ // this.parse();
+ this.bind();
+ },
+
+ bind: function() {
+ var options = this.options;
+
+ this.$element.on(EVENT_CLICK, options.label, $.proxy(this.toggle, this)).on(EVENT_CHANGE, options.group, $.proxy(this.toggle, this));
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK, this.toggle).off(EVENT_CHANGE, this.toggle);
+ },
+
+ toggle: function(e) {
+ let $target = $(e.currentTarget),
+ data = [],
+ params,
+ param,
+ search,
+ name,
+ value,
+ index,
+ matched,
+ paramName;
+
+ if ($target.is('select')) {
+ params = decodeSearch(decodeURI(location.search));
+
+ paramName = name = $target.attr('name');
+ value = $target.val();
+ param = [name];
+
+ if (value) {
+ param.push(value);
+ }
+
+ param = param.join('=');
+
+ if (value) {
+ data.push(param);
+ }
+
+ $target.children().each(function() {
+ var $this = $(this);
+ var param = [name];
+ var value = $.trim($this.prop('value'));
+
+ if (value) {
+ param.push(value);
+ }
+
+ param = param.join('=');
+ index = $.inArray(param, params);
+
+ if (index > -1) {
+ matched = param;
+ return false;
+ }
+ });
+
+ if (matched) {
+ data.push(matched);
+ search = encodeSearch(data, true);
+ } else {
+ search = encodeSearch(data);
+ }
+ } else if ($target.is('a')) {
+ e.preventDefault();
+ paramName = $target.data().paramName;
+ data = decodeSearch($target.attr('href'));
+ if ($target.hasClass(CLASS_IS_ACTIVE)) {
+ search = encodeSearch(data, true); // set `true` to detach
+ } else {
+ search = encodeSearch(data);
+ }
+ }
+
+ if (this.$element.closest(CLASS_BOTTOMSHEETS).length) {
+ $(CLASS_BOTTOMSHEETS).trigger(EVENT_FILTER_CHANGE, [search, paramName]);
+ } else {
+ location.search = search;
+ }
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorFilter.DEFAULTS = {
+ label: false,
+ group: false
+ };
+
+ QorFilter.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorFilter(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.filter"]';
+ var options = {
+ label: 'a',
+ group: 'select'
+ };
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorFilter.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorFilter.plugin.call($(selector, e.target), options);
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorFilter;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-fixer.js b/app/views/qor/assets/javascripts/qor/qor-fixer.js
new file mode 100644
index 0000000..c214b9c
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-fixer.js
@@ -0,0 +1,169 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let $window = $(window),
+ NAMESPACE = 'qor.fixer',
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_RESIZE = 'resize.' + NAMESPACE,
+ EVENT_SCROLL = 'scroll.' + NAMESPACE,
+ CLASS_FIXED_TABLE = 'qor-table-fixed-header',
+ CLASS_HEADER = '.qor-page__header';
+
+ function QorFixer(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorFixer.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorFixer.prototype = {
+ constructor: QorFixer,
+
+ init: function() {
+ var options = this.options;
+ var $this = this.$element;
+ if (this.isNeedBuild()) {
+ return;
+ }
+ this.$thead = $this.find('> thead');
+ this.$tbody = $this.find('> tbody');
+
+ this.$header = $(options.header);
+ this.$subHeader = $(options.subHeader);
+ this.$content = $(options.content);
+ this.marginBottomPX = parseInt(this.$subHeader.css('marginBottom'));
+ this.paddingHeight = options.paddingHeight;
+
+ this.resize();
+ this.bind();
+ },
+
+ bind: function() {
+ this.$content.on(EVENT_SCROLL, this.toggle.bind(this));
+ $window.on(EVENT_RESIZE, this.resize.bind(this));
+ },
+
+ unbind: function() {
+ this.$content.off(EVENT_SCROLL, this.toggle).off(EVENT_RESIZE, this.resize);
+ },
+
+ isNeedBuild: function() {
+ var $this = this.$element;
+ // disable fixer if have multiple tables or in search page or in media library list page
+ if (
+ $('.qor-page__body .qor-js-table').length > 1 ||
+ $('.qor-global-search--container').length > 0 ||
+ $this.hasClass('qor-table--medialibrary') ||
+ $this.is(':hidden') ||
+ $this.find('tbody > tr:visible').length <= 1 ||
+ $this.data("disable-fixer")
+ ) {
+ return true;
+ }
+ return false;
+ },
+
+ build: function() {
+ let headerWidth = [],
+ $items = this.$tbody.find('> tr:first').children();
+
+ $items.each(function() {
+ let tdWidth = $(this).outerWidth();
+ $(this).outerWidth(tdWidth);
+ headerWidth.push(tdWidth);
+ });
+
+ this.$thead
+ .find('>tr')
+ .children()
+ .each(function(i) {
+ $(this).outerWidth(headerWidth[i]);
+ });
+ },
+
+ toggle: function() {
+ if (!this.$content.length) {
+ return;
+ }
+ let $element = this.$element,
+ $thead = this.$thead,
+ scrollTop = this.$content.scrollTop(),
+ offsetTop = this.$subHeader.outerHeight() + this.paddingHeight + this.marginBottomPX,
+ headerHeight = $('.qor-page__header').outerHeight(),
+ pageTop = this.$content.offset().top + $(CLASS_HEADER).height();
+
+ if (scrollTop > offsetTop - headerHeight) {
+ $thead.css({top: pageTop});
+ $element.addClass(CLASS_FIXED_TABLE);
+ } else {
+ $element.removeClass(CLASS_FIXED_TABLE);
+ }
+ },
+
+ resize: function() {
+ this.build();
+ this.toggle();
+ },
+
+ destroy: function() {
+ if (this.buildCheck()) {
+ return;
+ }
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorFixer.DEFAULTS = {
+ header: false,
+ content: false
+ };
+
+ QorFixer.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ $this.data(NAMESPACE, (data = new QorFixer(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.call(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '.qor-js-table';
+ var options = {
+ header: '.mdl-layout__header',
+ subHeader: '.qor-page__header',
+ content: '.mdl-layout__content',
+ paddingHeight: 2 // Fix sub header height bug
+ };
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorFixer.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorFixer.plugin.call($(selector, e.target), options);
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorFixer;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-inline-edit.js b/app/views/qor/assets/javascripts/qor/qor-inline-edit.js
new file mode 100644
index 0000000..0dfa19e
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-inline-edit.js
@@ -0,0 +1,202 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ const NAMESPACE = 'qor.inlineEdit',
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_MOUSEENTER = 'mouseenter.' + NAMESPACE,
+ EVENT_MOUSELEAVE = 'mouseleave.' + NAMESPACE,
+ CLASS_FIELD = '.qor-field',
+ CLASS_FIELD_SHOW = '.qor-field__show',
+ CLASS_FIELD_SHOW_INNER = '.qor-field__show-inner',
+ CLASS_EDIT = '.qor-inlineedit__edit',
+ CLASS_SAVE = '.qor-inlineedit__save',
+ CLASS_BUTTONS = '.qor-inlineedit__buttons',
+ CLASS_CANCEL = '.qor-inlineedit__cancel',
+ CLASS_CONTAINER = 'qor-inlineedit__field';
+
+ function QorInlineEdit(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorInlineEdit.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ function getJsonData(names, data) {
+ let key,
+ value = data[names[0].slice(1)];
+
+ if (names.length > 1) {
+ for (let i = 1; i < names.length; i++) {
+ key = names[i].slice(1);
+ value = $.isArray(value) ? value[0][key] : value[key];
+ }
+ }
+
+ return value;
+ }
+
+ QorInlineEdit.prototype = {
+ constructor: QorInlineEdit,
+
+ init: function() {
+ let $element = this.$element,
+ saveButton = $element.data('button-save'),
+ cancelButton = $element.data('button-cancel');
+
+ this.TEMPLATE_SAVE = `
+
+
+
`;
+ this.bind();
+ },
+
+ bind: function() {
+ this.$element
+ .on(EVENT_MOUSEENTER, CLASS_FIELD_SHOW, this.showEditButton)
+ .on(EVENT_MOUSELEAVE, CLASS_FIELD_SHOW, this.hideEditButton)
+ .on(EVENT_CLICK, CLASS_CANCEL, this.hideEdit)
+ .on(EVENT_CLICK, CLASS_SAVE, this.saveEdit)
+ .on(EVENT_CLICK, CLASS_EDIT, this.showEdit.bind(this));
+ },
+
+ unbind: function() {
+ this.$element
+ .off(EVENT_MOUSEENTER)
+ .off(EVENT_MOUSELEAVE)
+ .off(EVENT_CLICK);
+ },
+
+ showEditButton: function(e) {
+ let $edit = $(QorInlineEdit.TEMPLATE_EDIT),
+ $field = $(e.target).closest(CLASS_FIELD);
+
+ if ($field.find('input:disabled, textarea:disabled,select:disabled').length) {
+ return false;
+ }
+
+ $edit.appendTo($(this));
+ },
+
+ hideEditButton: function() {
+ $('.qor-inlineedit__edit').remove();
+ },
+
+ showEdit: function(e) {
+ let $parent = $(e.target)
+ .closest(CLASS_EDIT)
+ .hide()
+ .closest(CLASS_FIELD)
+ .addClass(CLASS_CONTAINER),
+ $save = $(this.TEMPLATE_SAVE);
+
+ $save.appendTo($parent);
+ },
+
+ hideEdit: function() {
+ let $parent = $(this)
+ .closest(CLASS_FIELD)
+ .removeClass(CLASS_CONTAINER);
+ $parent.find(CLASS_BUTTONS).remove();
+ },
+
+ saveEdit: function() {
+ let $btn = $(this),
+ $parent = $btn.closest(CLASS_FIELD),
+ $form = $btn.closest('form'),
+ $hiddenInput = $parent.closest('.qor-fieldset').find('input.qor-hidden__primary_key[type="hidden"]'),
+ $input = $parent.find('input[name*="QorResource"],textarea[name*="QorResource"],select[name*="QorResource"]'),
+ names = $input.length && $input.prop('name').match(/\.\w+/g),
+ inputData = $input.serialize();
+
+ if ($hiddenInput.length) {
+ inputData = `${inputData}&${$hiddenInput.serialize()}`;
+ }
+
+ if (names.length) {
+ $.ajax($form.prop('action'), {
+ method: $form.prop('method'),
+ data: inputData,
+ dataType: 'json',
+ beforeSend: function() {
+ $btn.prop('disabled', true);
+ },
+ success: function(data) {
+ let newValue = getJsonData(names, data),
+ $show = $parent.removeClass(CLASS_CONTAINER).find(CLASS_FIELD_SHOW),
+ $inner = $show.find(CLASS_FIELD_SHOW_INNER);
+
+ if (typeof newValue === 'string' || newValue instanceof String){
+ newValue = newValue.escapeSymbol();
+ }
+
+ if ($inner.length) {
+ $inner.html(newValue);
+ } else {
+ $show.html(newValue);
+ }
+
+ $parent.find(CLASS_BUTTONS).remove();
+ $btn.prop('disabled', false);
+ },
+ error: function(err) {
+ window.QOR.handleAjaxError(err);
+ $btn.prop('disabled', false);
+ }
+ });
+ }
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorInlineEdit.DEFAULTS = {};
+
+ QorInlineEdit.TEMPLATE_EDIT = `
`;
+
+ QorInlineEdit.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ $this.data(NAMESPACE, (data = new QorInlineEdit(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.call(data);
+ }
+ });
+ };
+
+ $(function() {
+ let selector = '[data-toggle="qor.inlineEdit"]',
+ options = {};
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorInlineEdit.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorInlineEdit.plugin.call($(selector, e.target), options);
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorInlineEdit;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-material.js b/app/views/qor/assets/javascripts/qor/qor-material.js
new file mode 100644
index 0000000..cdd7bea
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-material.js
@@ -0,0 +1,59 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let componentHandler = window.componentHandler,
+ NAMESPACE = 'qor.material',
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_UPDATE = 'update.' + NAMESPACE,
+ SELECTOR_COMPONENT = '[class*="mdl-js"],[class*="mdl-tooltip"]';
+
+ function enable(target) {
+ /*jshint undef:false */
+ if (componentHandler) {
+ // Enable all MDL (Material Design Lite) components within the target element
+ if ($(target).is(SELECTOR_COMPONENT)) {
+ componentHandler.upgradeElements(target);
+ } else {
+ componentHandler.upgradeElements($(SELECTOR_COMPONENT, target).toArray());
+ }
+ }
+ }
+
+ function disable(target) {
+ /*jshint undef:false */
+ if (componentHandler) {
+ // Destroy all MDL (Material Design Lite) components within the target element
+ if ($(target).is(SELECTOR_COMPONENT)) {
+ componentHandler.downgradeElements(target);
+ } else {
+ componentHandler.downgradeElements($(SELECTOR_COMPONENT, target).toArray());
+ }
+ }
+ }
+
+ $(function() {
+ $(document)
+ .on(EVENT_ENABLE, function(e) {
+ enable(e.target);
+ })
+ .on(EVENT_DISABLE, function(e) {
+ disable(e.target);
+ })
+ .on(EVENT_UPDATE, function(e) {
+ disable(e.target);
+ enable(e.target);
+ });
+ });
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-modal.js b/app/views/qor/assets/javascripts/qor/qor-modal.js
new file mode 100644
index 0000000..35ac03f
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-modal.js
@@ -0,0 +1,235 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let $document = $(document),
+ NAMESPACE = 'qor.modal',
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_KEYUP = 'keyup.' + NAMESPACE,
+ EVENT_SHOW = 'show.' + NAMESPACE,
+ EVENT_SHOWN = 'shown.' + NAMESPACE,
+ EVENT_HIDE = 'hide.' + NAMESPACE,
+ EVENT_HIDDEN = 'hidden.' + NAMESPACE,
+ EVENT_TRANSITION_END = 'transitionend',
+ CLASS_OPEN = 'qor-modal-open',
+ CLASS_SHOWN = 'shown',
+ CLASS_FADE = 'fade',
+ CLASS_IN = 'in',
+ ARIA_HIDDEN = 'aria-hidden';
+
+ function QorModal(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorModal.DEFAULTS, $.isPlainObject(options) && options);
+ this.transitioning = false;
+ this.fadable = false;
+ this.init();
+ }
+
+ QorModal.prototype = {
+ constructor: QorModal,
+
+ init: function() {
+ this.fadable = this.$element.hasClass(CLASS_FADE);
+
+ if (this.options.show) {
+ this.show();
+ } else {
+ this.toggle();
+ }
+ },
+
+ bind: function() {
+ this.$element.on(EVENT_CLICK, $.proxy(this.click, this));
+
+ if (this.options.keyboard) {
+ $document.on(EVENT_KEYUP, $.proxy(this.keyup, this));
+ }
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK, this.click);
+
+ if (this.options.keyboard) {
+ $document.off(EVENT_KEYUP, this.keyup);
+ }
+ },
+
+ click: function(e) {
+ var element = this.$element[0];
+ var target = e.target;
+
+ if (target === element && this.options.backdrop) {
+ this.hide();
+ return;
+ }
+
+ while (target !== element) {
+ if ($(target).data('dismiss') === 'modal') {
+ this.hide();
+ break;
+ }
+
+ target = target.parentNode;
+ }
+ },
+
+ keyup: function(e) {
+ if (e.which === 27) {
+ this.hide();
+ }
+ },
+
+ show: function(noTransition) {
+ var $this = this.$element,
+ showEvent;
+
+ if (this.transitioning || $this.hasClass(CLASS_IN)) {
+ return;
+ }
+
+ showEvent = $.Event(EVENT_SHOW);
+ $this.trigger(showEvent);
+
+ if (showEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ $document.find('body').addClass(CLASS_OPEN);
+
+ /*jshint expr:true */
+ $this
+ .addClass(CLASS_SHOWN)
+ .scrollTop(0)
+ .get(0).offsetHeight; // reflow for transition
+ this.transitioning = true;
+
+ if (noTransition || !this.fadable) {
+ $this.addClass(CLASS_IN);
+ this.shown();
+ return;
+ }
+
+ $this.one(EVENT_TRANSITION_END, $.proxy(this.shown, this));
+ $this.addClass(CLASS_IN);
+ },
+
+ shown: function() {
+ this.transitioning = false;
+ this.bind();
+ this.$element
+ .attr(ARIA_HIDDEN, false)
+ .trigger(EVENT_SHOWN)
+ .focus();
+ },
+
+ hide: function(noTransition) {
+ var $this = this.$element,
+ hideEvent;
+
+ if (this.transitioning || !$this.hasClass(CLASS_IN)) {
+ return;
+ }
+
+ hideEvent = $.Event(EVENT_HIDE);
+ $this.trigger(hideEvent);
+
+ if (hideEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ $document.find('body').removeClass(CLASS_OPEN);
+ this.transitioning = true;
+
+ if (noTransition || !this.fadable) {
+ $this.removeClass(CLASS_IN);
+ this.hidden();
+ return;
+ }
+
+ $this.one(EVENT_TRANSITION_END, $.proxy(this.hidden, this));
+ $this.removeClass(CLASS_IN);
+ },
+
+ hidden: function() {
+ this.transitioning = false;
+ this.unbind();
+ this.$element
+ .removeClass(CLASS_SHOWN)
+ .attr(ARIA_HIDDEN, true)
+ .trigger(EVENT_HIDDEN);
+ },
+
+ toggle: function() {
+ if (this.$element.hasClass(CLASS_IN)) {
+ this.hide();
+ } else {
+ this.show();
+ }
+ },
+
+ destroy: function() {
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorModal.DEFAULTS = {
+ backdrop: false,
+ keyboard: true,
+ show: true
+ };
+
+ QorModal.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorModal(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $.fn.qorModal = QorModal.plugin;
+
+ $(function() {
+ var selector = '.qor-modal';
+
+ $(document)
+ .on(EVENT_CLICK, '[data-toggle="qor.modal"]', function() {
+ var $this = $(this);
+ var data = $this.data();
+ var $target = $(data.target || $this.attr('href'));
+
+ QorModal.plugin.call($target, $target.data(NAMESPACE) ? 'toggle' : data);
+ })
+ .on(EVENT_DISABLE, function(e) {
+ QorModal.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorModal.plugin.call($(selector, e.target));
+ });
+ });
+
+ return QorModal;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-radio-tabs.js b/app/views/qor/assets/javascripts/qor/qor-radio-tabs.js
new file mode 100644
index 0000000..270f83e
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-radio-tabs.js
@@ -0,0 +1,109 @@
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function ($) {
+
+ 'use strict';
+
+ var NAMESPACE = 'qor.tabbar.radio';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+ var EVENT_CLICK = 'click.' + NAMESPACE;
+ var EVENT_SWITCHED = 'switched.' + NAMESPACE;
+ var CLASS_TAB = '[data-tab-target]';
+ var CLASS_TAB_SOURCE = '[data-tab-source]';
+ var CLASS_ACTIVE = 'is-active';
+
+ function QorTabRadio(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorTabRadio.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorTabRadio.prototype = {
+ constructor: QorTabRadio,
+
+ init: function () {
+ this.bind();
+ },
+
+ bind: function () {
+ this.$element.on(EVENT_CLICK, CLASS_TAB, this.switchTab.bind(this));
+ },
+
+ unbind: function () {
+ this.$element.off(EVENT_CLICK, CLASS_TAB, this.switchTab);
+ },
+
+
+ switchTab: function (e) {
+ var $target = $(e.target),
+ $element = this.$element,
+ $tabs = $element.find(CLASS_TAB),
+ $tabSources = $element.find(CLASS_TAB_SOURCE),
+ data = $target.data(),
+ tabTarget = data.tabTarget;
+
+ if ($target.hasClass(CLASS_ACTIVE)){
+ return;
+ }
+
+ $tabs.removeClass(CLASS_ACTIVE);
+ $target.addClass(CLASS_ACTIVE);
+
+ $tabSources.hide().filter('[data-tab-source="' + tabTarget + '"]').show();
+ $element.trigger(EVENT_SWITCHED, [$element, tabTarget]);
+
+ },
+
+ destroy: function () {
+ this.unbind();
+ }
+ };
+
+ QorTabRadio.DEFAULTS = {};
+
+ QorTabRadio.plugin = function (options) {
+ return this.each(function () {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorTabRadio(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction(fn = data[options])) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function () {
+ var selector = '[data-toggle="qor.tab.radio"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function (e) {
+ QorTabRadio.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function (e) {
+ QorTabRadio.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorTabRadio;
+
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-redactor.js b/app/views/qor/assets/javascripts/qor/qor-redactor.js
new file mode 100644
index 0000000..a598181
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-redactor.js
@@ -0,0 +1,452 @@
+(function(factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as anonymous module.
+ define(["jquery"], factory);
+ } else if (typeof exports === "object") {
+ // Node / CommonJS
+ factory(require("jquery"));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ "use strict";
+
+ let NAMESPACE = "qor.redactor",
+ EVENT_ENABLE = "enable." + NAMESPACE,
+ EVENT_DISABLE = "disable." + NAMESPACE,
+ EVENT_CLICK = "click." + NAMESPACE,
+ EVENT_ADD_CROP = "addCrop." + NAMESPACE,
+ EVENT_REMOVE_CROP = "removeCrop." + NAMESPACE,
+ EVENT_SHOWN = "shown.qor.modal",
+ EVENT_HIDDEN = "hidden.qor.modal",
+ EVENT_SCROLL = "scroll." + NAMESPACE,
+ CLASS_WRAPPER = ".qor-cropper__wrapper",
+ CLASS_SAVE = ".qor-cropper__save",
+ CLASS_CROPPER_TOGGLE = ".qor-cropper__toggle--redactor";
+
+ function encodeCropData(data) {
+ var nums = [];
+
+ if ($.isPlainObject(data)) {
+ $.each(data, function() {
+ nums.push(arguments[1]);
+ });
+ }
+
+ return nums.join();
+ }
+
+ function decodeCropData(data) {
+ var nums = data && data.split(",");
+
+ data = null;
+
+ if (nums && nums.length === 4) {
+ data = {
+ x: Number(nums[0]),
+ y: Number(nums[1]),
+ width: Number(nums[2]),
+ height: Number(nums[3])
+ };
+ }
+
+ return data;
+ }
+
+ function capitalize(str) {
+ if (typeof str === "string") {
+ str = str.charAt(0).toUpperCase() + str.substr(1);
+ }
+
+ return str;
+ }
+
+ function getCapitalizeKeyObject(obj) {
+ var newObj = {},
+ key;
+
+ if ($.isPlainObject(obj)) {
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ newObj[capitalize(key)] = obj[key];
+ }
+ }
+ }
+
+ return newObj;
+ }
+
+ function replaceText(str, data) {
+ if (typeof str === "string") {
+ if (typeof data === "object") {
+ $.each(data, function(key, val) {
+ str = str.replace("$[" + String(key).toLowerCase() + "]", val);
+ });
+ }
+ }
+
+ return str;
+ }
+
+ function redactorToolbarSrcoll($toolbar, $container, toolbarFixedTopOffset) {
+ let offsetTop = $container.offset().top,
+ containerHeight = $container.outerHeight(),
+ normallCSS = {
+ position: "relative",
+ top: "auto",
+ width: "auto"
+ },
+ fixedCSS = {
+ position: "fixed",
+ top: toolbarFixedTopOffset,
+ width: $container.width(),
+ boxShadow: "none"
+ };
+ if (offsetTop < toolbarFixedTopOffset) {
+ if (
+ Math.abs(offsetTop) < Math.abs(containerHeight - toolbarFixedTopOffset)
+ ) {
+ $toolbar.css(fixedCSS);
+ $container.css("padding-top", $toolbar.outerHeight());
+ } else {
+ $toolbar.css(normallCSS);
+ $container.css("padding-top", 0);
+ }
+ } else {
+ $toolbar.css(normallCSS);
+ $container.css("padding-top", 0);
+ }
+ }
+
+ function QorRedactor(element, options) {
+ this.$element = $(element);
+ this.options = $.extend(
+ true,
+ {},
+ QorRedactor.DEFAULTS,
+ $.isPlainObject(options) && options
+ );
+ this.init();
+ }
+
+ QorRedactor.prototype = {
+ constructor: QorRedactor,
+
+ init: function() {
+ var options = this.options;
+ var $this = this.$element;
+ var $parent = $this.closest(options.parent);
+
+ if (!$parent.length) {
+ $parent = $this.parent();
+ }
+
+ this.$parent = $parent;
+ this.$button = $(QorRedactor.BUTTON);
+ this.$modal = $(replaceText(QorRedactor.MODAL, options.text)).appendTo(
+ "body"
+ );
+ this.bind();
+ },
+
+ bind: function() {
+ this.$element
+ .on(EVENT_ADD_CROP, $.proxy(this.addButton, this))
+ .on(EVENT_REMOVE_CROP, $.proxy(this.removeButton, this));
+ },
+
+ unbind: function() {
+ this.$element
+ .off(EVENT_ADD_CROP)
+ .off(EVENT_REMOVE_CROP)
+ .off(EVENT_SCROLL);
+ },
+
+ addButton: function(e, image) {
+ var $image = $(image);
+
+ this.$button
+ .css("left", $(image).width() / 2)
+ .prependTo($image.parent())
+ .find(CLASS_CROPPER_TOGGLE)
+ .one(EVENT_CLICK, $.proxy(this.crop, this, $image));
+ },
+
+ removeButton: function() {
+ this.$button.find(CLASS_CROPPER_TOGGLE).off(EVENT_CLICK);
+ this.$button.detach();
+ },
+
+ crop: function($image) {
+ let options = this.options,
+ url = $image.attr("src"),
+ originalUrl = url,
+ $clone,
+ $modal = this.$modal;
+
+ if ($.isFunction(options.replace)) {
+ originalUrl = options.replace(originalUrl);
+ }
+
+ $clone = $(`

`);
+
+ $modal
+ .one(EVENT_SHOWN, function() {
+ $clone.cropper({
+ data: decodeCropData($image.attr("data-crop-options")),
+ background: false,
+ movable: false,
+ zoomable: false,
+ scalable: false,
+ rotatable: false,
+ checkImageOrigin: false,
+
+ ready: function() {
+ $modal.find(CLASS_SAVE).one(EVENT_CLICK, function() {
+ var cropData = $clone.cropper("getData", true);
+
+ $.ajax(options.remote, {
+ type: "POST",
+ contentType: "application/json",
+ data: JSON.stringify({
+ Url: url,
+ CropOptions: {
+ original: getCapitalizeKeyObject(cropData)
+ },
+ Crop: true
+ }),
+ dataType: "json",
+
+ success: function(response) {
+ if ($.isPlainObject(response) && response.url) {
+ $image
+ .attr("src", response.url)
+ .attr("data-crop-options", encodeCropData(cropData))
+ .removeAttr("style")
+ .removeAttr("rel");
+
+ if ($.isFunction(options.complete)) {
+ options.complete();
+ }
+ $modal.qorModal("hide");
+ }
+ }
+ });
+ });
+ }
+ });
+ })
+ .one(EVENT_HIDDEN, function() {
+ $clone.cropper("destroy").remove();
+ })
+ .qorModal("show")
+ .find(CLASS_WRAPPER)
+ .append($clone);
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$modal.qorModal("hide").remove();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorRedactor.DEFAULTS = {
+ remote: false,
+ parent: false,
+ toggle: false,
+ replace: null,
+ complete: null,
+ text: {
+ title: "Crop the image",
+ ok: "OK",
+ cancel: "Cancel"
+ }
+ };
+
+ QorRedactor.BUTTON = `
+ Edit
+ Crop
+
`;
+
+ QorRedactor.MODAL = `
`;
+
+ QorRedactor.plugin = function(option) {
+ return this.each(function() {
+ let $this = $(this),
+ data = $this.data(NAMESPACE),
+ config,
+ fn;
+
+ if (!data) {
+ if (!window.$R) {
+ return;
+ }
+
+ if (/destroy/.test(option)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = {}));
+
+ let editorButtons = [
+ "html",
+ "format",
+ "bold",
+ "italic",
+ "deleted",
+ "lists",
+ "image",
+ "file",
+ "link"
+ ];
+
+ config = {
+ imageUpload: $this.data("uploadUrl"),
+ fileUpload: $this.data("uploadUrl"),
+ buttons: editorButtons,
+ linkNewTab: true,
+ linkTitle: false,
+ autoparsePaste: false,
+ autoparseLinks: false,
+ multipleUpload: false,
+ toolbarFixedTarget:
+ !$this.closest(".qor-slideout").length &&
+ !$this.closest(".qor-bottomsheets").length
+ ? $("main.mdl-layout__content").length
+ ? "main.mdl-layout__content"
+ : document
+ : document,
+
+ callbacks: {
+ started: function() {
+ let $container = $(this.container.$container.nodes[0]),
+ $toolbar = $(this.toolbar.$toolbar.nodes[0]),
+ isInSlideout = $(".qor-slideout").is(":visible"),
+ toolbarFixedTarget,
+ toolbarFixedTopOffset = 64;
+
+ if (isInSlideout) {
+ if ($this.closest(".qor-bottomsheets").length != 0) {
+ toolbarFixedTarget = $this.closest(".qor-page__body");
+ toolbarFixedTopOffset = $this
+ .closest(".qor-page__body")
+ .offset().top;
+ } else {
+ toolbarFixedTarget = ".qor-slideout__body";
+ toolbarFixedTopOffset = $(".qor-slideout__header").height();
+ }
+ } else {
+ toolbarFixedTarget = ".qor-layout main.qor-page";
+ toolbarFixedTopOffset =
+ toolbarFixedTopOffset +
+ $(toolbarFixedTarget)
+ .find(".qor-page__header")
+ .height();
+ }
+
+ $(toolbarFixedTarget).on(EVENT_SCROLL, function() {
+ redactorToolbarSrcoll(
+ $toolbar,
+ $container,
+ toolbarFixedTopOffset
+ );
+ });
+
+ if (!$this.data("cropUrl")) {
+ return;
+ }
+
+ $this.data(
+ NAMESPACE,
+ (data = new QorRedactor($this, {
+ remote: $this.data("cropUrl"),
+ text: $this.data("text"),
+ parent: ".qor-field",
+ toggle: ".qor-cropper__toggle--redactor",
+ replace: function(url) {
+ return url.replace(/\.\w+$/, function(extension) {
+ return ".original" + extension;
+ });
+ },
+ complete: $.proxy(function() {
+ this.code.sync();
+ }, this)
+ }))
+ );
+ },
+
+ imageUpload: function(image, json) {
+ var $image = $(image);
+ json.filelink && $image.prop("src", json.filelink);
+ },
+
+ insertedLink: function(link) {
+ var $link = $(link),
+ description = this.link.description;
+
+ $link.prop("title", description ? description : $link.text());
+ this.link.description = "";
+ this.link.linkUrlText = "";
+ this.link.insertedTriggered = true;
+ },
+
+ fileUpload: function(link, json) {
+ $(link)
+ .prop("href", json.filelink)
+ .html(json.filename);
+ }
+ }
+ };
+
+ $.extend(config, $this.data("redactorSettings"));
+ window.$R.prototype.constructor.services.editor.prototype.focus = function() {
+ return false;
+ };
+ window.$R(this, config);
+ } else {
+ if (/destroy/.test(option)) {
+ window.$R(this, "destroy");
+ }
+ }
+
+ if (typeof option === "string" && $.isFunction((fn = data[option]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = 'textarea[data-toggle="qor.redactor"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorRedactor.plugin.call($(selector, e.target), "destroy");
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorRedactor.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorRedactor;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-replicator.js b/app/views/qor/assets/javascripts/qor/qor-replicator.js
new file mode 100644
index 0000000..7827707
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-replicator.js
@@ -0,0 +1,417 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let _ = window._,
+ QOR = window.QOR,
+ NAMESPACE = 'qor.replicator',
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_SUBMIT = 'submit.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_SLIDEOUTBEFORESEND = 'slideoutBeforeSend.qor.slideout.replicator',
+ EVENT_SELECTCOREBEFORESEND = 'selectcoreBeforeSend.qor.selectcore.replicator bottomsheetBeforeSend.qor.bottomsheets.replicator',
+ EVENT_REPLICATOR_ADDED = 'added.' + NAMESPACE,
+ EVENT_REPLICATORS_ADDED = 'addedMultiple.' + NAMESPACE,
+ EVENT_REPLICATORS_ADDED_DONE = 'addedMultipleDone.' + NAMESPACE,
+ CLASS_CONTAINER = '.qor-fieldset-container';
+
+ function QorReplicator(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorReplicator.DEFAULTS, $.isPlainObject(options) && options);
+ this.index = 0;
+ this.init();
+ }
+
+ QorReplicator.prototype = {
+ constructor: QorReplicator,
+
+ init: function() {
+ let $element = this.$element,
+ $template = $element.find('> .qor-field__block > .qor-fieldset--new'),
+ fieldsetName;
+
+ this.singlePage = !($element.closest('.qor-slideout').length && $element.closest('.qor-bottomsheets').length);
+ this.maxitems = $element.data('maxItem');
+ this.isSortable = $element.hasClass('qor-fieldset-sortable');
+
+ if (!$template.length || $element.closest('.qor-fieldset--new').length) {
+ return;
+ }
+
+ // Should destroy all components here
+ $template.trigger('disable');
+ // remove data-select2-id attribute or select2 will disable all previous instance
+ $template.find('select[data-toggle]').removeAttr('data-select2-id');
+
+ // if have isMultiple data value or template length large than 1
+ this.isMultipleTemplate = $element.data('isMultiple');
+
+ if (this.isMultipleTemplate) {
+ this.fieldsetName = [];
+ this.template = {};
+ this.index = [];
+
+ $template.each((i, ele) => {
+ fieldsetName = $(ele).data('fieldsetName');
+ if (fieldsetName) {
+ this.template[fieldsetName] = $(ele).prop('outerHTML');
+ this.fieldsetName.push(fieldsetName);
+ }
+ });
+
+ this.parseMultiple();
+ } else {
+ this.parse($template.prop('outerHTML'));
+ }
+
+ $template.hide();
+ this.bind();
+ this.resetButton();
+ this.resetPositionButton();
+ },
+
+ resetPositionButton: function() {
+ let sortableButton = this.$element.find('> .qor-sortable__button');
+
+ if (this.isSortable) {
+ if (this.getCurrentItems() > 1) {
+ sortableButton.show();
+ } else {
+ sortableButton.hide();
+ }
+ }
+ },
+
+ getCurrentItems: function() {
+ return this.$element.find('> .qor-field__block > .qor-fieldset').not('.qor-fieldset--new,.is-deleted').length;
+ },
+
+ toggleButton: function(isHide) {
+ let $button = this.$element.find('> .qor-field__block > .qor-fieldset__add');
+
+ if (isHide) {
+ $button.hide();
+ } else {
+ $button.show();
+ }
+ },
+
+ resetButton: function() {
+ if (this.maxitems <= this.getCurrentItems()) {
+ this.toggleButton(true);
+ } else {
+ this.toggleButton();
+ }
+ },
+
+ parse: function($tmp) {
+ let template;
+
+ if (!$tmp) {
+ return;
+ }
+ template = this.initTemplate($tmp);
+
+ this.template = template.template;
+ this.index = template.index;
+ },
+
+ parseMultiple: function() {
+ let template,
+ name,
+ fieldsetName = this.fieldsetName;
+
+ for (let i = 0, len = fieldsetName.length; i < len; i++) {
+ name = fieldsetName[i];
+ template = this.initTemplate(this.template[name]);
+ this.template[name] = template.template;
+ this.index.push(template.index);
+ }
+
+ this.multipleIndex = _.max(this.index);
+ },
+
+ initTemplate: function(template) {
+ let i,
+ deepLevel = this.$element.parents(CLASS_CONTAINER).length;
+
+ template = template.replace(/(\w+)\="(\S*\[\d+\]\S*)"/g, function(attribute, name, value) {
+ value = value.replace(/^(\S*)\[(\d+)\]([^\[\]]*)$/, function(input, prefix, index) {
+ if (input === value) {
+ if (name === 'name' && !i) {
+ i = index;
+ }
+
+ if (deepLevel) {
+ // assume input = QorResource.SerializableMeta.Menus[1].SubMenus[2].Items[3].URL
+ // if deepLevel = 1, input should be QorResource.SerializableMeta.Menus[1].SubMenus[{{index}}].Items[3].URL
+ // if deepLevel = 2, input should be QorResource.SerializableMeta.Menus[1].SubMenus[2].Items[{{index}}].URL
+
+ let newInput = '',
+ splitStr = input.split(/\[\d+\]/), // ["QorResource.SerializableMeta.Menus", ".SubMenus", ".Items", ".URL"]
+ sortNumbers = input.match(/\[\d+\]/g); // ["[1]", "[2]", "[3]"]
+
+ for (let j = 0; j < splitStr.length; j++) {
+ let str = '';
+ if (j === deepLevel) {
+ str = '[{{index}}]';
+ } else if (j < sortNumbers.length) {
+ str = sortNumbers[j];
+ }
+ newInput += splitStr[j] + str;
+ }
+
+ return newInput;
+ } else {
+ return input.replace(/\[\d+\]/, '[{{index}}]');
+ }
+ }
+ });
+
+ return name + '="' + value + '"';
+ });
+
+ return {
+ template: template,
+ index: parseFloat(i) + 5 //make sure the index is different from original.
+ };
+ },
+
+ bind: function() {
+ let options = this.options;
+
+ this.$element.on(EVENT_CLICK, options.addClass, $.proxy(this.add, this)).on(EVENT_CLICK, options.delClass, $.proxy(this.del, this));
+
+ this.singlePage && $(document).on(EVENT_SUBMIT, '.mdl-layout__container form', this.clearFieldData);
+ $(document)
+ .on(EVENT_SLIDEOUTBEFORESEND, '.qor-slideout', this.clearFieldDataInSlideout)
+ .on(EVENT_SELECTCOREBEFORESEND, this.clearFieldDataInBottomsheet);
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK);
+
+ this.singlePage && $(document).off(EVENT_SUBMIT, '.mdl-layout__container form', this.clearFieldData);
+ $(document)
+ .off(EVENT_SLIDEOUTBEFORESEND, '.qor-slideout', this.clearFieldDataInSlideout)
+ .off(EVENT_SELECTCOREBEFORESEND, this.clearFieldDataInBottomsheet);
+ },
+
+ clearFieldData: function() {
+ $('.qor-fieldset--new').remove();
+ },
+
+ clearFieldDataInSlideout: function() {
+ $('.qor-slideout .qor-fieldset--new').remove();
+ },
+
+ clearFieldDataInBottomsheet: function() {
+ $('.qor-bottomsheets .qor-fieldset--new').remove();
+ },
+
+ add: function(e, data, isAutomatically) {
+ let options = this.options,
+ $item,
+ template,
+ $target = $(e.target).closest(options.addClass);
+
+ if (this.maxitems <= this.getCurrentItems()) {
+ return false;
+ }
+
+ if (this.isMultipleTemplate) {
+ let templateName = $target.data('template'),
+ parents = $target.closest(this.$element),
+ parentsChildren = parents.children(options.childrenClass),
+ $fieldset = $target.closest(options.childrenClass).children('fieldset');
+
+ template = this.template[templateName];
+ $item = $(template.replace(/\{\{index\}\}/g, this.multipleIndex));
+
+ // get input kind from add button then add into QorResource.Rules[1].Kind input
+ for (let dataKey in $target.data()) {
+ if (dataKey.match(/^sync/)) {
+ let k = dataKey.replace(/^sync/, '');
+ $item.find("input[name*='." + k + "']").val($target.data(dataKey));
+ }
+ }
+
+ if ($fieldset.length) {
+ $fieldset.last().after($item.show());
+ } else {
+ parentsChildren.prepend($item.show());
+ }
+ $item.data('itemIndex', this.multipleIndex).removeClass('qor-fieldset--new');
+ this.multipleIndex++;
+ } else {
+ if (!isAutomatically) {
+ $item = this.addSingle();
+ $target.before($item.show());
+ this.index++;
+ } else {
+ if (data && data.length) {
+ this.addMultiple(data);
+ $(document).trigger(EVENT_REPLICATORS_ADDED_DONE);
+ }
+ }
+ }
+
+ if (!isAutomatically) {
+ $item.trigger('enable');
+ $(document).trigger(EVENT_REPLICATOR_ADDED, [$item]);
+ e.stopPropagation();
+ }
+
+ this.resetPositionButton();
+ this.resetButton();
+ },
+
+ addMultiple: function(data) {
+ let $item;
+
+ for (let i = 0, len = data.length; i < len; i++) {
+ $item = this.addSingle();
+ this.index++;
+ $(document).trigger(EVENT_REPLICATORS_ADDED, [$item, data[i]]);
+ }
+ },
+
+ addSingle: function() {
+ let $item,
+ $element = this.$element;
+
+ if (!this.template) {
+ return;
+ }
+
+ $item = $(this.template.replace(/\{\{index\}\}/g, this.index));
+ // add order property for sortable fieldset
+ if (this.isSortable) {
+ let order = $element.find('> .qor-field__block > .qor-sortable__item').not('.qor-fieldset--new').length;
+ $item
+ .attr('order-index', order)
+ .attr('order-item', `item_${order}`)
+ .css('order', order);
+ }
+
+ $item.data('itemIndex', this.index).removeClass('qor-fieldset--new');
+
+ return $item;
+ },
+
+ del: function(e) {
+ let options = this.options,
+ $item = $(e.target).closest(options.itemClass),
+ $alert,
+ that = this,
+ message = {
+ confirm:
+ $(e.target)
+ .closest(options.delClass)
+ .data('confirm') || 'Are you sure?'
+ };
+
+ QOR.qorConfirm(message, function(confirm) {
+ if (confirm) {
+ $item
+ .addClass('is-deleted')
+ .children(':visible')
+ .addClass('hidden')
+ .hide();
+ $alert = $(options.alertTemplate.replace('{{name}}', that.parseName($item)));
+ $alert.find(options.undoClass).one(
+ EVENT_CLICK,
+ function() {
+ if (that.maxitems <= that.getCurrentItems()) {
+ window.QOR.qorConfirm(that.$element.data('maxItemHint'));
+ return false;
+ }
+
+ $item.find('> .qor-fieldset__alert').remove();
+ $item
+ .removeClass('is-deleted')
+ .children('.hidden')
+ .removeClass('hidden')
+ .show();
+ that.resetButton();
+ that.resetPositionButton();
+ }.bind(this)
+ );
+ that.resetButton();
+ that.resetPositionButton();
+ $item.append($alert);
+ }
+ });
+ },
+
+ parseName: function($item) {
+ let name = $item.find('input[name]').attr('name') || $item.find('textarea[name]').attr('name');
+
+ if (name) {
+ return name.replace(/[^\[\]]+$/, '');
+ }
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorReplicator.DEFAULTS = {
+ itemClass: '.qor-fieldset',
+ newClass: '.qor-fieldset--new',
+ addClass: '.qor-fieldset__add',
+ delClass: '.qor-fieldset__delete',
+ childrenClass: '.qor-field__block',
+ undoClass: '.qor-fieldset__undo',
+ alertTemplate:
+ '
' +
+ '' +
+ '' +
+ '
'
+ };
+
+ QorReplicator.plugin = function(options) {
+ return this.each(function() {
+ let $this = $(this),
+ data = $this.data(NAMESPACE),
+ fn;
+
+ if (!data) {
+ $this.data(NAMESPACE, (data = new QorReplicator(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.call(data);
+ }
+ });
+ };
+
+ $(function() {
+ let selector = CLASS_CONTAINER;
+ let options = {};
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorReplicator.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorReplicator.plugin.call($(selector, e.target), options);
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorReplicator;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-search.js b/app/views/qor/assets/javascripts/qor/qor-search.js
new file mode 100644
index 0000000..6d7eb1d
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-search.js
@@ -0,0 +1,163 @@
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function ($) {
+
+ 'use strict';
+ var location = window.location;
+ var componentHandler = window.componentHandler;
+ var history = window.history;
+ var NAMESPACE = 'qor.globalSearch';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+ var EVENT_CLICK = 'click.' + NAMESPACE;
+
+ var SEARCH_RESOURCE = '.qor-global-search--resource';
+ var SEARCH_RESULTS = '.qor-global-search--results';
+ var QOR_TABLE = '.qor-table';
+ var IS_ACTIVE = 'is-active';
+
+ function QorSearchCenter(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorSearchCenter.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorSearchCenter.prototype = {
+ constructor: QorSearchCenter,
+
+ init: function () {
+ this.bind();
+ this.initTab();
+ },
+
+ bind: function () {
+ this.$element.on(EVENT_CLICK, $.proxy(this.click, this));
+ },
+
+ unbind: function () {
+ this.$element.off(EVENT_CLICK, this.check);
+ },
+
+ initTab: function () {
+ var locationSearch = location.search;
+ var resourceName;
+ if (/resource_name/.test(locationSearch)){
+ resourceName = locationSearch.match(/resource_name=\w+/g).toString().split('=')[1];
+ $(SEARCH_RESOURCE).removeClass(IS_ACTIVE);
+ $('[data-resource="' + resourceName + '"]').addClass(IS_ACTIVE);
+ }
+ },
+
+ click : function (e) {
+ var $target = $(e.target);
+ var data = $target.data();
+
+ if ($target.is(SEARCH_RESOURCE)){
+ var oldUrl = location.href.replace(/#/g, '');
+ var newUrl;
+ var newResourceName = data.resource;
+ var hasResource = /resource_name/.test(oldUrl);
+ var hasKeyword = /keyword/.test(oldUrl);
+ var resourceParam = 'resource_name=' + newResourceName;
+ var searchSymbol = hasKeyword ? '&' : '?keyword=&';
+
+ if (newResourceName){
+ if (hasResource){
+ newUrl = oldUrl.replace(/resource_name=\w+/g, resourceParam);
+ } else {
+ newUrl = oldUrl + searchSymbol + resourceParam;
+ }
+ } else {
+ newUrl = oldUrl.replace(/&resource_name=\w+/g, '');
+ }
+
+ if (history.pushState){
+ this.fetchSearch(newUrl, $target);
+ } else {
+ location.href = newUrl;
+ }
+
+ }
+ },
+
+ fetchSearch: function (url,$target) {
+ var title = document.title;
+
+ $.ajax(url, {
+ method: 'GET',
+ dataType: 'html',
+ beforeSend: function () {
+ $('.mdl-spinner').remove();
+ $(SEARCH_RESULTS).prepend('
').find('.qor-section').hide();
+ componentHandler.upgradeElement(document.querySelector('.mdl-spinner'));
+ },
+ success: function (html) {
+ var result = $(html).find(SEARCH_RESULTS).html();
+ $(SEARCH_RESOURCE).removeClass(IS_ACTIVE);
+ $target.addClass(IS_ACTIVE);
+ // change location URL without refresh page
+ history.pushState({ Page: url, Title: title }, title, url);
+ $('.mdl-spinner').remove();
+ $(SEARCH_RESULTS).removeClass('loading').html(result);
+ componentHandler.upgradeElements(document.querySelectorAll(QOR_TABLE));
+ },
+ error: function (xhr, textStatus, errorThrown) {
+ $(SEARCH_RESULTS).find('.qor-section').show();
+ $('.mdl-spinner').remove();
+ window.alert([textStatus, errorThrown].join(': '));
+ }
+ });
+ },
+
+ destroy: function () {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+
+ };
+
+ QorSearchCenter.DEFAULTS = {
+ };
+
+ QorSearchCenter.plugin = function (options) {
+ return this.each(function () {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ $this.data(NAMESPACE, (data = new QorSearchCenter(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction(fn = data[options])) {
+ fn.call(data);
+ }
+ });
+ };
+
+ $(function () {
+ var selector = '[data-toggle="qor.global.search"]';
+ var options = {};
+
+ $(document).
+ on(EVENT_DISABLE, function (e) {
+ QorSearchCenter.plugin.call($(selector, e.target), 'destroy');
+ }).
+ on(EVENT_ENABLE, function (e) {
+ QorSearchCenter.plugin.call($(selector, e.target), options);
+ }).
+ triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorSearchCenter;
+
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-select-core.js b/app/views/qor/assets/javascripts/qor/qor-select-core.js
new file mode 100644
index 0000000..1583380
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-select-core.js
@@ -0,0 +1,170 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let FormData = window.FormData,
+ QOR = window.QOR,
+ NAMESPACE = 'qor.selectcore',
+ EVENT_SELECTCORE_BEFORESEND = 'selectcoreBeforeSend.' + NAMESPACE,
+ EVENT_ONSELECT = 'afterSelected.' + NAMESPACE,
+ EVENT_ONSUBMIT = 'afterSubmitted.' + NAMESPACE,
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_SUBMIT = 'submit.' + NAMESPACE,
+ CLASS_TABLE = 'table.qor-js-table tr',
+ CLASS_FORM = 'form';
+
+ function QorSelectCore(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorSelectCore.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorSelectCore.prototype = {
+ constructor: QorSelectCore,
+
+ init: function() {
+ this.bind();
+ },
+
+ bind: function() {
+ this.$element.on(EVENT_CLICK, CLASS_TABLE, this.processingData.bind(this)).on(EVENT_SUBMIT, CLASS_FORM, this.submit.bind(this));
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK, CLASS_TABLE).off(EVENT_SUBMIT, CLASS_FORM);
+ },
+
+ processingData: function(e) {
+ let $this = $(e.target).closest('tr'),
+ $bottomsheets = $this.closest('.qor-bottomsheets'),
+ data = {},
+ url,
+ options = this.options,
+ onSelect = options.onSelect,
+ loading = options.loading;
+
+ data = $.extend({}, data, $this.data());
+ data.$clickElement = $this;
+
+ url = data.mediaLibraryUrl || data.url;
+
+ if (loading && $.isFunction(loading)) {
+ loading($bottomsheets);
+ }
+
+ if (url) {
+
+ $.getJSON(url, function(json) {
+ json.MediaOption && (json.MediaOption = JSON.parse(json.MediaOption));
+ data = $.extend({}, json, data);
+ if (onSelect && $.isFunction(onSelect)) {
+ onSelect(data, e);
+ $(document).trigger(EVENT_ONSELECT);
+ }
+ }).always(function() {
+ $bottomsheets.find('.qor-media-loading').remove();
+ });
+
+ } else {
+ if (onSelect && $.isFunction(onSelect)) {
+ onSelect(data, e);
+ $(document).trigger(EVENT_ONSELECT);
+ }
+ }
+ return false;
+ },
+
+ submit: function(e) {
+ let form = e.target,
+ $form = $(form),
+ _this = this,
+ $submit = $form.find(':submit'),
+ data,
+ $loading = $(QOR.$formLoading),
+ onSubmit = this.options.onSubmit;
+
+ $(document).trigger(EVENT_SELECTCORE_BEFORESEND);
+
+ $form.find('.qor-fieldset--new').remove();
+
+ if (FormData) {
+ e.preventDefault();
+
+ $.ajax($form.prop('action'), {
+ method: $form.prop('method'),
+ data: new FormData(form),
+ dataType: 'json',
+ processData: false,
+ contentType: false,
+ beforeSend: function() {
+ $('.qor-submit-loading').remove();
+ $loading.appendTo($submit.prop('disabled', true).closest('.qor-form__actions')).trigger('enable.qor.material');
+ },
+ success: function(json) {
+ json.MediaOption && (json.MediaOption = JSON.parse(json.MediaOption));
+ data = json;
+ data.primaryKey = data.ID;
+
+ $('.qor-error').remove();
+
+ if (onSubmit && $.isFunction(onSubmit)) {
+ onSubmit(data, e);
+ $(document).trigger(EVENT_ONSUBMIT);
+ } else {
+ _this.refresh();
+ }
+ },
+ error: function(err) {
+ QOR.handleAjaxError(err);
+ },
+ complete: function() {
+ $submit.prop('disabled', false);
+ }
+ });
+ }
+ },
+
+ refresh: function() {
+ setTimeout(function() {
+ window.location.reload();
+ }, 350);
+ },
+
+ destroy: function() {
+ this.unbind();
+ }
+ };
+
+ QorSelectCore.plugin = function(options) {
+ return this.each(function() {
+ let $this = $(this),
+ data = $this.data(NAMESPACE),
+ fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+ $this.data(NAMESPACE, (data = new QorSelectCore(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $.fn.qorSelectCore = QorSelectCore.plugin;
+
+ return QorSelectCore;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-select-many.js b/app/views/qor/assets/javascripts/qor/qor-select-many.js
new file mode 100644
index 0000000..0d00252
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-select-many.js
@@ -0,0 +1,339 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let $body = $('body'),
+ $document = $(document),
+ Mustache = window.Mustache,
+ NAMESPACE = 'qor.selectone',
+ PARENT_NAMESPACE = 'qor.bottomsheets',
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_RELOAD = 'reload.' + PARENT_NAMESPACE,
+ CLASS_CLEAR_SELECT = '.qor-selected-many__remove',
+ CLASS_UNDO_DELETE = '.qor-selected-many__undo',
+ CLASS_DELETED_ITEM = 'qor-selected-many__deleted',
+ CLASS_SELECT_FIELD = '.qor-field__selected-many',
+ CLASS_SELECT_INPUT = '.qor-field__selectmany-input',
+ CLASS_SELECT_ICON = '.qor-select__select-icon',
+ CLASS_SELECT_HINT = '.qor-selectmany__hint',
+ CLASS_SELECT_ALL = '.qor-selectmany__selectall',
+ CLASS_PARENT = '.qor-field__selectmany',
+ CLASS_SELECTED = 'is_selected',
+ CLASS_MANY = 'qor-bottomsheets__select-many';
+
+ function QorSelectMany(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorSelectMany.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorSelectMany.prototype = {
+ constructor: QorSelectMany,
+
+ init: function() {
+ this.bind();
+ },
+
+ bind: function() {
+ $document.on(EVENT_RELOAD, `.${CLASS_MANY}`, this.reloadData.bind(this));
+
+ this.$element
+ .on(EVENT_CLICK, CLASS_CLEAR_SELECT, this.clearSelect.bind(this))
+ .on(EVENT_CLICK, '[data-select-modal="many"]', this.openBottomSheets.bind(this))
+ .on(EVENT_CLICK, CLASS_UNDO_DELETE, this.undoDelete.bind(this));
+ },
+
+ unbind: function() {
+ $document.off(EVENT_CLICK, '[data-select-modal="many"]').off(EVENT_RELOAD, `.${CLASS_MANY}`);
+ this.$element.off(EVENT_CLICK, CLASS_CLEAR_SELECT).off(EVENT_CLICK, CLASS_UNDO_DELETE);
+ },
+
+ clearSelect: function(e) {
+ var $target = $(e.target),
+ $selectFeild = $target.closest(CLASS_PARENT);
+
+ $target.closest('[data-primary-key]').addClass(CLASS_DELETED_ITEM);
+ this.updateSelectInputData($selectFeild);
+
+ return false;
+ },
+
+ undoDelete: function(e) {
+ var $target = $(e.target),
+ $selectFeild = $target.closest(CLASS_PARENT);
+
+ $target.closest('[data-primary-key]').removeClass(CLASS_DELETED_ITEM);
+ this.updateSelectInputData($selectFeild);
+
+ return false;
+ },
+
+ openBottomSheets: function(e) {
+ let $this = $(e.target),
+ data = $this.data();
+
+ this.BottomSheets = $body.data('qor.bottomsheets');
+ this.bottomsheetsData = data;
+
+ this.$selector = data.selectId ? $(data.selectId) : $this.closest(CLASS_PARENT).find('select');
+ this.$selectFeild = this.$selector.closest(CLASS_PARENT).find(CLASS_SELECT_FIELD);
+
+ // select many templates
+ this.SELECT_MANY_SELECTED_ICON = $('[name="select-many-selected-icon"]').html();
+ this.SELECT_MANY_UNSELECTED_ICON = $('[name="select-many-unselected-icon"]').html();
+ this.SELECT_MANY_HINT = $('[name="select-many-hint"]').html();
+ this.SELECT_MANY_TEMPLATE = $('[name="select-many-template"]').html();
+
+ data.url = data.selectListingUrl;
+
+ if (data.selectDefaultCreating) {
+ data.url = data.selectCreatingUrl;
+ }
+
+ this.BottomSheets.open(data, this.handleSelectMany.bind(this));
+ },
+
+ reloadData: function() {
+ this.initItems();
+ },
+
+ renderSelectMany: function(data) {
+ return Mustache.render(this.SELECT_MANY_TEMPLATE, data);
+ },
+
+ renderHint: function(data) {
+ return Mustache.render(this.SELECT_MANY_HINT, data);
+ },
+
+ initItems: function() {
+ var $tr = this.$bottomsheets.find('tbody tr'),
+ selectedIconTmpl = this.SELECT_MANY_SELECTED_ICON,
+ unSelectedIconTmpl = this.SELECT_MANY_UNSELECTED_ICON,
+ selectedIDs = [],
+ primaryKey,
+ $selectedItems = this.$selectFeild.find('[data-primary-key]').not('.' + CLASS_DELETED_ITEM);
+
+ $selectedItems.each(function() {
+ selectedIDs.push($(this).data().primaryKey);
+ });
+
+ $tr.each(function() {
+ var $this = $(this),
+ $td = $this.find('td:first');
+
+ primaryKey = $this.data().primaryKey;
+
+ if (selectedIDs.indexOf(primaryKey) != '-1') {
+ $this.addClass(CLASS_SELECTED);
+ $td.append(selectedIconTmpl);
+ } else {
+ $td.append(unSelectedIconTmpl);
+ }
+ });
+
+ this.updateHint(this.getSelectedItemData());
+ },
+
+ getSelectedItemData: function() {
+ var selecedItems = this.$selectFeild.find('[data-primary-key]').not('.' + CLASS_DELETED_ITEM);
+ return {
+ selectedNum: selecedItems.length
+ };
+ },
+
+ updateHint: function(data) {
+ var template;
+
+ $.extend(data, this.bottomsheetsData);
+ template = this.renderHint(data);
+
+ this.$bottomsheets.find(CLASS_SELECT_HINT).remove();
+ this.$bottomsheets.find('.qor-page__body').before(template);
+ },
+
+ updateSelectInputData: function($selectFeild) {
+ var $selectList = $selectFeild ? $selectFeild : this.$selectFeild,
+ $selectedItems = $selectList.find('[data-primary-key]').not('.' + CLASS_DELETED_ITEM),
+ $selector = $selectFeild ? $selectFeild.find(CLASS_SELECT_INPUT) : this.$selector,
+ $options = $selector.find('option'),
+ $option,
+ data,
+ primaryKey;
+
+ $options.prop('selected', false);
+
+ $selectedItems.each(function() {
+ primaryKey = $(this).data().primaryKey;
+ $option = $options.filter('[value="' + primaryKey + '"]');
+
+ if (!$option.length) {
+ data = {
+ primaryKey: primaryKey,
+ displayName: ''
+ };
+ $option = $(Mustache.render(QorSelectMany.SELECT_MANY_OPTION_TEMPLATE, data));
+ $selector.append($option);
+ }
+
+ $option.prop('selected', true);
+ });
+ },
+
+ changeIcon: function($ele, template) {
+ $ele.find(CLASS_SELECT_ICON).remove();
+ $ele.find('td:first').prepend(template);
+ },
+
+ removeItem: function(data) {
+ var primaryKey = data.primaryKey;
+
+ this.$selectFeild
+ .find('[data-primary-key="' + primaryKey + '"]')
+ .find(CLASS_CLEAR_SELECT)
+ .click();
+ this.changeIcon(data.$clickElement, this.SELECT_MANY_UNSELECTED_ICON);
+ },
+
+ addItem: function(data, isNewData) {
+ var template = this.renderSelectMany(data),
+ $option,
+ $list = this.$selectFeild.find('[data-primary-key="' + data.primaryKey + '"]');
+
+ if ($list.length) {
+ if ($list.hasClass(CLASS_DELETED_ITEM)) {
+ $list.removeClass(CLASS_DELETED_ITEM);
+ this.updateSelectInputData();
+ this.changeIcon(data.$clickElement, this.SELECT_MANY_SELECTED_ICON);
+ return;
+ } else {
+ return;
+ }
+ }
+
+ this.$selectFeild.append(template);
+
+ if (isNewData) {
+ $option = $(Mustache.render(QorSelectMany.SELECT_MANY_OPTION_TEMPLATE, data));
+ $option.appendTo(this.$selector);
+ $option.prop('selected', true);
+ this.$bottomsheets.remove();
+ if (!$('.qor-bottomsheets').is(':visible')) {
+ $('body').removeClass('qor-bottomsheets-open');
+ }
+ return;
+ }
+
+ this.changeIcon(data.$clickElement, this.SELECT_MANY_SELECTED_ICON);
+ },
+
+ handleSelectMany: function($bottomsheets) {
+ let options = {
+ onSelect: this.onSelectResults.bind(this), // render selected item after click item lists
+ onSubmit: this.onSubmitResults.bind(this) // render new items after new item form submitted
+ };
+
+ $bottomsheets.qorSelectCore(options).addClass(CLASS_MANY);
+ $bottomsheets.on(EVENT_CLICK, CLASS_SELECT_ALL, this.handleSelectAll.bind(this));
+ this.$bottomsheets = $bottomsheets;
+ this.initItems();
+ },
+
+ handleSelectAll: function() {
+ let $trs = this.$bottomsheets.find('.qor-table tbody tr'),
+ $trsHasUnselected = $trs.not('.is_selected');
+
+ if ($trsHasUnselected.length) {
+ $trsHasUnselected.click();
+ } else {
+ $trs.click();
+ }
+ },
+
+ onSelectResults: function(data) {
+ this.handleResults(data);
+ },
+
+ onSubmitResults: function(data) {
+ this.handleResults(data, true);
+ },
+
+ handleResults: function(data, isNewData) {
+ data.displayName = data.Text || data.Name || data.Title || data.Code || data[Object.keys(data)[0]];
+
+ data.displayName = (data.displayName).escapeSymbol();
+
+ if (isNewData) {
+ this.addItem(data, true);
+ return;
+ }
+
+ var $element = data.$clickElement,
+ isSelected;
+
+ $element.toggleClass(CLASS_SELECTED);
+ isSelected = $element.hasClass(CLASS_SELECTED);
+
+ if (isSelected) {
+ this.addItem(data);
+ } else {
+ this.removeItem(data);
+ }
+
+ this.updateHint(this.getSelectedItemData());
+ this.updateSelectInputData();
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorSelectMany.SELECT_MANY_OPTION_TEMPLATE = '
';
+
+ QorSelectMany.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorSelectMany(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.selectmany"]';
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorSelectMany.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorSelectMany.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorSelectMany;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-select-one.js b/app/views/qor/assets/javascripts/qor/qor-select-one.js
new file mode 100644
index 0000000..ebfb2fb
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-select-one.js
@@ -0,0 +1,214 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ let $body = $('body'),
+ $document = $(document),
+ Mustache = window.Mustache,
+ NAMESPACE = 'qor.selectone',
+ PARENT_NAMESPACE = 'qor.bottomsheets',
+ EVENT_CLICK = 'click.' + NAMESPACE,
+ EVENT_ENABLE = 'enable.' + NAMESPACE,
+ EVENT_DISABLE = 'disable.' + NAMESPACE,
+ EVENT_RELOAD = 'reload.' + PARENT_NAMESPACE,
+ CLASS_CLEAR_SELECT = '.qor-selected__remove',
+ CLASS_CHANGE_SELECT = '.qor-selected__change',
+ CLASS_SELECT_FIELD = '.qor-field__selected',
+ CLASS_SELECT_INPUT = '.qor-field__selectone-input',
+ CLASS_SELECT_TRIGGER = '.qor-field__selectone-trigger',
+ CLASS_PARENT = '.qor-field__selectone',
+ CLASS_SELECTED = 'is_selected',
+ CLASS_ONE = 'qor-bottomsheets__select-one';
+
+ function QorSelectOne(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorSelectOne.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorSelectOne.prototype = {
+ constructor: QorSelectOne,
+
+ init: function() {
+ this.bind();
+ },
+
+ bind: function() {
+ $document.on(EVENT_RELOAD, `.${CLASS_ONE}`, this.reloadData.bind(this));
+ this.$element
+ .on(EVENT_CLICK, CLASS_CLEAR_SELECT, this.clearSelect.bind(this))
+ .on(EVENT_CLICK, '[data-selectone-url]', this.openBottomSheets.bind(this))
+ .on(EVENT_CLICK, CLASS_CHANGE_SELECT, this.changeSelect);
+ },
+
+ unbind: function() {
+ $document.off(EVENT_CLICK, '[data-selectone-url]').off(EVENT_RELOAD, `.${CLASS_ONE}`);
+ this.$element.off(EVENT_CLICK, CLASS_CLEAR_SELECT).off(EVENT_CLICK, CLASS_CHANGE_SELECT);
+ },
+
+ clearSelect: function(e) {
+ var $target = $(e.target),
+ $parent = $target.closest(CLASS_PARENT);
+
+ $parent.find(CLASS_SELECT_FIELD).remove();
+ $parent.find(CLASS_SELECT_INPUT).html('');
+ $parent.find(CLASS_SELECT_INPUT)[0].value = '';
+ $parent.find(CLASS_SELECT_TRIGGER).show();
+
+ $parent.trigger('qor.selectone.unselected');
+ return false;
+ },
+
+ changeSelect: function() {
+ var $target = $(this),
+ $parent = $target.closest(CLASS_PARENT);
+
+ $parent.find(CLASS_SELECT_TRIGGER).trigger('click');
+ },
+
+ openBottomSheets: function(e) {
+ var $this = $(e.target),
+ data = $this.data();
+
+ this.BottomSheets = $body.data('qor.bottomsheets');
+ this.$parent = $this.closest(CLASS_PARENT);
+
+ data.url = data.selectoneUrl;
+
+ this.SELECT_ONE_SELECTED_ICON = $('[name="select-one-selected-icon"]').html();
+ this.BottomSheets.open(data, this.handleSelectOne.bind(this));
+ },
+
+ initItem: function() {
+ var $selectFeild = this.$parent.find(CLASS_SELECT_FIELD),
+ selectedID;
+
+ if (!$selectFeild.length) {
+ return;
+ }
+
+ selectedID = $selectFeild.data().primaryKey;
+
+ if (selectedID) {
+ this.$bottomsheets
+ .find('tr[data-primary-key="' + selectedID + '"]')
+ .addClass(CLASS_SELECTED)
+ .find('td:first')
+ .append(this.SELECT_ONE_SELECTED_ICON);
+ }
+ },
+
+ reloadData: function() {
+ this.initItem();
+ },
+
+ renderSelectOne: function(data) {
+ return Mustache.render($('[name="select-one-selected-template"]').html(), data);
+ },
+
+ handleSelectOne: function($bottomsheets) {
+ var options = {
+ onSelect: this.onSelectResults.bind(this), //render selected item after click item lists
+ onSubmit: this.onSubmitResults.bind(this) //render new items after new item form submitted
+ };
+
+ $bottomsheets.qorSelectCore(options).addClass(CLASS_ONE);
+ this.$bottomsheets = $bottomsheets;
+ this.initItem();
+ },
+
+ onSelectResults: function(data) {
+ this.handleResults(data);
+ },
+
+ onSubmitResults: function(data) {
+ this.handleResults(data, true);
+ },
+
+ handleResults: function(data) {
+ var template,
+ $parent = this.$parent,
+ $select = $parent.find('select'),
+ $selectFeild = $parent.find(CLASS_SELECT_FIELD);
+
+ data.displayName = data.Text || data.Name || data.Title || data.Code || data[Object.keys(data)[0]];
+ data.selectoneValue = data.primaryKey || data.ID;
+
+ data.displayName = (data.displayName).escapeSymbol();
+
+ if (!$select.length) {
+ return;
+ }
+
+ template = this.renderSelectOne(data);
+
+ if ($selectFeild.length) {
+ $selectFeild.remove();
+ }
+
+ $parent.prepend(template);
+ $parent.find(CLASS_SELECT_TRIGGER).hide();
+
+ $select.html(Mustache.render(QorSelectOne.SELECT_ONE_OPTION_TEMPLATE, data));
+ $select[0].value = data.primaryKey || data.ID;
+
+ $parent.trigger('qor.selectone.selected', [data]);
+
+ this.$bottomsheets.qorSelectCore('destroy').remove();
+ if (!$('.qor-bottomsheets').is(':visible')) {
+ $('body').removeClass('qor-bottomsheets-open');
+ }
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorSelectOne.SELECT_ONE_OPTION_TEMPLATE = '
';
+
+ QorSelectOne.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorSelectOne(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.selectone"]';
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorSelectOne.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorSelectOne.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorSelectOne;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-selector.js b/app/views/qor/assets/javascripts/qor/qor-selector.js
new file mode 100644
index 0000000..64d67d5
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-selector.js
@@ -0,0 +1,274 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ var $document = $(document);
+ var NAMESPACE = 'qor.selector';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+ var EVENT_CLICK = 'click.' + NAMESPACE;
+ var EVENT_SELECTOR_CHANGE = 'selectorChanged.' + NAMESPACE;
+ var CLASS_OPEN = 'open';
+ var CLASS_ACTIVE = 'active';
+ var CLASS_HOVER = 'hover';
+ var CLASS_SELECTED = 'selected';
+ var CLASS_DISABLED = 'disabled';
+ var CLASS_CLEARABLE = 'clearable';
+ var SELECTOR_SELECTED = '.' + CLASS_SELECTED;
+ var SELECTOR_TOGGLE = '.qor-selector-toggle';
+ var SELECTOR_LABEL = '.qor-selector-label';
+ var SELECTOR_CLEAR = '.qor-selector-clear';
+ var SELECTOR_MENU = '.qor-selector-menu';
+ var CLASS_BOTTOMSHEETS = '.qor-bottomsheets';
+
+ function QorSelector(element, options) {
+ this.options = options;
+ this.$element = $(element);
+ this.init();
+ }
+
+ QorSelector.prototype = {
+ constructor: QorSelector,
+
+ init: function() {
+ var $this = this.$element;
+
+ this.placeholder = $this.attr('placeholder') || $this.attr('name') || 'Select';
+ this.build();
+ },
+
+ build: function() {
+ var $this = this.$element;
+ var $selector = $(QorSelector.TEMPLATE);
+ var alignedClass = this.options.aligned + '-aligned';
+ var data = {};
+ var eleData = $this.data();
+ var hover = eleData.hover;
+ var paramName = $this.attr('name');
+
+ this.isBottom = eleData.position == 'bottom';
+
+ hover && $selector.addClass(CLASS_HOVER);
+
+ $selector
+ .addClass(alignedClass)
+ .find(SELECTOR_MENU)
+ .html(function() {
+ var list = [];
+
+ $this.children().each(function() {
+ var $this = $(this);
+ var selected = $this.attr('selected');
+ var disabled = $this.attr('disabled');
+ var value = $this.attr('value');
+ var label = $this.text();
+ var classNames = [];
+
+ if (selected) {
+ classNames.push(CLASS_SELECTED);
+ data.value = value;
+ data.label = label;
+ data.paramName = paramName;
+ }
+
+ if (disabled) {
+ classNames.push(CLASS_DISABLED);
+ }
+
+ list.push(
+ '
' +
+ label +
+ ''
+ );
+ });
+
+ return list.join('');
+ });
+
+ this.$selector = $selector;
+ $this.hide().after($selector);
+ $selector.find(SELECTOR_TOGGLE).data('paramName', paramName);
+ this.pick(data, true);
+ this.bind();
+ },
+
+ unbuild: function() {
+ this.unbind();
+ this.$selector.remove();
+ this.$element.show();
+ },
+
+ bind: function() {
+ this.$selector.on(EVENT_CLICK, $.proxy(this.click, this));
+ $document.on(EVENT_CLICK, $.proxy(this.close, this));
+ },
+
+ unbind: function() {
+ this.$selector.off(EVENT_CLICK, this.click);
+ },
+
+ click: function(e) {
+ var $target = $(e.target);
+
+ e.stopPropagation();
+
+ if ($target.is(SELECTOR_CLEAR)) {
+ this.clear();
+ } else if ($target.is('li')) {
+ if (!$target.hasClass(CLASS_SELECTED) && !$target.hasClass(CLASS_DISABLED)) {
+ this.pick($target.data());
+ }
+
+ this.close();
+ } else if ($target.closest(SELECTOR_TOGGLE).length) {
+ this.open();
+ }
+ },
+
+ pick: function(data, initialized) {
+ var $selector = this.$selector;
+ var selected = !!data.value;
+ var $element = this.$element;
+
+ $selector
+ .find(SELECTOR_TOGGLE)
+ .toggleClass(CLASS_ACTIVE, selected)
+ .toggleClass(CLASS_CLEARABLE, selected && this.options.clearable)
+ .find(SELECTOR_LABEL)
+ .text(data.label || this.placeholder);
+
+ if (!initialized) {
+ $selector
+ .find(SELECTOR_MENU)
+ .children('[data-value="' + data.value + '"]')
+ .addClass(CLASS_SELECTED)
+ .siblings(SELECTOR_SELECTED)
+ .removeClass(CLASS_SELECTED);
+
+ $element.val(data.value);
+
+ if ($element.closest(CLASS_BOTTOMSHEETS).length && !$element.closest('[data-toggle="qor.filter"]').length) {
+ // If action is in bottom sheet, will trigger filterChanged.qor.selector event, add passed data.value parameter to event.
+ $(CLASS_BOTTOMSHEETS).trigger(EVENT_SELECTOR_CHANGE, [data.value, data.paramName]);
+ } else {
+ $element.trigger('change');
+ }
+ }
+ },
+
+ clear: function() {
+ var $element = this.$element;
+
+ this.$selector
+ .find(SELECTOR_TOGGLE)
+ .removeClass(CLASS_ACTIVE)
+ .removeClass(CLASS_CLEARABLE)
+ .find(SELECTOR_LABEL)
+ .text(this.placeholder)
+ .end()
+ .end()
+ .find(SELECTOR_MENU)
+ .children(SELECTOR_SELECTED)
+ .removeClass(CLASS_SELECTED);
+
+ $element.val('').trigger('change');
+ },
+
+ open: function() {
+ // Close other opened dropdowns first
+ $document.triggerHandler(EVENT_CLICK);
+ $('.qor-filter__dropdown').hide();
+
+ // Open the current dropdown
+ this.$selector.addClass(CLASS_OPEN);
+ if (this.isBottom) {
+ this.$selector.addClass('bottom');
+ }
+ },
+
+ close: function() {
+ this.$selector.removeClass(CLASS_OPEN);
+ if (this.isBottom) {
+ this.$selector.removeClass('bottom');
+ }
+ },
+
+ destroy: function() {
+ this.unbuild();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorSelector.DEFAULTS = {
+ aligned: 'left',
+ clearable: false
+ };
+
+ QorSelector.TEMPLATE =
+ '
';
+
+ QorSelector.plugin = function(option) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var options;
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(option)) {
+ return;
+ }
+
+ options = $.extend({}, QorSelector.DEFAULTS, $this.data(), typeof option === 'object' && option);
+ $this.data(NAMESPACE, (data = new QorSelector(this, options)));
+ }
+
+ if (typeof option === 'string' && $.isFunction((fn = data[option]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.selector"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorSelector.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorSelector.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorSelector;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-slideout.js b/app/views/qor/assets/javascripts/qor/qor-slideout.js
new file mode 100644
index 0000000..d6c7a14
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-slideout.js
@@ -0,0 +1,689 @@
+(function(factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as anonymous module.
+ define(["jquery"], factory);
+ } else if (typeof exports === "object") {
+ // Node / CommonJS
+ factory(require("jquery"));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ "use strict";
+
+ let $document = $(document),
+ FormData = window.FormData,
+ QOR_Translations = window.QOR_Translations,
+ _ = window._,
+ QOR = window.QOR,
+ NAMESPACE = "qor.slideout",
+ EVENT_KEYUP = "keyup." + NAMESPACE,
+ EVENT_CLICK = "click." + NAMESPACE,
+ EVENT_SUBMIT = "submit." + NAMESPACE,
+ EVENT_SHOW = "show." + NAMESPACE,
+ EVENT_SLIDEOUT_SUBMIT_COMPLEMENT = "slideoutSubmitComplete." + NAMESPACE,
+ EVENT_SLIDEOUT_CLOSED = "slideoutClosed." + NAMESPACE,
+ EVENT_SLIDEOUT_LOADED = "slideoutLoaded." + NAMESPACE,
+ EVENT_SLIDEOUT_BEFORESEND = "slideoutBeforeSend." + NAMESPACE,
+ EVENT_SHOWN = "shown." + NAMESPACE,
+ EVENT_HIDE = "hide." + NAMESPACE,
+ EVENT_HIDDEN = "hidden." + NAMESPACE,
+ EVENT_TRANSITIONEND = "transitionend",
+ CLASS_OPEN = "qor-slideout-open",
+ CLASS_MINI = "qor-slideout-mini",
+ CLASS_IS_SHOWN = "is-shown",
+ CLASS_IS_SLIDED = "is-slided",
+ CLASS_IS_SELECTED = "is-selected",
+ CLASS_MAIN_CONTENT = ".mdl-layout__content.qor-page",
+ CLASS_HEADER_LOCALE = ".qor-actions__locale",
+ CLASS_BODY_LOADING = ".qor-body__loading";
+
+ function replaceHtml(el, html) {
+ let oldEl = typeof el === "string" ? document.getElementById(el) : el,
+ newEl = oldEl.cloneNode(false);
+ newEl.innerHTML = html;
+ oldEl.parentNode.replaceChild(newEl, oldEl);
+ return newEl;
+ }
+
+ function pushArrary($ele, isScript) {
+ let array = [],
+ prop = "href";
+
+ isScript && (prop = "src");
+ $ele.each(function() {
+ array.push($(this).attr(prop));
+ });
+ return _.uniq(array);
+ }
+
+ function execSlideoutEvents(url, response) {
+ // exec qorSliderAfterShow after script loaded
+ var qorSliderAfterShow = $.fn.qorSliderAfterShow;
+ for (var name in qorSliderAfterShow) {
+ if (
+ qorSliderAfterShow.hasOwnProperty(name) &&
+ !qorSliderAfterShow[name]["isLoaded"]
+ ) {
+ qorSliderAfterShow[name]["isLoaded"] = true;
+ qorSliderAfterShow[name].call(this, url, response);
+ }
+ }
+ }
+
+ function loadScripts(srcs, data, callback) {
+ let scriptsLoaded = 0;
+
+ for (let i = 0, len = srcs.length; i < len; i++) {
+ let script = document.createElement("script");
+
+ script.onload = function() {
+ scriptsLoaded++;
+
+ if (scriptsLoaded === srcs.length) {
+ if ($.isFunction(callback)) {
+ callback();
+ }
+ }
+
+ if (data && data.url && data.response) {
+ execSlideoutEvents(data.url, data.response);
+ }
+ };
+
+ script.src = srcs[i];
+ document.body.appendChild(script);
+ }
+ }
+
+ function loadStyles(srcs) {
+ let ss = document.createElement("link"),
+ src = srcs.shift();
+
+ ss.type = "text/css";
+ ss.rel = "stylesheet";
+ ss.onload = function() {
+ if (srcs.length) {
+ loadStyles(srcs);
+ }
+ };
+ ss.href = src;
+ document.getElementsByTagName("head")[0].appendChild(ss);
+ }
+
+ function compareScripts($scripts) {
+ let $currentPageScripts = $("script"),
+ slideoutScripts = pushArrary($scripts, true),
+ currentPageScripts = pushArrary($currentPageScripts, true),
+ scriptDiff = _.difference(slideoutScripts, currentPageScripts);
+ return scriptDiff;
+ }
+
+ function compareLinks($links) {
+ let $currentStyles = $("link"),
+ slideoutStyles = pushArrary($links),
+ currentStyles = pushArrary($currentStyles),
+ styleDiff = _.difference(slideoutStyles, currentStyles);
+
+ return styleDiff;
+ }
+
+ function QorSlideout(element, options) {
+ this.$element = $(element);
+ this.options = $.extend(
+ {},
+ QorSlideout.DEFAULTS,
+ $.isPlainObject(options) && options
+ );
+ this.slided = false;
+ this.disabled = false;
+ this.slideoutType = false;
+ this.init();
+ }
+
+ QorSlideout.prototype = {
+ constructor: QorSlideout,
+
+ init: function() {
+ this.build();
+ this.bind();
+ },
+
+ build: function() {
+ var $slideout;
+
+ this.$slideout = $slideout = $(QorSlideout.TEMPLATE).appendTo("body");
+ this.$slideoutTemplate = $slideout.html();
+ },
+
+ unbuild: function() {
+ this.$slideout.remove();
+ },
+
+ bind: function() {
+ this.$slideout
+ .on(EVENT_SUBMIT, "form", this.submit.bind(this))
+ .on(
+ EVENT_CLICK,
+ ".qor-slideout__fullscreen",
+ this.toggleSlideoutMode.bind(this)
+ )
+ .on(EVENT_CLICK, '[data-dismiss="slideout"]', this.hide.bind(this));
+
+ $document.on(EVENT_KEYUP, $.proxy(this.keyup, this));
+ },
+
+ unbind: function() {
+ this.$slideout.off(EVENT_SUBMIT, this.submit).off(EVENT_CLICK);
+
+ $document.off(EVENT_KEYUP, this.keyup);
+ },
+
+ keyup: function(e) {
+ if (e.which === 27) {
+ if (
+ $(".qor-bottomsheets").is(":visible") ||
+ $(".qor-modal").is(":visible") ||
+ $("#redactor-modal-box").length ||
+ $("#dialog").is(":visible")
+ ) {
+ return;
+ }
+
+ this.hide();
+ this.removeSelectedClass();
+ }
+ },
+
+ loadExtraResource: function(data) {
+ let styleDiff = compareLinks(data.$links),
+ scriptDiff = compareScripts(data.$scripts);
+
+ if (styleDiff.length) {
+ loadStyles(styleDiff);
+ }
+
+ if (scriptDiff.length) {
+ loadScripts(scriptDiff, data);
+ }
+ },
+
+ removeSelectedClass: function() {
+ this.$element.find("[data-url]").removeClass(CLASS_IS_SELECTED);
+ },
+
+ addLoading: function() {
+ $(CLASS_BODY_LOADING).remove();
+ var $loading = $(QorSlideout.TEMPLATE_LOADING);
+ $loading.appendTo($("body")).trigger("enable.qor.material");
+ },
+
+ toggleSlideoutMode: function() {
+ this.$slideout
+ .toggleClass("qor-slideout__fullscreen")
+ .find(".qor-slideout__fullscreen i")
+ .toggle();
+ },
+
+ checkRichedutorHTMLTags: function(source){
+ var DOMHolderArray = new Array();
+ var tagsArray = new Array();
+ var lines = source.value.split('\n');
+ for (var x = 0; x < lines.length; x++) {
+ tagsArray = lines[x].match(/<(\/{1})?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)>/g);
+ if (tagsArray) {
+ for (var i = 0; i < tagsArray.length; i++) {
+ if (tagsArray[i].indexOf('') >= 0) {
+ let elementToPop = tagsArray[i].substr(2, tagsArray[i].length - 3);
+ elementToPop = elementToPop.replace(/ /g, '');
+ for (var j = DOMHolderArray.length - 1; j >= 0; j--) {
+ if (DOMHolderArray[j].element == elementToPop) {
+ DOMHolderArray.splice(j, 1);
+ if (elementToPop != 'html') {
+ break;
+ }
+ }
+ }
+ } else {
+ var tag = new Object();
+ tag.full = tagsArray[i];
+ tag.line = x + 1;
+ if (tag.full.indexOf(' ') > 0) {
+ tag.element = tag.full.substr(1, tag.full.indexOf(' ') - 1);
+ } else {
+ tag.element = tag.full.substr(1, tag.full.length - 2);
+ }
+ var selfClosingTags = new Array('area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr');
+ var isSelfClosing = false;
+ for (var y = 0; y < selfClosingTags.length; y++) {
+ if (selfClosingTags[y].localeCompare(tag.element) == 0) {
+ isSelfClosing = true;
+ }
+ }
+ if (isSelfClosing == false) {
+ DOMHolderArray.push(tag);
+ }
+ }
+
+ }
+ }
+ }
+
+ return DOMHolderArray.length;
+
+ },
+
+ submit: function(e) {
+ let $slideout = this.$slideout,
+ form = e.target,
+ $form = $(form),
+ _this = this,
+ $loading = $(QOR.$formLoading),
+ $submit = $form.find(":submit"),
+ hasNotClosedTags = false;
+
+ if ($form.data("normal-submit")) {
+ return;
+ }
+
+ $slideout.trigger(EVENT_SLIDEOUT_BEFORESEND);
+
+ if (!FormData) {
+ return;
+ }
+ e.preventDefault();
+
+ document.querySelectorAll('.qor-redactor-box .redactor-source').forEach(function(item) {
+ if(_this.checkRichedutorHTMLTags(item)){
+ hasNotClosedTags=true;
+ }
+ });
+
+ if(hasNotClosedTags){
+ QOR.qorConfirm(QOR_Translations.slideoutCheckHTMLTagsError);
+ return false;
+ }
+
+ this.submitXHR = $.ajax($form.prop("action"), {
+ method: $form.prop("method"),
+ data: new FormData(form),
+ dataType: "html",
+ processData: false,
+ contentType: false,
+ beforeSend: function() {
+ $(".qor-submit-loading").remove();
+ $loading
+ .appendTo(
+ $submit.prop("disabled", true).closest(".qor-form__actions")
+ )
+ .trigger("enable.qor.material");
+ $.fn.qorSlideoutBeforeHide = null;
+ },
+ success: function() {
+ let returnUrl = $form.data("returnUrl"),
+ refreshUrl = $form.data("refreshUrl");
+
+ $slideout.trigger(EVENT_SLIDEOUT_SUBMIT_COMPLEMENT);
+
+ if (refreshUrl) {
+ window.location.href = refreshUrl;
+ return;
+ }
+
+ if (returnUrl == "refresh") {
+ _this.refresh();
+ return;
+ }
+
+ if (returnUrl && returnUrl != "refresh") {
+ _this.load(returnUrl);
+ } else {
+ _this.refresh();
+ }
+ },
+ error: function(err) {
+ QOR.handleAjaxError(err);
+ },
+ complete: function() {
+ $submit.prop("disabled", false);
+ }
+ });
+ },
+
+ load: function(url, data) {
+ var options = this.options;
+ var method;
+ var dataType;
+ var load;
+ var $slideout = this.$slideout;
+ var $title;
+
+ if (!url) {
+ return;
+ }
+
+ data = $.isPlainObject(data) ? data : {};
+
+ method = data.method ? data.method : "GET";
+ dataType = data.datatype ? data.datatype : "html";
+
+ load = $.proxy(function() {
+ $.ajax(url, {
+ method: method,
+ dataType: dataType,
+ cache: true,
+ ifModified: true,
+ success: $.proxy(function(response) {
+ let $response,
+ $content,
+ $qorFormContainer,
+ $scripts,
+ $links,
+ bodyClass;
+
+ $(CLASS_BODY_LOADING).remove();
+
+ if (method === "GET") {
+ $response = $(response);
+ $content = $response.find(CLASS_MAIN_CONTENT);
+ $qorFormContainer = $content.find(".qor-form-container");
+ this.slideoutType =
+ $qorFormContainer.length &&
+ $qorFormContainer.data().slideoutType;
+
+ if (!$content.length) {
+ return;
+ }
+
+ let bodyHtml = response.match(
+ /<\s*body.*>[\s\S]*<\s*\/body\s*>/gi
+ );
+ if (bodyHtml) {
+ bodyHtml = bodyHtml
+ .join("")
+ .replace(/<\s*body/gi, "
0) {
+ errors = $(".qor-error span")
+ .map(function() {
+ return $(this).text();
+ })
+ .get()
+ .join(", ");
+ } else {
+ errors = QOR_Translations.serverError;
+ }
+ window.alert(errors);
+ }, this)
+ });
+ }, this);
+
+ if (this.slided) {
+ this.hide(true);
+ this.$slideout.one(EVENT_HIDDEN, load);
+ } else {
+ load();
+ }
+ },
+
+ open: function(options) {
+ this.addLoading();
+ this.load(options.url, options.data);
+ },
+
+ reload: function(url) {
+ this.hide();
+ this.load(url);
+ },
+
+ show: function() {
+ var $slideout = this.$slideout;
+ var showEvent;
+
+ if (this.slided) {
+ return;
+ }
+
+ showEvent = $.Event(EVENT_SHOW);
+ $slideout.trigger(showEvent);
+
+ if (showEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ $slideout.removeClass(CLASS_MINI);
+ this.slideoutType == "mini" && $slideout.addClass(CLASS_MINI);
+
+ $slideout.addClass(CLASS_IS_SHOWN).get(0).offsetWidth;
+ $slideout
+ .one(EVENT_TRANSITIONEND, $.proxy(this.shown, this))
+ .addClass(CLASS_IS_SLIDED)
+ .scrollTop(0);
+ },
+
+ shown: function() {
+ this.slided = true;
+ // Disable to scroll body element
+ $("body").addClass(CLASS_OPEN);
+ this.$slideout
+ .trigger("beforeEnable.qor.slideout")
+ .trigger(EVENT_SHOWN)
+ .trigger("afterEnable.qor.slideout");
+ },
+
+ hide: function() {
+ let message = {
+ confirm: QOR_Translations.slideoutCloseWarning
+ };
+
+ if ($.fn.qorSlideoutBeforeHide) {
+ QOR.qorConfirm(
+ message,
+ function(confirm) {
+ if (confirm) {
+ this.hideSlideout();
+ }
+ }.bind(this)
+ );
+ } else {
+ this.hideSlideout();
+ }
+
+ this.removeSelectedClass();
+ },
+
+ hideSlideout: function() {
+ var $slideout = this.$slideout;
+ var hideEvent;
+ var $datePicker = $(".qor-datepicker").not(".hidden");
+
+ // remove onbeforeunload event
+ window.onbeforeunload = null;
+ $.fn.qorSlideoutBeforeHide = null;
+
+ this.submitXHR && this.submitXHR.abort();
+
+ if ($datePicker.length) {
+ $datePicker.addClass("hidden");
+ }
+
+ if (!this.slided) {
+ return;
+ }
+
+ hideEvent = $.Event(EVENT_HIDE);
+ $slideout.trigger(hideEvent);
+
+ if (hideEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ $slideout
+ .one(EVENT_TRANSITIONEND, $.proxy(this.hidden, this))
+ .removeClass(`${CLASS_IS_SLIDED} qor-slideout__fullscreen`);
+ $slideout.trigger(EVENT_SLIDEOUT_CLOSED);
+ },
+
+ hidden: function() {
+ this.slided = false;
+
+ // Enable to scroll body element
+ $("body").removeClass(CLASS_OPEN);
+
+ this.$slideout.removeClass(CLASS_IS_SHOWN).trigger(EVENT_HIDDEN);
+ },
+
+ refresh: function() {
+ this.hide();
+
+ setTimeout(function() {
+ window.location.reload();
+ }, 350);
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.unbuild();
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorSlideout.DEFAULTS = {
+ title: ".qor-form-title, .mdl-layout-title",
+ content: false
+ };
+
+ QorSlideout.TEMPLATE = `
`;
+
+ QorSlideout.TEMPLATE_LOADING = `
`;
+
+ QorSlideout.plugin = function(options) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorSlideout(this, options)));
+ }
+
+ if (typeof options === "string" && $.isFunction((fn = data[options]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $.fn.qorSlideout = QorSlideout.plugin;
+
+ return QorSlideout;
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-sorter.js b/app/views/qor/assets/javascripts/qor/qor-sorter.js
new file mode 100644
index 0000000..1256b7e
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-sorter.js
@@ -0,0 +1,110 @@
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function ($) {
+
+ 'use strict';
+
+ var location = window.location;
+ var NAMESPACE = 'qor.sorter';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+ var EVENT_CLICK = 'click.' + NAMESPACE;
+ var CLASS_IS_SORTABLE = 'is-sortable';
+
+ function QorSorter(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorSorter.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorSorter.prototype = {
+ constructor: QorSorter,
+
+ init: function () {
+ this.$element.addClass(CLASS_IS_SORTABLE);
+ this.bind();
+ },
+
+ bind: function () {
+ this.$element.on(EVENT_CLICK, '> thead > tr > th', $.proxy(this.sort, this));
+ },
+
+ unbind: function () {
+ this.$element.off(EVENT_CLICK, this.sort);
+ },
+
+ sort: function (e) {
+ var $target = $(e.currentTarget);
+ var orderBy = $target.data('orderBy');
+ var search = location.search;
+ var param = 'order_by=' + orderBy;
+
+ // Stop when it is not sortable
+ if (!orderBy) {
+ return;
+ }
+
+ if (/order_by/.test(search)) {
+ search = search.replace(/order_by(=\w+)?/, function () {
+ return param;
+ });
+ } else {
+ search += search.indexOf('?') > -1 ? ('&' + param) : param;
+ }
+
+ location.search = search;
+ },
+
+ destroy: function () {
+ this.unbind();
+ this.$element.removeClass(CLASS_IS_SORTABLE).removeData(NAMESPACE);
+ }
+ };
+
+ QorSorter.DEFAULTS = {};
+
+ QorSorter.plugin = function (options) {
+ return this.each(function () {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorSorter(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction(fn = data[options])) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function () {
+ var selector = '.qor-js-table';
+
+ $(document)
+ .on(EVENT_DISABLE, function (e) {
+ QorSorter.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function (e) {
+ QorSorter.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorSorter;
+
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-tabs.js b/app/views/qor/assets/javascripts/qor/qor-tabs.js
new file mode 100644
index 0000000..d074652
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-tabs.js
@@ -0,0 +1,210 @@
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function ($) {
+
+ 'use strict';
+
+ var _ = window._;
+ var $body = $('body');
+ var NAMESPACE = 'qor.tabbar';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+ var EVENT_CLICK = 'click.' + NAMESPACE;
+ var CLASS_TAB = '.qor-layout__tab-button';
+ var CLASS_TAB_CONTENT = '.qor-layout__tab-content';
+ var CLASS_TAB_BAR = '.mdl-layout__tab-bar-container';
+ var CLASS_TAB_BAR_RIGHT = '.qor-layout__tab-right';
+ var CLASS_TAB_BAR_LEFT = '.qor-layout__tab-left';
+ var CLASS_ACTIVE = 'is-active';
+
+ function QorTab(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, QorTab.DEFAULTS, $.isPlainObject(options) && options);
+ this.init();
+ }
+
+ QorTab.prototype = {
+ constructor: QorTab,
+
+ init: function () {
+ this.initTab();
+ this.bind();
+ },
+
+ bind: function () {
+ this.$element.on(EVENT_CLICK, CLASS_TAB, this.switchTab.bind(this));
+ this.$element.on(EVENT_CLICK, CLASS_TAB_BAR_RIGHT, this.scrollTabRight.bind(this));
+ this.$element.on(EVENT_CLICK, CLASS_TAB_BAR_LEFT, this.scrollTabLeft.bind(this));
+ },
+
+ unbind: function () {
+ this.$element.off(EVENT_CLICK, CLASS_TAB, this.switchTab);
+ this.$element.off(EVENT_CLICK, CLASS_TAB_BAR_RIGHT, this.scrollTabRight);
+ this.$element.off(EVENT_CLICK, CLASS_TAB_BAR_LEFT, this.scrollTabLeft);
+ },
+
+ initTab: function () {
+ var data = this.$element.data();
+
+ if (!data.scopeActive) {
+ $(CLASS_TAB).first().addClass(CLASS_ACTIVE);
+ $body.data('tabScopeActive',$(CLASS_TAB).first().data('name'));
+ } else {
+ $body.data('tabScopeActive',data.scopeActive);
+ }
+
+ this.tabWidth = 0;
+ this.slideoutWidth = $(CLASS_TAB_CONTENT).outerWidth();
+
+ _.each($(CLASS_TAB), function(ele) {
+ this.tabWidth = this.tabWidth + $(ele).outerWidth();
+ }.bind(this));
+
+ if (this.tabWidth > this.slideoutWidth) {
+ this.$element.find(CLASS_TAB_BAR).append(QorTab.ARROW_RIGHT);
+ }
+
+ },
+
+ scrollTabLeft: function (e) {
+ e.stopPropagation();
+
+ var $scrollBar = $(CLASS_TAB_BAR),
+ scrollLeft = $scrollBar.scrollLeft(),
+ jumpDistance = scrollLeft - this.slideoutWidth;
+
+ if (scrollLeft > 0){
+ $scrollBar.animate({scrollLeft:jumpDistance}, 400, function () {
+
+ $(CLASS_TAB_BAR_RIGHT).show();
+ if ($scrollBar.scrollLeft() == 0) {
+ $(CLASS_TAB_BAR_LEFT).hide();
+ }
+
+ });
+ }
+ },
+
+ scrollTabRight: function (e) {
+ e.stopPropagation();
+
+ var $scrollBar = $(CLASS_TAB_BAR),
+ scrollLeft = $scrollBar.scrollLeft(),
+ tabWidth = this.tabWidth,
+ slideoutWidth = this.slideoutWidth,
+ jumpDistance = scrollLeft + slideoutWidth;
+
+ if (jumpDistance < tabWidth){
+ $scrollBar.animate({scrollLeft:jumpDistance}, 400, function () {
+
+ $(CLASS_TAB_BAR_LEFT).show();
+ if ($scrollBar.scrollLeft() + slideoutWidth >= tabWidth) {
+ $(CLASS_TAB_BAR_RIGHT).hide();
+ }
+
+ });
+
+ !$(CLASS_TAB_BAR_LEFT).length && this.$element.find(CLASS_TAB_BAR).prepend(QorTab.ARROW_LEFT);
+ }
+ },
+
+ switchTab: function (e) {
+ var $target = $(e.target),
+ $element = this.$element,
+ data = $target.data(),
+ tabScopeActive = $body.data().tabScopeActive,
+ isInSlideout = $('.qor-slideout').is(':visible');
+
+ if (!isInSlideout) {
+ return;
+ }
+
+ if ($target.hasClass(CLASS_ACTIVE)){
+ return false;
+ }
+
+ $element.find(CLASS_TAB).removeClass(CLASS_ACTIVE);
+ $target.addClass(CLASS_ACTIVE);
+
+ $.ajax(data.tabUrl, {
+ method: 'GET',
+ dataType: 'html',
+ processData: false,
+ contentType: false,
+ beforeSend: function () {
+ $('.qor-layout__tab-spinner').remove();
+ var $spinner = '
';
+ $(CLASS_TAB_CONTENT).hide().before($spinner);
+ window.componentHandler.upgradeElement($('.qor-layout__tab-spinner')[0]);
+ },
+ success: function (html) {
+ $('.qor-layout__tab-spinner').remove();
+ $body.data('tabScopeActive',$target.data('name'));
+ var $content = $(html).find(CLASS_TAB_CONTENT).html();
+ $(CLASS_TAB_CONTENT).show().html($content).trigger('enable');
+
+ },
+ error: function () {
+ $('.qor-layout__tab-spinner').remove();
+ $body.data('tabScopeActive',tabScopeActive);
+ }
+ });
+ return false;
+ },
+
+ destroy: function () {
+ this.unbind();
+ $body.removeData('tabScopeActive');
+ }
+ };
+
+ QorTab.ARROW_RIGHT = '
';
+ QorTab.ARROW_LEFT = '
';
+
+ QorTab.DEFAULTS = {};
+
+ QorTab.plugin = function (options) {
+ return this.each(function () {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
+
+ if (!data) {
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new QorTab(this, options)));
+ }
+
+ if (typeof options === 'string' && $.isFunction(fn = data[options])) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function () {
+ var selector = '[data-toggle="qor.tab"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function (e) {
+ QorTab.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function (e) {
+ QorTab.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorTab;
+
+});
diff --git a/app/views/qor/assets/javascripts/qor/qor-timepicker.js b/app/views/qor/assets/javascripts/qor/qor-timepicker.js
new file mode 100644
index 0000000..c8b7f2f
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor/qor-timepicker.js
@@ -0,0 +1,262 @@
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node / CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+})(function($) {
+ 'use strict';
+
+ var NAMESPACE = 'qor.timepicker';
+ var EVENT_ENABLE = 'enable.' + NAMESPACE;
+ var EVENT_DISABLE = 'disable.' + NAMESPACE;
+ var EVENT_CLICK = 'click.' + NAMESPACE;
+ var EVENT_FOCUS = 'focus.' + NAMESPACE;
+ var EVENT_KEYDOWN = 'keydown.' + NAMESPACE;
+ var EVENT_BLUR = 'blur.' + NAMESPACE;
+ var EVENT_CHANGE_TIME = 'selectTime.' + NAMESPACE;
+
+ var CLASS_PARENT = '[data-picker-type]';
+ var CLASS_TIME_SELECTED = '.ui-timepicker-selected';
+
+ function QorTimepicker(element, options) {
+ this.$element = $(element);
+ this.options = $.extend(true, {}, QorTimepicker.DEFAULTS, $.isPlainObject(options) && options);
+ this.formatDate = null;
+ this.pickerData = this.$element.data();
+ this.parent = this.$element.closest(CLASS_PARENT);
+ this.isDateTimePicker = this.parent.data('picker-type') == 'datetime';
+ this.$targetInput = this.parent.find(this.pickerData.targetInput || (this.isDateTimePicker ? '.qor-datetimepicker__input' : '.qor-datepicker__input'));
+ this.init();
+ }
+
+ QorTimepicker.prototype = {
+ init: function() {
+ if (this.$targetInput.is(':disabled')) {
+ this.$element.remove();
+ return;
+ }
+ this.bind();
+ this.oldValue = this.$targetInput.val();
+
+ var dateNow = new Date();
+ var month = dateNow.getMonth() + 1;
+ var date = dateNow.getDate();
+
+ month = month < 8 ? '0' + month : month;
+ date = date < 10 ? '0' + date : date;
+
+ this.dateValueNow = dateNow.getFullYear() + '-' + month + '-' + date;
+ },
+
+ bind: function() {
+ var pickerOptions = {
+ timeFormat: 'H:i',
+ showOn: null,
+ wrapHours: false,
+ scrollDefault: 'now'
+ };
+
+ if (this.isDateTimePicker) {
+ this.$targetInput
+ .qorTimepicker(pickerOptions)
+ .on(EVENT_CHANGE_TIME, $.proxy(this.changeTime, this))
+ .on(EVENT_BLUR, $.proxy(this.blur, this))
+ .on(EVENT_FOCUS, $.proxy(this.focus, this))
+ .on(EVENT_KEYDOWN, $.proxy(this.keydown, this));
+ }
+
+ this.$element.on(EVENT_CLICK, $.proxy(this.show, this));
+ },
+
+ unbind: function() {
+ this.$element.off(EVENT_CLICK, this.show);
+
+ if (this.isDateTimePicker) {
+ this.$targetInput
+ .off(EVENT_CHANGE_TIME, this.changeTime)
+ .off(EVENT_BLUR, this.blur)
+ .off(EVENT_FOCUS, this.focus)
+ .off(EVENT_KEYDOWN, this.keydown);
+ }
+ },
+
+ focus: function() {},
+
+ blur: function() {
+ var inputValue = this.$targetInput.val();
+ var inputArr = inputValue.split(' ');
+ var inputArrLen = inputArr.length;
+
+ var tempValue;
+ var newDateValue;
+ var newTimeValue;
+ var isDate;
+ var isTime;
+ var splitSym;
+
+ var timeReg = /\d{1,2}:\d{1,2}/;
+ var dateReg = /^\d{4}-\d{1,2}-\d{1,2}/;
+
+ if (!inputValue) {
+ return;
+ }
+
+ if (inputArrLen == 1) {
+ if (dateReg.test(inputArr[0])) {
+ newDateValue = inputArr[0];
+ newTimeValue = '00:00';
+ }
+
+ if (timeReg.test(inputArr[0])) {
+ newDateValue = this.dateValueNow;
+ newTimeValue = inputArr[0];
+ }
+ } else {
+ for (var i = 0; i < inputArrLen; i++) {
+ // check for date && time
+ isDate = dateReg.test(inputArr[i]);
+ isTime = timeReg.test(inputArr[i]);
+
+ if (isDate) {
+ newDateValue = inputArr[i];
+ splitSym = '-';
+ }
+
+ if (isTime) {
+ newTimeValue = inputArr[i];
+ splitSym = ':';
+ }
+
+ tempValue = inputArr[i].split(splitSym);
+
+ for (var j = 0; j < tempValue.length; j++) {
+ if (tempValue[j].length < 2) {
+ tempValue[j] = '0' + tempValue[j];
+ }
+ }
+
+ if (isDate) {
+ newDateValue = tempValue.join(splitSym);
+ }
+
+ if (isTime) {
+ newTimeValue = tempValue.join(splitSym);
+ }
+ }
+ }
+
+ if (this.checkDate(newDateValue) && this.checkTime(newTimeValue)) {
+ this.$targetInput.val(newDateValue + ' ' + newTimeValue);
+ this.oldValue = this.$targetInput.val();
+ } else {
+ this.$targetInput.val(this.oldValue);
+ }
+ },
+
+ keydown: function(e) {
+ var keycode = e.keyCode;
+ var keys = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 8, 37, 38, 39, 40, 27, 32, 20, 189, 16, 186, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105];
+ if (keys.indexOf(keycode) == -1) {
+ e.preventDefault();
+ }
+ },
+
+ checkDate: function(value) {
+ var regCheckDate = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{1,2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;
+ return regCheckDate.test(value);
+ },
+
+ checkTime: function(value) {
+ var regCheckTime = /^([01]\d|2[0-3]):?([0-5]\d)$/;
+ return regCheckTime.test(value);
+ },
+
+ changeTime: function() {
+ var $targetInput = this.$targetInput;
+
+ var oldValue = this.oldValue;
+ var timeReg = /\d{1,2}:\d{1,2}/;
+ var hasTime = timeReg.test(oldValue);
+ var selectedTime = $targetInput
+ .data()
+ .timepickerObj.list.find(CLASS_TIME_SELECTED)
+ .html();
+ var newValue;
+
+ if (!oldValue) {
+ newValue = this.dateValueNow + ' ' + selectedTime;
+ } else if (hasTime) {
+ newValue = oldValue.replace(timeReg, selectedTime);
+ } else {
+ newValue = oldValue + ' ' + selectedTime;
+ }
+
+ $targetInput.val(newValue);
+ $targetInput.trigger('change');
+ },
+
+ show: function() {
+ if (!this.isDateTimePicker) {
+ return;
+ }
+
+ this.$targetInput.qorTimepicker('show');
+ this.oldValue = this.$targetInput.val();
+ },
+
+ destroy: function() {
+ this.unbind();
+ this.$targetInput.qorTimepicker('remove');
+ this.$element.removeData(NAMESPACE);
+ }
+ };
+
+ QorTimepicker.DEFAULTS = {};
+
+ QorTimepicker.plugin = function(option) {
+ return this.each(function() {
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var options;
+ var fn;
+
+ if (!data) {
+ if (!$.fn.qorDatepicker) {
+ return;
+ }
+
+ if (/destroy/.test(option)) {
+ return;
+ }
+
+ options = $.extend(true, {}, $this.data(), typeof option === 'object' && option);
+ $this.data(NAMESPACE, (data = new QorTimepicker(this, options)));
+ }
+
+ if (typeof option === 'string' && $.isFunction((fn = data[option]))) {
+ fn.apply(data);
+ }
+ });
+ };
+
+ $(function() {
+ var selector = '[data-toggle="qor.timepicker"]';
+
+ $(document)
+ .on(EVENT_DISABLE, function(e) {
+ QorTimepicker.plugin.call($(selector, e.target), 'destroy');
+ })
+ .on(EVENT_ENABLE, function(e) {
+ QorTimepicker.plugin.call($(selector, e.target));
+ })
+ .triggerHandler(EVENT_ENABLE);
+ });
+
+ return QorTimepicker;
+});
diff --git a/app/views/qor/assets/javascripts/qor_admin_default.js b/app/views/qor/assets/javascripts/qor_admin_default.js
new file mode 100644
index 0000000..c74d4cf
--- /dev/null
+++ b/app/views/qor/assets/javascripts/qor_admin_default.js
@@ -0,0 +1,2 @@
+"use strict";function getSelect2Header(){var t=$("body").data().selectAjaxHeader,e=window.getSelect2HeaderFunction,i={};return t&&e&&$.isFunction(e)?(i[t]=e(),i):{}}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}$.fn.qorSliderAfterShow=$.fn.qorSliderAfterShow||{},window.QOR={$formLoading:'
'},String.prototype.escapeSymbol=function(){var e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return this.replace(/[&<>"']/g,function(t){return e[t]||t})},window.Mustache&&(window.Mustache.tags=["[[","]]"]),$(document).ajaxComplete(function(t,e,i){"POST"!=i.type&&"PUT"!=i.type||$.fn.qorSlideoutBeforeHide&&($.fn.qorSlideoutBeforeHide=null,window.onbeforeunload=null)}),$.fn.select2.ajaxCommonOptions=function(t){var i=t.remoteDataPrimaryKey;return{dataType:"json",headers:getSelect2Header(t),cache:!0,delay:250,data:function(t){return{keyword:t.term,page:t.page,per_page:20}},processResults:function(t,e){e.page=e.page||1;t=$.map(t,function(t){return t.id=t[i]||t.primaryKey||t.Id||t.ID,t});return{results:t,pagination:{more:20<=t.length}}}}},$.fn.select2.ajaxFormatResult=function(t,e,i){var n="";if(t.loading)return t.text;if(console.log("select2.ajaxFormatResult: Data"),console.log(t),console.log("select2.ajaxFormatResult: has remote image"),console.log(i),i){var o=t.text||t.Name||t.Title||t.Code||t[Object.keys(t)[0]],i=t.Image,n=i?'
'+o+"":'
'+o+"
";return $(n)}return n=0
|<\/.+>)/.test(n)?$(n):n},$(function(){var r=window._,o=window.QOR,s=window.QOR_Translations,t='
\n
\n
\n
\n
\n \n \n
\n
\n
"),a=$(t).appendTo("body");$(document).on("keyup.qor.confirm",function(t){a.is(":visible")&&(27===t.which&&setTimeout(function(){a.hide(),o.qorConfirmCallback=void 0},100),13===t.which&&setTimeout(function(){$('.dialog-button[data-type="confirm"]').click()},100))}).on("click.qor.confirm",".dialog-button",function(){var t=$(this).data("type"),e=o.qorConfirmCallback;return $.isFunction(e)&&e(t),a.hide(),o.qorConfirmCallback=void 0,!1}),o.qorConfirm=function(t,e){var i=a.find(".dialog-ok"),n=a.find(".dialog-cancel");return r.isString(t)?(a.find(".dialog-message").text(t),i.text(s.okButton),n.text(s.cancelButton)):r.isObject(t)&&(t.confirmOk&&t.confirmCancel?(i.text(t.confirmOk),n.text(t.confirmCancel)):(i.text(s.okButton),n.text(s.cancelButton)),t.icon&&a.find("i.material-icons").addClass(t.icon).html(t.icon),a.find(".dialog-message").text(t.confirm)),a.show(),o.qorConfirmCallback=e,!1};function l(t,e){var i,n,o=e||new FormData;for(n in t)t.hasOwnProperty(n)&&t[n]&&(i=n),t[n]instanceof Date?o.append(i,t[n].toISOString()):"object"!==_typeof(t[n])||t[n]instanceof File?o.append(i,t[n]):l(t[n],o);return o}o.qorAjaxHandleFile=function(t,i,n,e){var o=new XMLHttpRequest;o.responseType="arraybuffer",o.open("POST",t,!0),o.onload=function(){var t,e;200===this.status?(e=new Blob([this.response],{type:i}),t=window.URL.createObjectURL(e),e=document.createElement("a"),document.body.appendChild(e),e.href=t,e.download=n||"download-"+$.now(),e.click()):window.alert(s.serverError)},r.isObject(e)&&("[object FormData]"!=Object.prototype.toString.call(e)&&(e=l(e)),o.send(e))};t=function(){var t=$(".qor-linkify-object"),e=/https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/gi;t.length&&t.each(function(){var t=$(this).data("video-link");t.match(e)&&$(this).html('
'))})};($.fn.qorSliderAfterShow.converVideoLinks=t)(),o.handleAjaxError=function(t){var e=$("body"),i=t.responseJSON,n=t.responseText,o=$('
');if(e.find(".qor-alert").remove(),422===t.status)if(i){var r=i.errors,s="";if($.isArray(r))for(var a=0;a
\n error\n '.concat(r[a],"\n ");else s='\n error\n '.concat(r,"\n ");o.append(s)}else o=$(n).find(".qor-error");else o.append('\n error\n '.concat(t.statusText,"\n "));o.prependTo(e),setTimeout(function(){o.addClass("qor-alert__active")},50),setTimeout(function(){$('.qor-alert[data-dismissible="true"]').removeClass("qor-alert__active"),$("#qor-submit-loading").remove()},6e3)}}),function(t){"function"==typeof define&&define.amd?define("datepicker",["jquery"],t):"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?t(require("jquery")):t(jQuery)}(function(C){var t=C(window),o=window.document,h=C(o),r=window.Number,a="datepicker",i="click."+a,n="keyup."+a,s="focus."+a,e="resize."+a,l="show."+a,d="hide."+a,c="pick."+a,u=/(y|m|d)+/g,f=/\d+/g,p=/^\d{2,4}$/,m=a+"-top-left",y=a+"-bottom-left",g=[m,a+"-top-right",y,a+"-bottom-right"].join(" "),b=a+"-hide",v=Math.min,_=Object.prototype.toString;function q(t){return"string"==typeof t}function w(t){return"number"==typeof t&&!isNaN(t)}function S(t){return void 0===t}function $(t){return"date"===(t=t,_.call(t).slice(8,-1).toLowerCase())}function k(t,e){var i=[];return Array.from?Array.from(t).slice(e||0):(w(e)&&i.push(e),i.slice.apply(t,i))}function x(t,e){var i=k(arguments,2);return function(){return t.apply(e,i.concat(k(arguments)))}}function T(t,e){return[31,(t=t)%4==0&&t%100!=0||t%400==0?29:28,31,30,31,30,31,31,30,31,30,31][e]}function D(t,e){(e=C.isPlainObject(e)?e:{}).language&&(e=C.extend({},D.LANGUAGES[e.language],e)),this.$element=C(t),this.options=C.extend({},D.DEFAULTS,e),this.isBuilt=!1,this.isShown=!1,this.isInput=!1,this.isInline=!1,this.initialValue="",this.initialDate=null,this.startDate=null,this.endDate=null,this.init()}D.prototype={constructor:D,init:function(){var t=this.options,e=this.$element,i=t.startDate,n=t.endDate,o=t.date;this.$trigger=C(t.trigger||e),this.isInput=e.is("input")||e.is("textarea"),this.isInline=t.inline&&(t.container||!this.isInput),this.format=function(t){var e,i,n=String(t).toLowerCase(),o=n.match(u);if(!o||0===o.length)throw new Error("Invalid date format.");for(t={source:n,parts:o},e=o.length,i=0;in.getTime()&&(o=new Date(n)),this.endDate=n),this.date=o,this.viewDate=new Date(o),this.initialDate=new Date(this.date),this.bind(),(t.autoshow||this.isInline)&&this.show(),t.autopick&&this.pick()},build:function(){var t,e=this.options,i=this.$element;this.isBuilt||(this.isBuilt=!0,this.$picker=t=C(e.template),this.$week=t.find('[data-view="week"]'),this.$yearsPicker=t.find('[data-view="years picker"]'),this.$yearsPrev=t.find('[data-view="years prev"]'),this.$yearsNext=t.find('[data-view="years next"]'),this.$yearsCurrent=t.find('[data-view="years current"]'),this.$years=t.find('[data-view="years"]'),this.$monthsPicker=t.find('[data-view="months picker"]'),this.$yearPrev=t.find('[data-view="year prev"]'),this.$yearNext=t.find('[data-view="year next"]'),this.$yearCurrent=t.find('[data-view="year current"]'),this.$months=t.find('[data-view="months"]'),this.$daysPicker=t.find('[data-view="days picker"]'),this.$monthPrev=t.find('[data-view="month prev"]'),this.$monthNext=t.find('[data-view="month next"]'),this.$monthCurrent=t.find('[data-view="month current"]'),this.$days=t.find('[data-view="days"]'),this.isInline?C(e.container||i).append(t.addClass("datepicker-inline")):(C(o.body).append(t.addClass("datepicker-dropdown")),t.addClass(b)),this.fillWeek())},unbuild:function(){this.isBuilt&&(this.isBuilt=!1,this.$picker.remove())},bind:function(){var t=this.options,e=this.$element;C.isFunction(t.show)&&e.on(l,t.show),C.isFunction(t.hide)&&e.on(d,t.hide),C.isFunction(t.pick)&&e.on(c,t.pick),this.isInput&&(e.on(n,C.proxy(this.keyup,this)),t.trigger||e.on(s,C.proxy(this.show,this))),this.$trigger.on(i,C.proxy(this.show,this))},unbind:function(){var t=this.options,e=this.$element;C.isFunction(t.show)&&e.off(l,t.show),C.isFunction(t.hide)&&e.off(d,t.hide),C.isFunction(t.pick)&&e.off(c,t.pick),this.isInput&&(e.off(n,this.keyup),t.trigger||e.off(s,this.show)),this.$trigger.off(i,this.show)},showView:function(t){var e=this.$yearsPicker,i=this.$monthsPicker,n=this.$daysPicker,o=this.format;if(o.hasYear||o.hasMonth||o.hasDay)switch(r(t)){case 2:case"years":i.addClass(b),n.addClass(b),o.hasYear?(this.fillYears(),e.removeClass(b)):this.showView(0);break;case 1:case"months":e.addClass(b),n.addClass(b),o.hasMonth?(this.fillMonths(),i.removeClass(b)):this.showView(2);break;default:e.addClass(b),i.addClass(b),o.hasDay?(this.fillDays(),n.removeClass(b)):this.showView(1)}},hideView:function(){this.options.autohide&&this.hide()},place:function(){var t=this.options,e=this.$element,i=this.$picker,n=h.outerWidth(),o=h.outerHeight(),r=e.outerWidth(),s=e.outerHeight(),a=i.width(),l=i.height(),d=e.offset(),c=d.left,u=d.top,e=parseFloat(t.offset)||10,d=m;l"+n.text+""+i+">"},fillAll:function(){this.fillYears(),this.fillMonths(),this.fillDays()},fillWeek:function(){for(var t=this.options,e=parseInt(t.weekStart,10)%7,i=t.daysMin,n="",i=C.merge(i.slice(e),i.slice(0,e)),o=0;o<=6;o++)n+=this.createItem({text:i[o]});this.$week.html(n)},fillYears:function(){for(var t,e,i=this.options,n=i.disabledClass||"",o=i.yearSuffix||"",r=C.isFunction(i.filter)&&i.filter,s=this.startDate,a=this.endDate,i=this.viewDate,l=i.getFullYear(),d=i.getMonth(),c=i.getDate(),u=this.date,h=u.getFullYear(),f=!1,p=!1,m=!1,y="",g=-5;g<=6;g++)u=new Date(l+g,d,c),e=-5===g||6===g,t=l+g===h,m=!1,s&&(m=u.getFullYear()a.getFullYear(),6===g&&(p=m)),!m&&r&&(m=!1===r.call(this.$element,u)),y+=this.createItem({text:l+g,view:m?"year disabled":t?"year picked":"year",muted:e,picked:t,disabled:m});this.$yearsPrev.toggleClass(n,f),this.$yearsNext.toggleClass(n,p),this.$yearsCurrent.toggleClass(n,!0).html(l+-5+o+" - "+(l+6)+o),this.$years.html(y)},fillMonths:function(){for(var t,e=this.options,i=e.disabledClass||"",n=e.monthsShort,o=C.isFunction(e.filter)&&e.filter,r=this.startDate,s=this.endDate,a=this.viewDate,l=a.getFullYear(),d=a.getDate(),c=this.date,u=c.getFullYear(),h=c.getMonth(),f=!1,p=!1,m=!1,y="",g=0;g<=11;g++)c=new Date(l,g,d),t=l===u&&g===h,m=!1,r&&(m=(f=c.getFullYear()===r.getFullYear())&&c.getMonth()s.getMonth()),!m&&o&&(m=!1===o.call(this.$element,c)),y+=this.createItem({index:g,text:n[g],view:m?"month disabled":t?"month picked":"month",picked:t,disabled:m});this.$yearPrev.toggleClass(i,f),this.$yearNext.toggleClass(i,p),this.$yearCurrent.toggleClass(i,f&&p).html(l+e.yearSuffix||""),this.$months.html(y)},fillDays:function(){var t,e,i,n,o=this.options,r=o.disabledClass||"",s=o.yearSuffix||"",a=o.monthsShort,l=parseInt(o.weekStart,10)%7,d=C.isFunction(o.filter)&&o.filter,c=this.startDate,u=this.endDate,h=this.viewDate,f=h.getFullYear(),p=h.getMonth(),m=f,y=p,g=f,b=p,v=this.date,_=v.getFullYear(),q=v.getMonth(),w=v.getDate(),S=!1,h=!1,$=!1,k=[],x=[],D=[];for(0===p?(--m,y=11):--y,e=T(m,y),(n=(v=new Date(f,p,1)).getDay()-l)<=0&&(n+=7),c&&(S=v.getTime()<=c.getTime()),i=e-(n-1);i<=e;i++)v=new Date(m,y,i),$=!1,c&&($=v.getTime()=u.getTime()),i=1;i<=n;i++)v=new Date(g,b,i),$=!1,u&&($=v.getTime()>u.getTime()),!$&&d&&($=!1===d.call(this.$element,v)),x.push(this.createItem({text:i,view:"day next",muted:!0,disabled:$}));for(i=1;i<=e;i++)v=new Date(f,p,i),t=f===_&&p===q&&i===w,$=!1,c&&($=v.getTime()u.getTime()),!$&&d&&($=!1===d.call(this.$element,v)),D.push(this.createItem({text:i,view:$?"day disabled":t?"day picked":"day",picked:t,disabled:$}));this.$monthPrev.toggleClass(r,S),this.$monthNext.toggleClass(r,h),this.$monthCurrent.toggleClass(r,S&&h).html(o.yearFirst?f+s+" "+a[p]:a[p]+" "+f+s),this.$days.html(k.join("")+D.join(" ")+x.join(""))},click:function(t){var e,i,n,o,r,s,a=C(t.target),l=this.viewDate;if(t.stopPropagation(),t.preventDefault(),!a.hasClass("disabled"))switch(e=l.getFullYear(),i=l.getMonth(),n=l.getDate(),s=a.data("view")){case"years prev":case"years next":e="years prev"===s?e-10:e+10,r=a.text(),(o=p.test(r))&&(e=parseInt(r,10),this.date=new Date(e,i,v(n,28))),this.viewDate=new Date(e,i,v(n,28)),this.fillYears(),o&&(this.showView(1),this.pick("year"));break;case"year prev":case"year next":e="year prev"===s?e-1:e+1,this.viewDate=new Date(e,i,v(n,28)),this.fillMonths();break;case"year current":this.format.hasYear&&this.showView(2);break;case"year picked":this.format.hasMonth?this.showView(1):this.hideView();break;case"year":e=parseInt(a.text(),10),this.date=new Date(e,i,v(n,28)),this.viewDate=new Date(e,i,v(n,28)),this.format.hasMonth?this.showView(1):this.hideView(),this.pick("year");break;case"month prev":case"month next":i="month prev"===s?i-1:"month next"===s?i+1:i,this.viewDate=new Date(e,i,v(n,28)),this.fillDays();break;case"month current":this.format.hasMonth&&this.showView(1);break;case"month picked":this.format.hasDay?this.showView(0):this.hideView();break;case"month":i=C.inArray(a.text(),this.options.monthsShort),this.date=new Date(e,i,v(n,28)),this.viewDate=new Date(e,i,v(n,28)),this.format.hasDay?this.showView(0):this.hideView(),this.pick("month");break;case"day prev":case"day next":case"day":i="day prev"===s?i-1:"day next"===s?i+1:i,n=parseInt(a.text(),10),this.date=new Date(e,i,n),this.viewDate=new Date(e,i,n),this.fillDays(),"day"===s&&this.hideView(),this.pick("day");break;case"day picked":this.hideView(),this.pick("day")}},clickDoc:function(t){for(var e,i=t.target,n=this.$trigger[0];i!==o;){if(i===n){e=!0;break}i=i.parentNode}e||this.hide()},keyup:function(){this.update()},getValue:function(){var t=this.$element,e="";return this.isInput?e=t.val():this.isInline&&!this.options.container||(e=t.text()),e},setValue:function(t){var e=this.$element;t=q(t)?t:"",this.isInput?e.val(t):this.isInline&&!this.options.container||e.text(t)},show:function(){this.isBuilt||this.build(),this.isShown||this.trigger(l).isDefaultPrevented()||(this.isShown=!0,this.$picker.removeClass(b).on(i,C.proxy(this.click,this)),this.showView(this.options.startView),this.isInline||(t.on(e,this._place=x(this.place,this)),h.on(i,this._clickDoc=x(this.clickDoc,this)),this.place()))},hide:function(){this.isShown&&(this.trigger(d).isDefaultPrevented()||(this.isShown=!1,this.$picker.addClass(b).off(i,this.click),this.isInline||(t.off(e,this._place),h.off(i,this._clickDoc))))},update:function(){this.setDate(this.getValue(),!0)},pick:function(t){var e=this.$element,i=this.date;this.trigger(c,{view:t||"",date:i}).isDefaultPrevented()||(this.setValue(this.formatDate(this.date)),this.isInput&&e.trigger("change"))},reset:function(){this.setDate(this.initialDate,!0),this.setValue(this.initialValue),this.isShown&&this.showView(this.options.startView)},getMonthName:function(t,e){var i=this.options,n=i.months;return C.isNumeric(t)?t=r(t):S(e)&&(e=t),!0===e&&(n=i.monthsShort),n[w(t)?t:this.date.getMonth()]},getDayName:function(t,e,i){var n=this.options,o=n.days;return C.isNumeric(t)?t=r(t):(S(i)&&(i=e),S(e)&&(e=t)),(o=!0===i?n.daysMin:!0===e?n.daysShort:o)[w(t)?t:this.date.getDay()]},getDate:function(t){var e=this.date;return t?this.formatDate(e):new Date(e)},setDate:function(t,e){var i=this.options.filter;($(t)||q(t))&&(t=this.parseDate(t),C.isFunction(i)&&!1===i.call(this.$element,t)||(this.date=t,this.viewDate=new Date(t),e||this.pick(),this.isBuilt&&this.fillAll()))},setStartDate:function(t){($(t)||q(t))&&(this.startDate=this.parseDate(t),this.isBuilt&&this.fillAll())},setEndDate:function(t){($(t)||q(t))&&(this.endDate=this.parseDate(t),this.isBuilt&&this.fillAll())},parseDate:function(t){var e,i,n,o,r,s,a=this.format,l=[];if($(t))return new Date(t.getFullYear(),t.getMonth(),t.getDate());if(q(t)&&(l=t.match(f)||[]),i=(t=new Date).getFullYear(),n=t.getDate(),o=t.getMonth(),e=a.parts.length,l.length===e)for(s=0;s',offset:10,zIndex:1e3,filter:null,show:null,hide:null,pick:null},D.setDefaults=function(t){C.extend(D.DEFAULTS,C.isPlainObject(t)&&t)},D.other=C.fn.qorDatepicker,C.fn.qorDatepicker=function(o){var r,s=k(arguments,1);return this.each(function(){var t,e,i=C(this),n=i.data(a);if(!n){if(/destroy/.test(o))return;t=C.extend({},i.data(),C.isPlainObject(o)&&o),i.data(a,n=new D(this,t))}q(o)&&C.isFunction(e=n[o])&&(r=e.apply(n,s))}),S(r)?this:r},C.fn.qorDatepicker.Constructor=D,C.fn.qorDatepicker.languages=D.LANGUAGES,C.fn.qorDatepicker.setDefaults=D.setDefaults,C.fn.qorDatepicker.noConflict=function(){return C.fn.qorDatepicker=D.other,this}}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?t(require("jquery")):t(jQuery)}(function(h){var i=window.Mustache,f=window.QOR,o="qor.action",t="enable."+o,n="click."+o,r='[data-ajax-form="true"][data-method]',e=".qor-action-bulk-buttons",s=".qor-page .qor-table-container",a=".qor-table--bulking",l=".qor-table--bulking tbody tr",p="is_undo",d="mdl-data-table--selectable",c="primary_values[]",m=".qor-body__loading";function u(t,e){this.$element=h(t),this.options=h.extend({},u.DEFAULTS,h.isPlainObject(e)&&e),this.ajaxForm={},this.init()}return u.prototype={constructor:u,init:function(){this.bind(),this.initActions()},bind:function(){this.$element.on(n,".qor-action--bulk",this.renderBulkTable.bind(this)).on(n,".qor-action--exit-bulk",this.removeBulkTable.bind(this)),h(document).on(n,l,this.handleBulkTableClick.bind(this)).on(n,r,this.clickAjaxButton.bind(this))},unbind:function(){this.$element.off(n),h(document).off(n,l,this.handleBulkTableClick).off(n,r,this.clickAjaxButton)},initActions:function(){h(s).find("table").length||(h(e).hide(),h(".qor-page__header a.qor-action--button").hide())},collectFormData:function(){var e,t=h(a).find(".mdl-checkbox__input:checked"),i=[],n=[];return t.length&&t.each(function(){var t=h(this).closest("tr").data("primary-key");e={},t&&(i.push({name:c,value:t.toString()}),e[c]=t.toString(),n.push(e))}),this.ajaxForm.formData=i,this.ajaxForm.normalFormData=n,this.ajaxForm},actionSubmit:function(t){return this.submit(t),!1},handleBulkTableClick:function(t){var e=h(t.target).closest("tr"),i=e.find("td").first(),t=i.find(".mdl-js-checkbox");return t.toggleClass("is-checked"),e.toggleClass("is-selected"),i.find("input").prop("checked",t.hasClass("is-checked")),!1},adjustPageBodyStyle:function(t){var e=h(".qor-page > .qor-page__header"),i=h(".qor-page > .qor-page__body"),n=e.find(".qor-page-subnav__header").length?96:48;t?e.height()>n&&i.css("padding-top",e.height()):parseInt(i.css("padding-top"))>n&&i.css("padding-top","")},renderBulkTable:function(){var t=h("body");t.hasClass("qor-slideout-open")&&t.data("qor.slideout").hide(),h(".qor-table__inner-list").remove(),this.toggleBulkButtons(),this.enableTableMDL(),this.adjustPageBodyStyle(!0)},removeBulkTable:function(){this.toggleBulkButtons(),this.disableTableMDL(),this.adjustPageBodyStyle()},enableTableMDL:function(){h(s).find("table").removeAttr("data-upgraded").addClass(d).trigger("enable")},disableTableMDL:function(){h(s).find("table").removeClass(d).find("tr").removeClass("is-selected").find("td:first,th:first").remove()},toggleBulkButtons:function(){this.$element.find(".qor-action-forms").toggle(),h(e).find("button").toggleClass("hidden"),h(s).toggleClass("qor-table--bulking").find(".qor-table__actions").toggle(),h(".qor-page__header .qor-actions, .qor-page__header .qor-search-container").toggle()},clickAjaxButton:function(t){t=h(t.target);return this.collectFormData(),this.ajaxForm.properties=t.data(),this.submit(t),!1},renderFlashMessage:function(t){var e=u.FLASHMESSAGETMPL;return i.parse(e),i.render(e,t)},addLoading:function(){h(m).remove(),h(u.TEMPLATE_LOADING).appendTo(h("body")).trigger("enable.qor.material")},submit:function(e){var i=this,n=this.ajaxForm||{},t=n.properties||e.data();if(e.hasClass("qor-action-disabled"))return!1;!t.fromIndex||n.formData&&n.formData.length?t.confirm?f.qorConfirm(t,function(t){t&&i.handleAjaxSubmit(n,e)}):this.handleAjaxSubmit(n,e):f.qorConfirm(n.properties.errorNoItem)},handleAjaxSubmit:function(o,r){var s=this,a=this.$element,l=r.closest(".qor-action-forms"),d=o.properties||r.data(),c=d.url,u=d.undoUrl,e=r.hasClass(p),t=r.closest(".qor-slideout").length,i=a.length&&!t;e&&(c=u),this.addLoading(),(l.length?l.find('[data-ajax-form="true"][data-method]'):r).addClass("qor-action-disabled"),h.ajax(c,{method:d.method,data:o.formData,dataType:d.datatype||"json",beforeSend:function(){u?r.prop("disabled",!0):i&&s.switchButtons(a,1)},success:function(t){if(u)return a.trigger("undo.qor.action",[r,e,t]),e?r.removeClass(p):r.addClass(p),void r.prop("disabled",!1);window.location.reload()},error:function(t){200!=t.status&&(u?r.prop("disabled",!1):i&&s.switchButtons(a),f.handleAjaxError(t))},complete:function(t){var e,i=t.getResponseHeader("content-type"),n=t.getResponseHeader("Content-Disposition");h(m).remove(),r.prop("disabled",!1),(l.length?l.find('[data-ajax-form="true"][data-method]'):r).removeClass("qor-action-disabled"),n&&-1!==n.indexOf("attachment")&&(e={},t="",null!=(n=/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(n))&&n[1]&&(t=n[1].replace(/['"]/g,"")),d.method&&(e=h.extend({},o.normalFormData,{_method:d.method})),f.qorAjaxHandleFile(c,i,t,e),u?r.prop("disabled",!1):s.switchButtons(a))}})},switchButtons:function(t,e){e=!!e;t.find(".qor-action-button").prop("disabled",e)},destroy:function(){this.unbind(),this.$element.removeData(o)}},u.DEFAULTS={},u.TEMPLATE_LOADING='
',h.fn.qorSliderAfterShow.qorInsertActionData=function(t,e){var i=h(e).find('[data-toggle="qor-action-slideout"]'),n=i.find("form"),e=h(a).find(".mdl-checkbox__input:checked");i.length&&e.length&&e.each(function(){var t=h(this).closest("tr").data("primary-key");t&&n.prepend('
')})},u.plugin=function(n){return this.each(function(){var t,e=h(this),i=e.data(o);i||e.data(o,i=new u(this,n)),"string"==typeof n&&h.isFunction(t=i[n])&&t.call(i)})},h(function(){var e={},i='[data-toggle="qor.action.bulk"]';h(i).length||h(document).on(n,r,function(t){return(new u).actionSubmit(h(t.target)),!1}),h(document).on("disable.qor.action",function(t){u.plugin.call(h(i,t.target),"destroy")}).on(t,function(t){u.plugin.call(h(i,t.target),e)}).triggerHandler(t)}),u}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?t(require("jquery")):t(jQuery)}(function(a){var l=window.location,r=window.QOR,o="qor.advancedsearch",t="enable."+o,e="click."+o;function s(t,e){this.$element=a(t),this.options=a.extend({},s.DEFAULTS,a.isPlainObject(e)&&e),this.init()}return s.prototype={constructor:s,init:function(){this.$form=this.$element.find("form"),this.$modal=a(s.MODAL).appendTo("body"),this.bind()},bind:function(){this.$element.on("submit.qor.advancedsearch","form",this.submit.bind(this)).on(e,".qor-advanced-filter__save",this.showSaveFilter.bind(this)).on(e,".qor-advanced-filter__toggle",this.toggleFilterContent).on(e,".qor-advanced-filter__close",this.closeFilter).on(e,".qor-advanced-filter__delete",this.deleteSavedFilter),this.$modal.on("shown.qor.modal",this.start.bind(this))},closeFilter:function(){a(".qor-advanced-filter__dropdown").hide()},toggleFilterContent:function(t){a(t.target).closest(".qor-advanced-filter__toggle").parent().find(">[advanced-search-toggle]").toggle()},showSaveFilter:function(){this.$modal.qorModal("show")},deleteSavedFilter:function(t){var e=a(t.target).closest(".qor-advanced-filter__delete"),i=e.closest(".qor-advanced-filter__savedfilter"),n=e.data("filter-name"),o=l.pathname;return r.qorConfirm({confirm:"Are you sure you want to delete this saved filter?"},function(t){t&&a.get(o,a.param({delete_saved_filter:n})).done(function(){e.closest("li").remove(),0===i.find("li").length&&i.remove()}).fail(function(){r.qorConfirm("Server error, please try again!")})}),!1},start:function(){this.$modal.trigger("enable.qor.material").on(e,".qor-advanced-filter__savefilter",this.saveFilter.bind(this))},saveFilter:function(){var t=this.$modal.find("#qor-advanced-filter__savename").val();t&&this.$form.prepend('
')).submit()},submit:function(){var t,e=this.$form,i=e.find("input[name],select[name]"),n=[],o=e.closest(".qor-bottomsheets"),r=e.serialize();if(i.each(function(){n.push(a(this).attr("name"))}),t=function(t){var e,i,n=decodeURIComponent(l.search.substr(1)).split("&"),o={};if(1==n.length&&""==n[0])return!1;for(i in n)""!==n[i]&&(e=n[i].split("="),o[e[0]]=e[1]);return t.forEach(function(t){delete o[t]}),o}(n),!a.isEmptyObject(t))for(var s in t)t.hasOwnProperty(s)&&e.prepend('
\n
\n
\n
Save advanced filter
\n \n
\n \n
\n \n \n
\n\n
\n
\n \n
\n
',s.plugin=function(n){return this.each(function(){var t,e=a(this),i=e.data(o);if(!i){if(/destroy/.test(n))return;e.data(o,i=new s(this,n))}"string"==typeof n&&a.isFunction(t=i[n])&&t.apply(i)})},a(function(){var e='[data-toggle="qor.advancedsearch"]';a(document).on("disable.qor.advancedsearch",function(t){s.plugin.call(a(e,t.target),"destroy")}).on(t,function(t){s.plugin.call(a(e,t.target),void 0)}).triggerHandler(t)}),s}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?t(require("jquery")):t(jQuery)}(function(o){var r="qor.autoheight",t="enable."+r;function s(t,e){this.$element=o(t),this.options=o.extend({},s.DEFAULTS,o.isPlainObject(e)&&e),this.init()}return s.prototype={constructor:s,init:function(){var t=this.$element;this.paddingTop=parseInt(t.css("padding-top"),10),this.paddingBottom=parseInt(t.css("padding-bottom"),10),this.resize(),this.bind()},bind:function(){this.$element.on("input",o.proxy(this.resize,this))},unbind:function(){this.$element.off("input",this.resize)},resize:function(){var t=this.$element,e=t.prop("scrollHeight");e?t.height("auto").height(e-this.paddingTop-this.paddingBottom):t.height("40px")},destroy:function(){this.unbind(),this.$element.removeData(r)}},s.DEFAULTS={},s.plugin=function(n){return this.each(function(){var t,e=o(this),i=e.data(r);if(!i){if(/destroy/.test(n))return;e.data(r,i=new s(this,n))}"string"==typeof n&&o.isFunction(t=i[n])&&t.apply(i)})},o(function(){var e="textarea.qor-js-autoheight";o(document).on("disable.qor.autoheight",function(t){s.plugin.call(o(e,t.target),"destroy")}).on(t,function(t){s.plugin.call(o(e,t.target))}).triggerHandler(t)}),s}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?t(require("jquery")):t(jQuery)}(function(b){var o=window._,n=window.FormData,i=window.QOR_Translations,r="qor.bottomsheets",t="click."+r,e="submit."+r,v="qor-bottomsheets-open",_=".mdl-layout__content.qor-page",s=".qor-page__body",q=".qor-page__header",a=".qor-bottomsheets__search-input";function l(t,e){var i=[],n=e?"src":"href";return t.each(function(){i.push(b(this).attr(n))}),o.uniq(i)}function d(t,e,i){for(var n=0,o=0,r=t.length;o