From e083f8cfb0132ca4730af9ad8da9f736f612764f Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Fri, 17 Jul 2015 11:12:31 +0300 Subject: [PATCH 01/60] MAGETWO-22612: All rows must be filled in on 'Order by SKU' before adding to cart instead of escaping empty ones --- lib/web/mage/validation.js | 282 +++++++++++++++++++------------------ 1 file changed, 147 insertions(+), 135 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 78cc93607e66e..98240eb8cfa40 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -22,16 +22,16 @@ /** * Check if string is empty with trim * @param {string} value - */ - isEmpty: function(value) { - return (value === '' || value === undefined || (value == null) || (value.length === 0) || /^\s+$/.test(value)); + */ + isEmpty: function (value) { + return (value === '' || value === undefined || (value == null) || (value.length === 0) || /^\s+$/.test(value)); }, /** * Check if string is empty no trim * @param {string} value - */ - isEmptyNoTrim: function(value) { + */ + isEmptyNoTrim: function (value) { return (value === '' || (value == null) || (value.length === 0)); }, @@ -43,16 +43,16 @@ * @param {string} to * @returns {boolean} */ - isBetween: function(value, from, to){ + isBetween: function (value, from, to) { return ($.mage.isEmpty(from) || value >= $.mage.parseNumber(from)) && - ($.mage.isEmpty(to) || value <= $.mage.parseNumber(to)); + ($.mage.isEmpty(to) || value <= $.mage.parseNumber(to)); }, /** * Parse price string * @param {string} value - */ - parseNumber: function(value) { + */ + parseNumber: function (value) { if (typeof value !== 'string') { return parseFloat(value); } @@ -75,7 +75,7 @@ * @param value Value being stripped. * @return {*} */ - stripHtml: function(value) { + stripHtml: function (value) { return value.replace(/<.[^<>]*?>/g, ' ').replace(/ | /gi, ' ') .replace(/[0-9.(),;:!?%#$'"_+=\/-]*/g, ''); } @@ -85,7 +85,7 @@ $.validator.addMethod = function (name, method, message, dontSkip) { $.validator.methods[name] = method; $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name]; - + if (method.length < 3 || dontSkip) { $.validator.addClassRules(name, $.validator.normalizeRule(name)); } @@ -146,63 +146,63 @@ */ var rules = { "max-words": [ - function(value, element, params) { + function (value, element, params) { return this.optional(element) || $.mage.stripHtml(value).match(/\b\w+\b/g).length < params; }, 'Please enter {0} words or less.' ], "min-words": [ - function(value, element, params) { + function (value, element, params) { return this.optional(element) || $.mage.stripHtml(value).match(/\b\w+\b/g).length >= params; }, 'Please enter at least {0} words.' ], "range-words": [ - function(value, element, params) { + function (value, element, params) { return this.optional(element) || $.mage.stripHtml(value).match(/\b\w+\b/g).length >= params[0] && - value.match(/bw+b/g).length < params[1]; + value.match(/bw+b/g).length < params[1]; }, 'Please enter between {0} and {1} words.' ], "letters-with-basic-punc": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^[a-z\-.,()'\"\s]+$/i.test(value); }, 'Letters or punctuation only please' ], "alphanumeric": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^\w+$/i.test(value); }, 'Letters, numbers, spaces or underscores only please' ], "letters-only": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^[a-z]+$/i.test(value); }, 'Letters only please' ], "no-whitespace": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^\S+$/i.test(value); }, 'No white space please' ], "zip-range": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^90[2-5]-\d{2}-\d{4}$/.test(value); }, 'Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx' ], "integer": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^-?\d+$/.test(value); }, 'A positive or negative non-decimal number please' ], "vinUS": [ - function(v) { + function (v) { if (v.length !== 17) { return false; } @@ -245,7 +245,7 @@ 'The specified vehicle identification number (VIN) is invalid.' ], "dateITA": [ - function(value, element) { + function (value, element) { var check = false; var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/; if (re.test(value)) { @@ -268,25 +268,25 @@ 'Please enter a correct date' ], "dateNL": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?$/.test(value); }, 'Vul hier een geldige datum in.' ], "time": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){0,2}$/.test(value); }, 'Please enter a valid time, between 00:00 and 23:59' ], "time12h": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){0,2}(\ [AP]M))$/i.test(value); }, 'Please enter a valid time, between 00:00 am and 12:00 pm' ], "phoneUS": [ - function(phone_number, element) { + function (phone_number, element) { phone_number = phone_number.replace(/\s+/g, ""); return this.optional(element) || phone_number.length > 9 && phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/); @@ -294,39 +294,39 @@ 'Please specify a valid phone number' ], "phoneUK": [ - function(phone_number, element) { + function (phone_number, element) { return this.optional(element) || phone_number.length > 9 && phone_number.match(/^(\(?(0|\+44)[1-9]{1}\d{1,4}?\)?\s?\d{3,4}\s?\d{3,4})$/); }, 'Please specify a valid phone number' ], "mobileUK": [ - function(phone_number, element) { + function (phone_number, element) { return this.optional(element) || phone_number.length > 9 && phone_number.match(/^((0|\+44)7(5|6|7|8|9){1}\d{2}\s?\d{6})$/); }, 'Please specify a valid mobile number' ], "stripped-min-length": [ - function(value, element, param) { + function (value, element, param) { return $(value).text().length >= param; }, 'Please enter at least {0} characters' ], "email2": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); }, $.validator.messages.email ], "url2": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); }, $.validator.messages.url ], "credit-card-types": [ - function(value, element, param) { + function (value, element, param) { if (/[^0-9-]+/.test(value)) { return false; } @@ -393,25 +393,25 @@ 'Please enter a valid credit card number.' ], "ipv4": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i.test(value); }, 'Please enter a valid IP v4 address.' ], "ipv6": [ - function(value, element) { + function (value, element) { return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value); }, 'Please enter a valid IP v6 address.' ], "pattern": [ - function(value, element, param) { + function (value, element, param) { return this.optional(element) || param.test(value); }, 'Invalid format.' ], "allow-container-className": [ - function(element) { + function (element) { if (element.type === 'radio' || element.type === 'checkbox') { return $(element).hasClass('change-container-classname'); } @@ -419,73 +419,73 @@ '' ], "validate-no-html-tags": [ - function(value) { + function (value) { return !/<(\/)?\w+/.test(value); }, 'HTML tags are not allowed.' ], "validate-select": [ - function(value) { + function (value) { return ((value !== "none") && (value != null) && (value.length !== 0)); }, 'Please select an option.' ], "validate-no-empty": [ - function(value) { + function (value) { return !$.mage.isEmpty(value); }, 'Empty Value.' ], "validate-alphanum-with-spaces": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z0-9 ]+$/.test(v); }, 'Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.' ], "validate-data": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v); }, 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.' ], "validate-street": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(v); }, 'Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.' ], "validate-phoneStrict": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v); }, 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.' ], "validate-phoneLax": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^((\d[\-. ]?)?((\(\d{3}\))|\d{3}))?[\-. ]?\d{3}[\-. ]?\d{4}$/.test(v); }, 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.' ], "validate-fax": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v); }, 'Please enter a valid fax number (Ex: 123-456-7890).' ], "validate-email": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(v); }, 'Please enter a valid email address (Ex: johndoe@domain.com).' ], "validate-emailSender": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[\S ]+$/.test(v); }, 'Please enter a valid email address (Ex: johndoe@domain.com).' ], "validate-password": [ - function(v) { + function (v) { if (v == null) { return false; } @@ -499,7 +499,7 @@ 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.' ], "validate-admin-password": [ - function(v) { + function (v) { if (v == null) { return false; } @@ -519,7 +519,7 @@ 'Please enter 7 or more characters, using both numeric and alphabetic.' ], "validate-url": [ - function(v) { + function (v) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -530,35 +530,35 @@ 'Please enter a valid URL. Protocol is required (http://, https:// or ftp://).' ], "validate-clean-url": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v) || /^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v); }, 'Please enter a valid URL. For example http://www.example.com or www.example.com.' ], "validate-xml-identifier": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[A-Z][A-Z0-9_\/-]*$/i.test(v); }, 'Please enter a valid XML-identifier (Ex: something_1, block5, id-4).' ], "validate-ssn": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v); }, 'Please enter a valid social security number (Ex: 123-45-6789).' ], "validate-zip-us": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v); }, 'Please enter a valid zip code (Ex: 90602 or 90602-1234).' ], "validate-date-au": [ - function(v) { + function (v) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -575,14 +575,14 @@ 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.' ], "validate-currency-dollar": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v); }, 'Please enter a valid $ amount. For example $100.00.' ], "validate-not-negative-number": [ - function(v) { + function (v) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -594,7 +594,7 @@ ], // validate-not-negative-number should be replaced in all places with this one and then removed "validate-zero-or-greater": [ - function(v) { + function (v) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -605,7 +605,7 @@ 'Please enter a number 0 or greater in this field.' ], "validate-greater-than-zero": [ - function(v) { + function (v) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -615,7 +615,7 @@ 'Please enter a number greater than 0 in this field.' ], "validate-css-length": [ - function(v) { + function (v) { if (v !== '') { return (/^[0-9]*\.*[0-9]+(px|pc|pt|ex|em|mm|cm|in|%)?$/).test(v); } @@ -625,19 +625,19 @@ ], /** @description Additional methods */ "validate-number": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || (!isNaN($.mage.parseNumber(v)) && /^\s*-?\d*(\.\d*)?\s*$/.test(v)); }, 'Please enter a valid number in this field.' ], "required-number": [ - function(v){ + function (v) { return !!v.length; }, 'Please enter a valid number in this field.' ], "validate-number-range": [ - function(v, elm, param) { + function (v, elm, param) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -658,7 +658,7 @@ if (m) { result = result && $.mage.isBetween(numValue, m[1], m[2]); } - } else if (elm && elm.className ) { + } else if (elm && elm.className) { classes = elm.className.split(" "); ii = classes.length; @@ -678,13 +678,13 @@ true ], "validate-digits": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || !/[^\d]/.test(v); }, 'Please enter a valid number in this field.' ], "validate-digits-range": [ - function(v, elm, param) { + function (v, elm, param) { if ($.mage.isEmptyNoTrim(v)) { return true; } @@ -699,13 +699,13 @@ result = true, range, m, classes, ii; range = param; - + if (typeof range === 'object') { m = dataAttrRange.exec(range); if (m) { result = result && $.mage.isBetween(numValue, m[1], m[2]); } - } else if (elm && elm.className ) { + } else if (elm && elm.className) { classes = elm.className.split(" "); ii = classes.length; @@ -725,7 +725,7 @@ true ], 'validate-range': [ - function(v, elm) { + function (v, elm) { var minValue, maxValue; if ($.mage.isEmptyNoTrim(v)) { return true; @@ -756,8 +756,8 @@ var minValidRange = $.mage.parseNumber(validRange[1]); var maxValidRange = $.mage.parseNumber(validRange[2]); result = result && - (isNaN(minValidRange) || minValue >= minValidRange) && - (isNaN(maxValidRange) || maxValue <= maxValidRange); + (isNaN(minValidRange) || minValue >= minValidRange) && + (isNaN(maxValidRange) || maxValue <= maxValidRange); } } return result; @@ -765,39 +765,39 @@ 'The value is not within the specified range.' ], "validate-alpha": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z]+$/.test(v); }, 'Please use letters only (a-z or A-Z) in this field.' ], "validate-code": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[a-z]+[a-z0-9_]+$/.test(v); }, 'Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.' ], "validate-alphanum": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z0-9]+$/.test(v); }, 'Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.' ], "validate-date": [ - function(v) { + function (v) { var test = new Date(v); return $.mage.isEmptyNoTrim(v) || !isNaN(test); - },'Please enter a valid date.' + }, 'Please enter a valid date.' ], "validate-date-range": [ - function(v, elm) { + function (v, elm) { var m = /\bdate-range-(\w+)-(\w+)\b/.exec(elm.className); if (!m || m[2] === 'to' || $.mage.isEmptyNoTrim(v)) { return true; } var currentYear = new Date().getFullYear() + ''; - var normalizedTime = function(v) { + var normalizedTime = function (v) { v = v.split(/[.\/]/); if (v[2] && v[2].length < 4) { v[2] = currentYear.substr(0, v[2].length) + v[2]; @@ -812,7 +812,7 @@ 'Make sure the To Date is later than or the same as the From Date.' ], "validate-cpassword": [ - function() { + function () { var conf = $('#confirmation').length > 0 ? $('#confirmation') : $($('.validate-cpassword')[0]); var pass = false; if ($('#password')) { @@ -833,7 +833,7 @@ 'Please make sure your passwords match.' ], "validate-identifier": [ - function(v) { + function (v) { return $.mage.isEmptyNoTrim(v) || /^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(v); }, 'Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").' @@ -843,29 +843,29 @@ // @TODO: Cleanup return Validation.get('IsEmpty').test(v) || /(^[A-z0-9]{2,10}([\s]{0,1}|[\-]{0,1})[A-z0-9]{2,10}$)/.test(v); }*/ - function() { + function () { return true; }, 'Please enter a valid zip code.' ], "validate-one-required": [ - function(v, elm) { + function (v, elm) { var p = $(elm).parent(); var options = p.find('input'); - return options.map(function(elm) { - return $(elm).val(); - }).length > 0; + return options.map(function (elm) { + return $(elm).val(); + }).length > 0; }, 'Please select one of the options above.' ], "validate-state": [ - function(v) { + function (v) { return (v !== 0 || v === ''); }, 'Please select State/Province.' ], "required-file": [ - function(v, elm) { + function (v, elm) { var result = !$.mage.isEmptyNoTrim(v); if (!result) { var ovId = $(elm).attr('id') + '_value'; @@ -878,9 +878,9 @@ 'Please select a file.' ], "validate-ajax-error": [ - function(v, element) { + function (v, element) { element = $(element); - element.on('change.ajaxError', function() { + element.on('change.ajaxError', function () { element.removeClass('validate-ajax-error'); element.off('change.ajaxError'); }); @@ -889,7 +889,7 @@ '' ], "validate-optional-datetime": [ - function(v, elm, param) { + function (v, elm, param) { var dateTimeParts = $('.datetime-picker[id^="options_' + param + '"]'), hasWithValue = false, hasWithNoValue = false, pattern = /day_part$/i; @@ -907,7 +907,7 @@ 'The field isn\'t complete.' ], "validate-required-datetime": [ - function(v, elm, param) { + function (v, elm, param) { var dateTimeParts = $('.datetime-picker[id^="options_' + param + '"]'); for (var i = 0; i < dateTimeParts.length; i++) { if (dateTimeParts[i].value === "") { @@ -919,43 +919,43 @@ 'This is a required field.' ], "validate-one-required-by-name": [ - function(v, elm, selector) { - var name = elm.name.replace(/([\\"])/g, '\\$1'), - container = this.currentForm, - selector = selector === true ? 'input[name="' + name + '"]:checked' : selector; - + function (v, elm, selector) { + var name = elm.name.replace(/([\\"])/g, '\\$1'), + container = this.currentForm, + selector = selector === true ? 'input[name="' + name + '"]:checked' : selector; + return !!container.querySelectorAll(selector).length; }, 'Please select one of the options.' ], "less-than-equals-to": [ - function(value, element, params) { + function (value, element, params) { if ($.isNumeric($(params).val()) && $.isNumeric(value)) { this.lteToVal = $(params).val(); return parseFloat(value) <= parseFloat($(params).val()); } return true; }, - function() { + function () { var message = $.mage.__('Please enter a value less than or equal to %s.'); return message.replace('%s', this.lteToVal); } ], "greater-than-equals-to": [ - function(value, element, params) { + function (value, element, params) { if ($.isNumeric($(params).val()) && $.isNumeric(value)) { this.gteToVal = $(params).val(); return parseFloat(value) >= parseFloat($(params).val()); } return true; }, - function() { + function () { var message = $.mage.__('Please enter a value greater than or equal to %s.'); return message.replace('%s', this.gteToVal); } ], "validate-emails": [ - function(value) { + function (value) { if ($.mage.isEmpty(value)) { return true; } @@ -978,7 +978,7 @@ * @param params - selector for credit card number * @return {boolean} */ - function(value, element, params) { + function (value, element, params) { if (value && params && creditCartTypes[value]) { return creditCartTypes[value][0].test($(params).val().replace(/\s+/g, '')); } @@ -991,7 +991,7 @@ * @param value - credit card number * @return {boolean} */ - function(value) { + function (value) { if (value) { return validateCreditCard(value); } @@ -1006,7 +1006,7 @@ * @param params - selector for credit card type * @return {boolean} */ - function(value, element, params) { + function (value, element, params) { if (value && params) { var ccType = $(params).val(); value = value.replace(/\s/g, '').replace(/\-/g, ''); @@ -1027,7 +1027,7 @@ * @param params - year selector * @return {Boolean} */ - function(value, element, params) { + function (value, element, params) { var isValid = false; if (value && params) { var month = value, @@ -1048,7 +1048,7 @@ * @param params - credit card type selector * @return {*} */ - function(value, element, params) { + function (value, element, params) { if (value && params) { var ccType = $(params).val(); if (creditCartTypes[ccType] && creditCartTypes[ccType][0]) { @@ -1064,19 +1064,19 @@ * @param value - input field value * @return {*} */ - function(value) { + function (value) { return value; }, 'Please enter issue number or start date for switch/solo card type.' ], "validate-length": [ - function(v, elm) { + function (v, elm) { var reMax = new RegExp(/^maximum-length-[0-9]+$/), reMin = new RegExp(/^minimum-length-[0-9]+$/), validator = this, result = true, length = 0; - $.each(elm.className.split(' '), function(index, name) { + $.each(elm.className.split(' '), function (index, name) { if (name.match(reMax) && result) { length = name.split('-')[2]; validator.attrLength = length; @@ -1088,18 +1088,18 @@ } }); return result; - }, function() { + }, function () { return $.mage.__("Maximum length of this field must be equal or less than %1 symbols.") .replace('%1', this.attrLength); } ], 'required-entry': [ - function(value) { + function (value) { return !$.mage.isEmpty(value); }, $.mage.__('This is a required field.') ], 'not-negative-amount': [ - function(v) { + function (v) { if (v.length) return (/^\s*\d+([,.]\d+)*\s*%?\s*$/).test(v); else @@ -1108,7 +1108,7 @@ 'Please enter positive number in this field.' ], 'validate-per-page-value-list': [ - function(v) { + function (v) { var isValid = !$.mage.isEmpty(v); var values = v.split(','); for (var i = 0; i < values.length; i++) { @@ -1121,7 +1121,7 @@ 'Please enter a valid value, ex: 10,20,30' ], 'validate-per-page-value': [ - function(v, elm) { + function (v, elm) { if ($.mage.isEmpty(v)) { return false; } @@ -1131,10 +1131,9 @@ 'Please enter a valid value from list' ], 'validate-new-password': [ - function(v) { + function (v) { - if ($.validator.methods['validate-password'] && - !$.validator.methods['validate-password'](v)) { + if ($.validator.methods['validate-password'] && !$.validator.methods['validate-password'](v)) { return false; } if ($.mage.isEmpty(v) && v !== '') { @@ -1168,6 +1167,19 @@ }, 'This is a required field.' ], + 'required-if-all-sku-empty': [ + function (value, element, params) { + var valid = false; + + $('input[' + params + '=true]').each(function () { + if ($(this).val() !== '') { + valid = true; + } + }); + + return valid; + }, 'Enter valid SKU key' + ], 'required-if-specified': [ function (value, element, params) { var valid = true; @@ -1194,9 +1206,9 @@ 'This is a required field.' ], 'required-number-if-specified': [ - function (value, element, params) { - var valid = true, - dependent = $(params), + function (value, element, params) { + var valid = true, + dependent = $(params), depeValue; if (dependent.length) { @@ -1219,8 +1231,8 @@ // validate quantity var isMinAllowedValid = typeof params.minAllowed === 'undefined' || (qty >= $.mage.parseNumber(params.minAllowed)); - var isMaxAllowedValid = typeof params.maxAllowed === 'undefined' || (qty <= $.mage.parseNumber(params.maxAllowed)); - var isQtyIncrementsValid = typeof params.qtyIncrements === 'undefined' || (qty % $.mage.parseNumber(params.qtyIncrements) === 0); + var isMaxAllowedValid = typeof params.maxAllowed === 'undefined' || (qty <= $.mage.parseNumber(params.maxAllowed)); + var isQtyIncrementsValid = typeof params.qtyIncrements === 'undefined' || (qty % $.mage.parseNumber(params.qtyIncrements) === 0); return isMaxAllowedValid && isMinAllowedValid && isQtyIncrementsValid && qty > 0; }, @@ -1228,7 +1240,7 @@ ] }; - $.each(rules, function(i, rule) { + $.each(rules, function (i, rule) { rule.unshift(i); $.validator.addMethod.apply($.validator, rule); }); @@ -1254,7 +1266,7 @@ var showLabel = $.validator.prototype.showLabel; $.extend(true, $.validator.prototype, { - showLabel: function(element, message) { + showLabel: function (element, message) { showLabel.call(this, element, message); // ARIA (adding aria-invalid & aria-describedby) @@ -1262,7 +1274,7 @@ elem = $(element); if (!label.attr('id')) { - label.attr('id', this.idOrName(element)+'-error'); + label.attr('id', this.idOrName(element) + '-error'); } elem.attr('aria-invalid', 'true') .attr('aria-describedby', label.attr('id')); @@ -1274,7 +1286,7 @@ * @param {Element||String} element - DOM element or selector * @return {Boolean} validation result */ - $.validator.validateElement = function(element) { + $.validator.validateElement = function (element) { element = $(element); var form = element.get(0).form, validator = form ? $(form).data('validator') : null; @@ -1284,7 +1296,7 @@ } else { var valid = true, classes = element.prop('class').split(' '); - $.each(classes, $.proxy(function(i, className) { + $.each(classes, $.proxy(function (i, className) { if (this.methods[className] && !this.methods[className](element.val(), element.get(0))) { valid = false; return valid; @@ -1303,7 +1315,7 @@ ignoreTitle: true, errorClass: 'mage-error', errorElement: 'div', - errorPlacement: function(error, element) { + errorPlacement: function (error, element) { var errorPlacement = element; // logic for date-picker error placement if (element.hasClass('hasDatepicker')) { @@ -1325,16 +1337,16 @@ * Check if form pass validation rules without submit * @return boolean */ - isValid: function() { + isValid: function () { return this.element.valid(); }, /** * Remove validation error messages */ - clearError: function() { + clearError: function () { if (arguments.length) { - $.each(arguments, $.proxy(function(index, item) { + $.each(arguments, $.proxy(function (index, item) { this.validate.prepareElement(item); this.validate.hideErrors(); }, this)); @@ -1346,7 +1358,7 @@ * Validation creation * @protected */ - _create: function() { + _create: function () { this.validate = this.element.validate(this.options); // ARIA (adding aria-required attribute) @@ -1362,7 +1374,7 @@ * Validation listening * @protected */ - _listenFormValidate: function() { + _listenFormValidate: function () { $('form').on('invalid-form.validate', function (event, validation) { var firstActive = $(validation.errorList[0].element || []), lastActive = $(validation.findLastActive() || validation.errorList.length && validation.errorList[0].element || []); @@ -1378,7 +1390,7 @@ // ARIA (removing aria attributes if success) var successList = validation.successList; if (successList.length) { - $.each(successList, function() { + $.each(successList, function () { $(this) .removeAttr('aria-describedby') .removeAttr('aria-invalid'); From 39992c0daad40888b4067c6a41ca02582aefa054 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Fri, 17 Jul 2015 16:36:56 +0300 Subject: [PATCH 02/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- .../backend/Magento_Backend/web/css/source/module/_menu.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less index c4dcfaa20e93b..1c7f1eed7cabe 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less @@ -230,7 +230,7 @@ visibility: hidden; z-index: @submenu__z-index - 1; &._overlap { - overflow-y: auto; + overflow-y: hidden; height: 100%; &::-webkit-scrollbar { width: 0; From aeb511f5353ada33998cf53754c8303656ded396 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Fri, 17 Jul 2015 18:18:43 +0300 Subject: [PATCH 03/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- .../adminhtml/Magento/backend/web/js/theme.js | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index c3d695cb9e582..7a12a9e63f309 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -18,7 +18,7 @@ define('globalNavigationScroll', [ subMenus = menuItems.children(subMenuClass), winHeight, menuHeight = menu.height(), - menuHeightRest = 0, + menuHeightRest, menuScrollMax = 0, submenuHeight = 0, contentHeight, @@ -82,19 +82,20 @@ define('globalNavigationScroll', [ nextTop < (menuScrollMax - scrollStep) ? nextTop += scrollStep : nextTop = menuScrollMax; - menu.css('top', -nextTop); + menu.css('top', -nextTop * 2); + } else if (winTop < winTopLast) { // scroll up nextTop > -scrollStep ? nextTop += scrollStep : nextTop = 0; - menu.css('top', -nextTop); + menu.css('top', -nextTop * 2); } - } + } else { // static menu cases checkRemoveClass(menu, fixedClassName); } @@ -127,10 +128,9 @@ define('globalNavigationScroll', [ // Add event to menuItems to check submenu overlap menuItems.on('click', function () { - + var submenu = $(this).children(subMenuClass); submenuHeight = submenu.height(); - if (isMenuFixed() && (submenuHeight > winHeight)) { checkAddClass(submenu, overlapClassName); } @@ -161,7 +161,7 @@ define('globalNavigation', [ _create: function () { var selectors = this.options.selectors; - this.menu = this.element; + this.menu = this.element; this.menuLinks = $(selectors.topLevelHref, selectors.topLevelItem); this.closeActions = $(selectors.closeSubmenuBtn); @@ -195,9 +195,9 @@ define('globalNavigation', [ * Remove active class from current menu item * Turn back active class to current page menu item */ - _blur: function(e){ + _blur: function (e) { var selectors = this.options.selectors, - menuItem = $(e.target).closest(selectors.topLevelItem), + menuItem = $(e.target).closest(selectors.topLevelItem), currentItem = $(selectors.menu).find(selectors.currentItem); menuItem.removeClass('_active'); @@ -207,11 +207,11 @@ define('globalNavigation', [ /** * Add focus to active menu item */ - _keyboard: function(e) { + _keyboard: function (e) { var selectors = this.options.selectors, - menuItem = $(e.target).closest(selectors.topLevelItem); + menuItem = $(e.target).closest(selectors.topLevelItem); - if(e.which === 13) { + if (e.which === 13) { this._close(e); $(selectors.topLevelHref, menuItem).focus(); } @@ -222,11 +222,11 @@ define('globalNavigation', [ */ _focus: function (e) { var selectors = this.options.selectors, - menuItem = $(e.target).closest(selectors.topLevelItem); + menuItem = $(e.target).closest(selectors.topLevelItem); menuItem.addClass('_active') - .siblings(selectors.topLevelItem) - .removeClass('_active'); + .siblings(selectors.topLevelItem) + .removeClass('_active'); }, _closeSubmenu: function (e) { @@ -239,23 +239,23 @@ define('globalNavigation', [ }, _open: function (e) { - var selectors = this.options.selectors, - menuItemSelector = selectors.topLevelItem, - menuItem = $(e.target).closest(menuItemSelector), - subMenu = $(selectors.subMenu, menuItem), - close = this._closeSubmenu.bind(this), - closeBtn = subMenu.find(selectors.closeSubmenuBtn); + var selectors = this.options.selectors, + menuItemSelector = selectors.topLevelItem, + menuItem = $(e.target).closest(menuItemSelector), + subMenu = $(selectors.subMenu, menuItem), + close = this._closeSubmenu.bind(this), + closeBtn = subMenu.find(selectors.closeSubmenuBtn); if (subMenu.length) { e.preventDefault(); } menuItem.addClass('_show') - .siblings(menuItemSelector) - .removeClass('_show'); + .siblings(menuItemSelector) + .removeClass('_show'); subMenu.attr('aria-expanded', 'true'); - + subMenu.css('height', 765); closeBtn.on('click', close); this.overlay.show(0).on('click', close); @@ -263,11 +263,11 @@ define('globalNavigation', [ }, _close: function (e) { - var selectors = this.options.selectors, - menuItem = this.menu.find(selectors.topLevelItem + '._show'), - subMenu = $(selectors.subMenu, menuItem), - closeBtn = subMenu.find(selectors.closeSubmenuBtn), - blur = this._blur.bind(this); + var selectors = this.options.selectors, + menuItem = this.menu.find(selectors.topLevelItem + '._show'), + subMenu = $(selectors.subMenu, menuItem), + closeBtn = subMenu.find(selectors.closeSubmenuBtn), + blur = this._blur.bind(this); e.preventDefault(); From 3f6630de39d8ded9c44dffa5193ecb60446ff2a7 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Mon, 20 Jul 2015 10:46:46 +0300 Subject: [PATCH 04/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 7a12a9e63f309..91f6077f1af87 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -95,7 +95,6 @@ define('globalNavigationScroll', [ } } - } else { // static menu cases checkRemoveClass(menu, fixedClassName); } From ea1528c94773f036ee6d1aa3b44fe9734ee6db88 Mon Sep 17 00:00:00 2001 From: Anton Guz Date: Wed, 22 Jul 2015 11:27:05 +0300 Subject: [PATCH 05/60] MAGETWO-40308: [GITHUB] admin external extjs.com requests #1483 - Overwritten EXTjs emty icon setting. - Fixed code style --- lib/web/extjs/defaults.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/web/extjs/defaults.js b/lib/web/extjs/defaults.js index 5203e1a6fe27a..d4047c3ddf302 100644 --- a/lib/web/extjs/defaults.js +++ b/lib/web/extjs/defaults.js @@ -1,4 +1,13 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/* global Ext*/ define(['extjs/ext-tree'], function () { + 'use strict'; + Ext.UpdateManager.defaults.loadScripts = false; Ext.UpdateManager.defaults.disableCaching = true; -}); \ No newline at end of file + Ext.BLANK_IMAGE_URL = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; +}); From 59125894105ece252f6c2826cd5e85b187ec9563 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Wed, 22 Jul 2015 16:50:22 +0300 Subject: [PATCH 06/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index c3d695cb9e582..a41dc6302e572 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -82,14 +82,14 @@ define('globalNavigationScroll', [ nextTop < (menuScrollMax - scrollStep) ? nextTop += scrollStep : nextTop = menuScrollMax; - menu.css('top', -nextTop); + menu.css('top', -nextTop * 2); } else if (winTop < winTopLast) { // scroll up nextTop > -scrollStep ? nextTop += scrollStep : nextTop = 0; - menu.css('top', -nextTop); + menu.css('top', -nextTop * 2); } @@ -255,6 +255,7 @@ define('globalNavigation', [ .removeClass('_show'); subMenu.attr('aria-expanded', 'true'); + subMenu.css('height', 765); closeBtn.on('click', close); From f57ca0c3087ce7e2e8cd6e814693170d5c9f8ae0 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Wed, 22 Jul 2015 18:48:17 +0300 Subject: [PATCH 07/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index a41dc6302e572..15338cb17b0ae 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -82,14 +82,14 @@ define('globalNavigationScroll', [ nextTop < (menuScrollMax - scrollStep) ? nextTop += scrollStep : nextTop = menuScrollMax; - menu.css('top', -nextTop * 2); + menu.css('top', -nextTop ); } else if (winTop < winTopLast) { // scroll up nextTop > -scrollStep ? nextTop += scrollStep : nextTop = 0; - menu.css('top', -nextTop * 2); + menu.css('top', -nextTop ); } @@ -126,11 +126,13 @@ define('globalNavigationScroll', [ }); // Add event to menuItems to check submenu overlap - menuItems.on('click', function () { + menuItems.on('click', function (e) { var submenu = $(this).children(subMenuClass); submenuHeight = submenu.height(); + + if (isMenuFixed() && (submenuHeight > winHeight)) { checkAddClass(submenu, overlapClassName); } @@ -246,6 +248,7 @@ define('globalNavigation', [ close = this._closeSubmenu.bind(this), closeBtn = subMenu.find(selectors.closeSubmenuBtn); + if (subMenu.length) { e.preventDefault(); } @@ -255,7 +258,8 @@ define('globalNavigation', [ .removeClass('_show'); subMenu.attr('aria-expanded', 'true'); - subMenu.css('height', 765); + + //subMenu.css('height', subMenu.find('ul.menu')[0].height() + subMenu.find('strong.submenu-title').height()); closeBtn.on('click', close); From 8c6f25e1036cc525df50d6ffe65d11a52815f93f Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Wed, 22 Jul 2015 18:57:26 +0300 Subject: [PATCH 08/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- .../adminhtml/Magento/backend/web/js/theme.js | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 15338cb17b0ae..751eb9749a9aa 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -82,14 +82,14 @@ define('globalNavigationScroll', [ nextTop < (menuScrollMax - scrollStep) ? nextTop += scrollStep : nextTop = menuScrollMax; - menu.css('top', -nextTop ); + menu.css('top', -nextTop); } else if (winTop < winTopLast) { // scroll up nextTop > -scrollStep ? nextTop += scrollStep : nextTop = 0; - menu.css('top', -nextTop ); + menu.css('top', -nextTop); } @@ -127,11 +127,12 @@ define('globalNavigationScroll', [ // Add event to menuItems to check submenu overlap menuItems.on('click', function (e) { - - var submenu = $(this).children(subMenuClass); - submenuHeight = submenu.height(); + var submenu = $(this).children(subMenuClass); + submenuHeight = submenu.height(); + menu.css('height', submenuHeight); + menuHeight = submenuHeight; if (isMenuFixed() && (submenuHeight > winHeight)) { checkAddClass(submenu, overlapClassName); @@ -163,7 +164,7 @@ define('globalNavigation', [ _create: function () { var selectors = this.options.selectors; - this.menu = this.element; + this.menu = this.element; this.menuLinks = $(selectors.topLevelHref, selectors.topLevelItem); this.closeActions = $(selectors.closeSubmenuBtn); @@ -197,9 +198,9 @@ define('globalNavigation', [ * Remove active class from current menu item * Turn back active class to current page menu item */ - _blur: function(e){ + _blur: function (e) { var selectors = this.options.selectors, - menuItem = $(e.target).closest(selectors.topLevelItem), + menuItem = $(e.target).closest(selectors.topLevelItem), currentItem = $(selectors.menu).find(selectors.currentItem); menuItem.removeClass('_active'); @@ -209,11 +210,11 @@ define('globalNavigation', [ /** * Add focus to active menu item */ - _keyboard: function(e) { + _keyboard: function (e) { var selectors = this.options.selectors, - menuItem = $(e.target).closest(selectors.topLevelItem); + menuItem = $(e.target).closest(selectors.topLevelItem); - if(e.which === 13) { + if (e.which === 13) { this._close(e); $(selectors.topLevelHref, menuItem).focus(); } @@ -224,11 +225,11 @@ define('globalNavigation', [ */ _focus: function (e) { var selectors = this.options.selectors, - menuItem = $(e.target).closest(selectors.topLevelItem); + menuItem = $(e.target).closest(selectors.topLevelItem); menuItem.addClass('_active') - .siblings(selectors.topLevelItem) - .removeClass('_active'); + .siblings(selectors.topLevelItem) + .removeClass('_active'); }, _closeSubmenu: function (e) { @@ -241,12 +242,12 @@ define('globalNavigation', [ }, _open: function (e) { - var selectors = this.options.selectors, - menuItemSelector = selectors.topLevelItem, - menuItem = $(e.target).closest(menuItemSelector), - subMenu = $(selectors.subMenu, menuItem), - close = this._closeSubmenu.bind(this), - closeBtn = subMenu.find(selectors.closeSubmenuBtn); + var selectors = this.options.selectors, + menuItemSelector = selectors.topLevelItem, + menuItem = $(e.target).closest(menuItemSelector), + subMenu = $(selectors.subMenu, menuItem), + close = this._closeSubmenu.bind(this), + closeBtn = subMenu.find(selectors.closeSubmenuBtn); if (subMenu.length) { @@ -254,8 +255,8 @@ define('globalNavigation', [ } menuItem.addClass('_show') - .siblings(menuItemSelector) - .removeClass('_show'); + .siblings(menuItemSelector) + .removeClass('_show'); subMenu.attr('aria-expanded', 'true'); @@ -268,11 +269,11 @@ define('globalNavigation', [ }, _close: function (e) { - var selectors = this.options.selectors, - menuItem = this.menu.find(selectors.topLevelItem + '._show'), - subMenu = $(selectors.subMenu, menuItem), - closeBtn = subMenu.find(selectors.closeSubmenuBtn), - blur = this._blur.bind(this); + var selectors = this.options.selectors, + menuItem = this.menu.find(selectors.topLevelItem + '._show'), + subMenu = $(selectors.subMenu, menuItem), + closeBtn = subMenu.find(selectors.closeSubmenuBtn), + blur = this._blur.bind(this); e.preventDefault(); From 589a33c032c8f89a3647159022f2a8765e6001c3 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Wed, 22 Jul 2015 18:57:54 +0300 Subject: [PATCH 09/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 751eb9749a9aa..041cec4bfaa42 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -126,7 +126,7 @@ define('globalNavigationScroll', [ }); // Add event to menuItems to check submenu overlap - menuItems.on('click', function (e) { + menuItems.on('click', function () { var submenu = $(this).children(subMenuClass); From 3cdbfa84813e57c891784a3ea088aa616e062225 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Wed, 22 Jul 2015 18:59:08 +0300 Subject: [PATCH 10/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 041cec4bfaa42..9d6c55eadb46b 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -131,8 +131,10 @@ define('globalNavigationScroll', [ var submenu = $(this).children(subMenuClass); submenuHeight = submenu.height(); - menu.css('height', submenuHeight); - menuHeight = submenuHeight; + if (submenuHeight > menuHeight) { + menu.css('height', submenuHeight); + menuHeight = submenuHeight; + } if (isMenuFixed() && (submenuHeight > winHeight)) { checkAddClass(submenu, overlapClassName); From 9b69a8014ecfa7256c8dd0614a16fba296793dcc Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Thu, 23 Jul 2015 10:36:56 +0300 Subject: [PATCH 11/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 9d6c55eadb46b..ff53b81148084 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -131,6 +131,7 @@ define('globalNavigationScroll', [ var submenu = $(this).children(subMenuClass); submenuHeight = submenu.height(); + if (submenuHeight > menuHeight) { menu.css('height', submenuHeight); menuHeight = submenuHeight; From afd813c4ef87f890053635a2bbd889f1bcca5bdb Mon Sep 17 00:00:00 2001 From: Zaets Volodymyr Date: Thu, 23 Jul 2015 10:43:19 +0300 Subject: [PATCH 12/60] MAGETWO-39100: [Code Coverage - M11] Increase JS code coverage S1 --- .../form/components/collection/item.test.js | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js new file mode 100644 index 0000000000000..bc2f08748f45e --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js @@ -0,0 +1,57 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'Magento_Ui/js/lib/events' +], function (EventBus) { + 'use strict'; + + var EVENT = 'testEvent'; + + describe('Magento_Ui/js/lib/events', function () { + describe('"on" method', function () { + afterEach(function () { + EventBus.off(EVENT); + }); + + it('calls passed callback when event is triggered', function () { + var callback = jasmine.createSpy(); + + EventBus.on(EVENT, callback); + + EventBus.trigger(EVENT); + + expect(callback).toHaveBeenCalled(); + }); + + it('calls callbacks in order they have been assigned', function () { + var expected = '', + firstCallback, + secondCallback; + + /** + * Test callback + */ + firstCallback = function () { + expected += 'one'; + }; + + /** + * Test callback + */ + secondCallback = function () { + expected += ' two'; + }; + + EventBus.on(EVENT, firstCallback); + EventBus.on(EVENT, secondCallback); + + EventBus.trigger(EVENT); + + expect(expected).toEqual('one two'); + }); + }); + }); +}); From dcd824e6409a9917ffe4ea0caa08241ed1f1c3fb Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Thu, 23 Jul 2015 10:43:46 +0300 Subject: [PATCH 13/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- app/design/adminhtml/Magento/backend/web/js/theme.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index ff53b81148084..c2499f8ef152f 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -132,7 +132,7 @@ define('globalNavigationScroll', [ submenuHeight = submenu.height(); - if (submenuHeight > menuHeight) { + if (submenuHeight > menuHeight && menuHeight > win.height()) { menu.css('height', submenuHeight); menuHeight = submenuHeight; } From 23eb60dac6a62ee2866d4a776c56f6735ecb3313 Mon Sep 17 00:00:00 2001 From: Zaets Volodymyr Date: Thu, 23 Jul 2015 11:44:19 +0300 Subject: [PATCH 14/60] MAGETWO-39100: [Code Coverage - M11] Increase JS code coverage S1 --- .../Ui/base/js/form/components/collection/item.test.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js index bc2f08748f45e..e28d5c98c4122 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js @@ -4,17 +4,15 @@ */ define([ - 'Magento_Ui/js/lib/events' -], function (EventBus) { + 'Magento_Ui/js/form/components/collection/item' +], function (constr) { 'use strict'; var EVENT = 'testEvent'; - describe('Magento_Ui/js/lib/events', function () { + describe('Magento_Ui/js/form/components/collection/item', function () { describe('"on" method', function () { - afterEach(function () { - EventBus.off(EVENT); - }); + console.info('asd' , new constr); it('calls passed callback when event is triggered', function () { var callback = jasmine.createSpy(); From 6b9108a5608f8109ba2c9d205ea2187d8611c6c1 Mon Sep 17 00:00:00 2001 From: Anton Guz Date: Thu, 23 Jul 2015 13:35:40 +0300 Subject: [PATCH 15/60] MAGETWO-40308: [GITHUB] admin external extjs.com requests #1483 - Fixed file encoding --- lib/web/extjs/defaults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/extjs/defaults.js b/lib/web/extjs/defaults.js index d4047c3ddf302..c47859dacb418 100644 --- a/lib/web/extjs/defaults.js +++ b/lib/web/extjs/defaults.js @@ -1,5 +1,5 @@ /** - * Copyright © 2015 Magento. All rights reserved. + * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ From 34df9e34ed02db79ff51e9646db18a2b806a0d75 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Thu, 23 Jul 2015 16:17:25 +0300 Subject: [PATCH 16/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll --- .../adminhtml/Magento/backend/web/js/theme.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index c2499f8ef152f..2abbc1da104ea 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -84,7 +84,7 @@ define('globalNavigationScroll', [ menu.css('top', -nextTop); - } else if (winTop < winTopLast) { // scroll up + } else if (winTop <= winTopLast) { // scroll up nextTop > -scrollStep ? nextTop += scrollStep : nextTop = 0; @@ -126,14 +126,20 @@ define('globalNavigationScroll', [ }); // Add event to menuItems to check submenu overlap - menuItems.on('click', function () { + menuItems.on('click', function (e) { - var submenu = $(this).children(subMenuClass); + var submenu = $(this).children(subMenuClass), + delta; submenuHeight = submenu.height(); - if (submenuHeight > menuHeight && menuHeight > win.height()) { - menu.css('height', submenuHeight); + if (submenuHeight > menuHeight && menuHeight > winHeight) { + menu.height(submenuHeight - $('.logo')[0].offsetHeight); + delta = -menu.position().top; + window.scrollTo(0, 0); + positionMenu(); + window.scrollTo(0, delta); + positionMenu(); menuHeight = submenuHeight; } From da5a14a4085088b5bfa210174b194fb9cfa28c1e Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Thu, 23 Jul 2015 19:11:51 +0300 Subject: [PATCH 17/60] MAGETWO-40654: Create MassActionNStep component --- .../Ui/view/base/web/js/grid/massactions.js | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js index 883ff1f018c31..78214cfae956f 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -3,6 +3,7 @@ * See COPYING.txt for license details. */ define([ + 'ko', 'underscore', 'uiRegistry', 'mageUtils', @@ -10,7 +11,7 @@ define([ 'Magento_Ui/js/modal/confirm', 'Magento_Ui/js/modal/alert', 'mage/translate' -], function (_, registry, utils, Collapsible, confirm, alert, $t) { +], function (ko, _, registry, utils, Collapsible, confirm, alert, $t) { 'use strict'; return Collapsible.extend({ @@ -33,9 +34,23 @@ define([ this._super() .observe('actions'); + this.recursiveObserveActions(this.actions()); + return this; }, - + /** + * Initializes observable actions. + * + * Chainable. + */ + recursiveObserveActions: function (actions) { + _.each(actions, function (action) { + if (action.actions) { + action.visible = ko.observable(false); + this.recursiveObserveActions(action.actions); + } + }.bind(this)); + }, /** * Applies specified action. * @@ -44,9 +59,15 @@ define([ */ applyAction: function (actionIndex) { var data = this.getSelections(), - action, + action = this.getAction(actionIndex), callback; + if (action.visible) { + action.visible(!action.visible()); + + return this; + } + if (!data.total) { alert({ content: this.noItemsMsg @@ -55,7 +76,6 @@ define([ return this; } - action = this.getAction(actionIndex), callback = this._getCallback(action, data); action.confirm ? @@ -122,7 +142,7 @@ define([ */ _getCallback: function (action, selections) { var callback = action.callback, - args = [action, selections]; + args = [action, selections]; if (utils.isObject(callback)) { args.unshift(callback.target); From adae07987a0edc2d7a31bc73682f5da86ede7f73 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Fri, 24 Jul 2015 11:18:42 +0300 Subject: [PATCH 18/60] MAGETWO-40654: Create MassActionNStep component --- app/code/Magento/Ui/view/base/web/js/grid/massactions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js index 78214cfae956f..fb3211a4dc986 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -41,15 +41,15 @@ define([ /** * Initializes observable actions. * - * Chainable. + * Recursive function */ recursiveObserveActions: function (actions) { - _.each(actions, function (action) { + _.each(actions, function (list, action, context) { if (action.actions) { action.visible = ko.observable(false); - this.recursiveObserveActions(action.actions); + context.recursiveObserveActions(action.actions); } - }.bind(this)); + }); }, /** * Applies specified action. From 96bcd417f43f26aecd4884862af9cf65aa72ea9a Mon Sep 17 00:00:00 2001 From: Bogdan Plieshka Date: Fri, 24 Jul 2015 12:40:37 +0300 Subject: [PATCH 19/60] MAGETWO-40279: Admin Navigation Menu has vertical scroll - Removed overlap fuctionality from submenu --- .../Magento_Backend/web/css/source/module/_menu.less | 7 ------- app/design/adminhtml/Magento/backend/web/js/theme.js | 7 ------- 2 files changed, 14 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less index c4dcfaa20e93b..f207c4c3d0cc0 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less @@ -229,13 +229,6 @@ transition-timing-function: ease-in-out; visibility: hidden; z-index: @submenu__z-index - 1; - &._overlap { - overflow-y: auto; - height: 100%; - &::-webkit-scrollbar { - width: 0; - } - } } &._show { > .submenu { diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 2abbc1da104ea..9d1524c4e2352 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -10,7 +10,6 @@ define('globalNavigationScroll', [ var win = $(window), subMenuClass = '.submenu', - overlapClassName = '_overlap', fixedClassName = '_fixed', menu = $('.menu-wrapper'), content = $('.page-wrapper'), @@ -118,8 +117,6 @@ define('globalNavigationScroll', [ // Reset position if fixed and out of smart scroll if ((menuHeight < contentHeight) && (menuHeight <= winHeight)) { menu.removeAttr('style'); - // Remove overlap classes from submenus and clear overlap adding event - subMenus.removeClass(overlapClassName); menuItems.off(); } @@ -142,10 +139,6 @@ define('globalNavigationScroll', [ positionMenu(); menuHeight = submenuHeight; } - - if (isMenuFixed() && (submenuHeight > winHeight)) { - checkAddClass(submenu, overlapClassName); - } }); }); From c884697c1fd7630c599b174d14165060ed0a380b Mon Sep 17 00:00:00 2001 From: vladimir zaets Date: Sun, 26 Jul 2015 20:52:02 +0300 Subject: [PATCH 20/60] MAGETWO-39100: [Code Coverage - M11] Increase JS code coverage S1 --- .../Magento/Ui/base/js/form/provider.test.js | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/provider.test.js diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/provider.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/provider.test.js new file mode 100644 index 0000000000000..63285e6119990 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/provider.test.js @@ -0,0 +1,101 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/provider' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/provider', function () { + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }), + originalClient = obj.client, + originalClientSave = originalClient.save; + describe('"initialize" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initialize')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initialize); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initialize()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initialize()); + + expect(type).toEqual('object'); + }); + }); + describe('"initClient" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initClient')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initClient); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initClient()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initClient()); + + expect(type).toEqual('object'); + }); + it('Check returned value type if method called without arguments', function () { + obj.client = null; + expect(typeof(obj.client)).toEqual('object'); + }); + }); + describe('"save" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('save')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.save); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + obj.client = originalClient; + obj.client.save = jasmine.createSpy(); + expect(obj.save()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.save()); + + expect(type).toEqual('object'); + }); + it('Check call method "this.get" inner save method', function () { + obj.get = jasmine.createSpy(); + obj.save(); + expect(obj.get).toHaveBeenCalled(); + }); + it('Check call method "this.client.save" inner save method', function () { + obj.get = jasmine.createSpy(); + obj.save(); + expect(obj.client.save).toHaveBeenCalled(); + }); + }); + }); +}); From 47e176bfefa632bc89f13a6c181a8418098cf548 Mon Sep 17 00:00:00 2001 From: vladimir zaets Date: Sun, 26 Jul 2015 20:53:10 +0300 Subject: [PATCH 21/60] MAGETWO-39100: [Code Coverage - M11] Increase JS code coverage S1 --- .../Magento/Ui/base/js/form/adapter.test.js | 23 ++ .../Magento/Ui/base/js/form/client.test.js | 67 +++++ .../Ui/base/js/form/components/area.test.js | 115 +++++++++ .../js/form/components/collection.test.js | 169 ++++++++++++ .../form/components/collection/item.test.js | 241 ++++++++++++++++-- .../Ui/base/js/form/components/group.test.js | 114 +++++++++ .../Ui/base/js/form/components/html.test.js | 223 ++++++++++++++++ .../Ui/base/js/form/components/tab.test.js | 92 +++++++ .../base/js/form/components/tab_group.test.js | 146 +++++++++++ .../code/Magento/Ui/base/js/form/form.test.js | 165 ++++++++++++ 10 files changed, 1327 insertions(+), 28 deletions(-) create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/adapter.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/area.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/group.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/html.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/adapter.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/adapter.test.js new file mode 100644 index 0000000000000..70fb014f272f5 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/adapter.test.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'Magento_Ui/js/form/adapter' +], function (obj) { + 'use strict'; + + describe('Magento_Ui/js/form/adapter', function () { + describe('"on" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('on')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.on); + + expect(type).toEqual('function'); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js new file mode 100644 index 0000000000000..331af04d840d0 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js @@ -0,0 +1,67 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/client' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/client', function () { + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + describe('"save" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('save')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.save); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + obj.urls = {}; + obj.urls.beforeSave = {}; + expect(obj.save()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.save()); + + expect(type).toEqual('object'); + }); + }); + describe('"initialize" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initialize')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initialize); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initialize()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initialize()); + + expect(type).toEqual('object'); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/area.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/area.test.js new file mode 100644 index 0000000000000..5c6f393aaeb3d --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/area.test.js @@ -0,0 +1,115 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/components/area' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/components/area', function () { + + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initObservable" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initObservable')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initObservable); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initObservable()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initObservable()); + + expect(type).toEqual('object'); + }); + it('Check called "this.observe" method', function () { + obj.observe = jasmine.createSpy(); + obj.initObservable(); + expect(obj.observe).toHaveBeenCalled(); + }); + }); + describe('"initElement" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initElement')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initElement); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with object argument', function () { + var arg = { + initContainer: function () { + }, + on: function() { + } + }; + + expect(obj.initElement(arg)).toBeDefined(); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + initContainer: function () { + }, + on: function() { + } + }, + type = typeof(obj.initElement(arg)); + + expect(type).toEqual('object'); + }); + }); + describe('"onChildrenUpdate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('onChildrenUpdate')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.onChildrenUpdate); + + expect(type).toEqual('function'); + }); + it('Check called "this.delegate" method ', function () { + obj.delegate = jasmine.createSpy(); + obj.onChildrenUpdate(); + expect(obj.delegate).toHaveBeenCalled(); + }); + }); + describe('"onContentLoading" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('onContentLoading')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.onContentLoading); + + expect(type).toEqual('function'); + }); + it('Try called', function () { + obj.onContentLoading = jasmine.createSpy(); + obj.onContentLoading(); + expect(obj.onContentLoading).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection.test.js new file mode 100644 index 0000000000000..84f47124df290 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection.test.js @@ -0,0 +1,169 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/components/collection' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/components/collection', function () { + + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initElement" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initElement')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initElement); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with object arguments', function () { + var arg = { + initContainer: function () { + }, + activate: function () { + + } + }; + + expect(obj.initElement(arg)).toBeDefined(); + }); + it('Check returned value type if method called object arguments', function () { + var arg = { + initContainer: function () { + }, + activate: function () { + } + }, + type = typeof(obj.initElement(arg)); + + expect(type).toEqual('object'); + }); + it('Check call method "this.bubble" inner initElement method', function () { + var arg = { + initContainer: function () { + }, + activate: function () { + } + }; + obj.bubble = jasmine.createSpy(); + obj.initElement(arg) + expect(obj.bubble).toHaveBeenCalled(); + }); + }); + describe('"initChildren" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initChildren')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initChildren); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initChildren()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initChildren()); + + expect(type).toEqual('object'); + }); + it('Check call method "this.source.get" inner initElement method', function () { + obj.source.get = jasmine.createSpy(); + obj.initChildren(); + expect(obj.source.get).toHaveBeenCalled(); + }); + it('Check this.initialItems property affter called initChildren', function () { + obj.initialItems = null; + obj.initChildren(); + expect(obj.initialItems).toEqual([]); + }); + }); + describe('"addChild" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('addChild')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.addChild); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with arguments', function () { + expect(obj.addChild()).toBeDefined(); + }); + it('Check returned value type if method called with arguments', function () { + var type = typeof(obj.addChild()); + + expect(type).toEqual('object'); + }); + it('Check this.childIndex property affter called addChild', function () { + obj.childIndex = null; + obj.addChild('4'); + expect(obj.childIndex).toEqual('4'); + }); + }); + describe('"hasChanged" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('hasChanged')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.hasChanged); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.hasChanged()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.hasChanged()); + + expect(type).toEqual('boolean'); + }); + }); + describe('"validate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('validate')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.validate); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.validate()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + expect(obj.validate()).toEqual([]); + }); + }); + describe('"removeAddress" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('removeAddress')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.removeAddress); + + expect(type).toEqual('function'); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js index e28d5c98c4122..5fe0e656d1fd0 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js @@ -4,51 +4,236 @@ */ define([ + 'underscore', + 'uiRegistry', 'Magento_Ui/js/form/components/collection/item' -], function (constr) { +], function (_, registry, constr) { 'use strict'; - var EVENT = 'testEvent'; - describe('Magento_Ui/js/form/components/collection/item', function () { - describe('"on" method', function () { - console.info('asd' , new constr); - it('calls passed callback when event is triggered', function () { - var callback = jasmine.createSpy(); + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initProperties" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initProperties')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initProperties); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initProperties()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initProperties()); + + expect(type).toEqual('object'); + }); + it('Check "displayed" property', function () { + obj.displayed = null; + obj.initProperties(); + expect(obj.displayed).toEqual([]); + }); + }); + describe('"initObservable" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initObservable')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initObservable); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initObservable()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initObservable()); + + expect(type).toEqual('object'); + }); + it('Check called "this.observe" method', function () { + obj.observe = jasmine.createSpy(); + obj.initObservable(); + expect(obj.observe).toHaveBeenCalled(); + }); + }); + describe('"initElement" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initElement')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initElement); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with object argument', function () { + var arg = { + initContainer: function () { + } + }; + + expect(obj.initElement(arg)).toBeDefined(); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + initContainer: function () { + } + }, + type = typeof(obj.initElement(arg)); + + expect(type).toEqual('object'); + }); + it('Check called "this.insertToIndexed" method with object argument', function () { + var arg = { + initContainer: function () { + } + }; + + obj.insertToIndexed = jasmine.createSpy(); + obj.initElement(arg); + expect(obj.insertToIndexed).toHaveBeenCalledWith(arg); + }); + }); + describe('"insertToIndexed" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('insertToIndexed')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.insertToIndexed); - EventBus.on(EVENT, callback); + expect(type).toEqual('function'); + }); + it('Check called "insertToIndexed" method with object argument', function () { + var arg = { + initContainer: function () { + } + }; - EventBus.trigger(EVENT); + obj.insertToIndexed(arg); + expect(obj.insertToIndexed).toHaveBeenCalledWith(arg); + }); + }); + describe('"formatPreviews" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('formatPreviews')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.formatPreviews); - expect(callback).toHaveBeenCalled(); + expect(type).toEqual('function'); }); + it('Check returned value if call method with array arguments', function () { + expect(obj.formatPreviews(['1', '2', '3'])).toEqual([{ + "items": ["1"], + "separator": " ", + "prefix": "" + }, {"items": ["2"], "separator": " ", "prefix": ""}, { + "items": ["3"], + "separator": " ", + "prefix": "" + }] + ); + }); + }); + describe('"buildPreview" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('buildPreview')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.buildPreview); - it('calls callbacks in order they have been assigned', function () { - var expected = '', - firstCallback, - secondCallback; + expect(type).toEqual('function'); + }); + it('Check returned value if method called with object argument', function () { + var arg = { + items: [], + prefix: 'magento' + }; - /** - * Test callback - */ - firstCallback = function () { - expected += 'one'; + expect(obj.buildPreview(arg)).toBeDefined(); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + items: [], + prefix: 'magento' + }, + type = typeof(obj.buildPreview(arg)); + + expect(type).toEqual('string'); + }); + it('Check called "this.getPreview" method with object argument', function () { + var arg = { + items: [], + prefix: 'magento' }; - /** - * Test callback - */ - secondCallback = function () { - expected += ' two'; + obj.getPreview = jasmine.createSpy().and.callFake(function() { return []; }); + obj.buildPreview(arg); + expect(obj.getPreview).toHaveBeenCalledWith(arg.items); + }); + }); + describe('"hasPreview" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('hasPreview')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.hasPreview); + + expect(type).toEqual('function'); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + items: [], + prefix: 'magento' + }, + type = typeof(obj.hasPreview(arg)); + + expect(type).toEqual('boolean'); + }); + it('Check called "this.getPreview" method with object argument', function () { + var arg = { + items: [], + prefix: 'magento' }; - EventBus.on(EVENT, firstCallback); - EventBus.on(EVENT, secondCallback); + obj.getPreview = jasmine.createSpy().and.callFake(function() { return []; }); + obj.hasPreview(arg); + expect(obj.getPreview).toHaveBeenCalledWith(arg.items); + }); + }); + describe('"getPreview" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('getPreview')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.getPreview); - EventBus.trigger(EVENT); + expect(type).toEqual('function'); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + items: [], + prefix: 'magento' + }, + type = typeof(obj.getPreview(arg)); - expect(expected).toEqual('one two'); + expect(type).toEqual('object'); }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/group.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/group.test.js new file mode 100644 index 0000000000000..1cee6e7a5735f --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/group.test.js @@ -0,0 +1,114 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/components/group' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/components/group', function () { + + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initObservable" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initObservable')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initObservable); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initObservable()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initObservable()); + + expect(type).toEqual('object'); + }); + it('Check called "this.observe" method', function () { + obj.observe = jasmine.createSpy().and.callFake(function() { return obj; }); + obj.initObservable(); + expect(obj.observe).toHaveBeenCalled(); + }); + }); + describe('"isSingle" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('isSingle')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.isSingle); + + expect(type).toEqual('function'); + }); + it('Check returned value if this.elems.getLength return 1', function () { + obj.elems.getLength = jasmine.createSpy().and.callFake(function() { return 1; }); + + expect(obj.isSingle()).toEqual(true); + }); + it('Check returned value if this.elems.getLength return not 1', function () { + obj.elems.getLength = jasmine.createSpy().and.callFake(function() { return 2; }); + + expect(obj.isSingle()).toEqual(false); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.isSingle()); + + expect(type).toEqual('boolean'); + }); + it('Check called "this.observe" method', function () { + obj.elems.getLength = jasmine.createSpy().and.callFake(function() { return 1; }); + obj.isSingle(); + expect(obj.elems.getLength).toHaveBeenCalled(); + }); + }); + describe('"isMultiple" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('isMultiple')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.isMultiple); + + expect(type).toEqual('function'); + }); + it('Check returned value if this.elems.getLength return more 1', function () { + obj.elems.getLength = jasmine.createSpy().and.callFake(function() { return 4; }); + + expect(obj.isMultiple()).toEqual(true); + }); + it('Check returned value if this.elems.getLength return 1 or less', function () { + obj.elems.getLength = jasmine.createSpy().and.callFake(function() { return 1; }); + + expect(obj.isMultiple()).toEqual(false); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.isMultiple()); + + expect(type).toEqual('boolean'); + }); + it('Check called "this.observe" method', function () { + obj.elems.getLength = jasmine.createSpy().and.callFake(function() { return 1; }); + obj.isMultiple(); + expect(obj.elems.getLength).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/html.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/html.test.js new file mode 100644 index 0000000000000..8ce23d0411d56 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/html.test.js @@ -0,0 +1,223 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/components/html' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/components/html', function () { + window.FORM_KEY = 'magentoFormKey'; + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initObservable" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initObservable')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initObservable); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initObservable()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initObservable()); + + expect(type).toEqual('object'); + }); + it('Check called "this.observe" method', function () { + obj.observe = jasmine.createSpy().and.callFake(function() { return obj; }); + obj.initObservable(); + expect(obj.observe).toHaveBeenCalled(); + }); + }); + describe('"initContainer" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initContainer')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initContainer); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with arguments', function () { + var parent = { + on: jasmine.createSpy() + }; + + expect(obj.initContainer(parent)).toBeDefined(); + }); + it('Check returned value type if method called with arguments', function () { + var parent = { + on: jasmine.createSpy() + }, + type = typeof(obj.initContainer(parent)); + + expect(type).toEqual('object'); + }); + it('Check called "arguments.on" method inner "initContainer" method', function () { + var parent = { + on: jasmine.createSpy() + }; + + obj.initContainer(parent); + expect(parent.on).toHaveBeenCalled(); + }); + }); + describe('"initAjaxConfig" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initAjaxConfig')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initAjaxConfig); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initAjaxConfig()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initAjaxConfig()); + + expect(type).toEqual('object'); + }); + it('Check url property', function () { + obj.ajaxConfig = null; + obj.url = 'magento'; + + obj.initAjaxConfig(); + expect(obj.ajaxConfig.url).toEqual(obj.url); + }); + it('Check FORM_KEY property', function () { + obj.ajaxConfig = null; + + obj.initAjaxConfig(); + expect(obj.ajaxConfig.data.FORM_KEY).toEqual(window.FORM_KEY); + }); + it('Check success property', function () { + obj.ajaxConfig = null; + + obj.initAjaxConfig(); + expect(typeof(obj.ajaxConfig.success)).toEqual('function'); + }); + }); + describe('"onContainerToggle" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('onContainerToggle')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.onContainerToggle); + + expect(type).toEqual('function'); + }); + it('Check call method "this.shouldLoad" inner onContainerToggle method', function () { + obj.shouldLoad = jasmine.createSpy().and.callFake(function() {return true;}); + + obj.onContainerToggle(true); + expect(obj.shouldLoad).toHaveBeenCalled(); + }); + it('Check call method "this.loadData" inner onContainerToggle method', function () { + obj.shouldLoad = jasmine.createSpy().and.callFake(function() {return true;}); + obj.loadData = jasmine.createSpy().and.callFake(function() {return true;}); + + obj.onContainerToggle(true); + expect(obj.loadData).toHaveBeenCalled(); + }); + }); + describe('"hasData" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('hasData')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.hasData); + + expect(type).toEqual('function'); + }); + it('Check returned type', function () { + var type = typeof(obj.hasData()); + + expect(type).toEqual('boolean'); + }); + }); + describe('"shouldLoad" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('shouldLoad')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.shouldLoad); + + expect(type).toEqual('function'); + }); + it('Check returned type', function () { + var type = typeof(obj.shouldLoad()); + + expect(type).toEqual('boolean'); + }); + }); + describe('"loadData" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('loadData')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.loadData); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.loadData()).toBeDefined(); + }); + }); + describe('"onDataLoaded" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('onDataLoaded')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.onDataLoaded); + + expect(type).toEqual('function'); + }); + it('Check call method "this.updateContent" inner onDataLoaded method', function () { + var data = 'magento'; + + obj.updateContent = jasmine.createSpy().and.callFake(function() {return obj;}); + obj.onDataLoaded(data); + expect(obj.loadData).toHaveBeenCalled(); + }); + }); + describe('"updateContent" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('updateContent')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.updateContent); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.updateContent()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + expect(typeof(obj.updateContent())).toEqual('object'); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js new file mode 100644 index 0000000000000..0f22e00fd8d90 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js @@ -0,0 +1,92 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/components/tab' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/components/tab', function () { + window.FORM_KEY = 'magentoFormKey'; + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initObservable" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initObservable')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initObservable); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initObservable()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initObservable()); + + expect(type).toEqual('object'); + }); + it('Check called "this.observe" method', function () { + obj.observe = jasmine.createSpy().and.callFake(function() { return obj; }); + obj.initObservable(); + expect(obj.observe).toHaveBeenCalled(); + }); + }); + describe('"onUniqueUpdate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('onUniqueUpdate')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.onUniqueUpdate); + + expect(type).toEqual('function'); + }); + it('Check called "this.trigger" inner onUniqueUpdate method', function () { + obj.trigger = jasmine.createSpy().and.callFake(function() { return obj; }); + obj.onUniqueUpdate(); + expect(obj.trigger).toHaveBeenCalled(); + }); + }); + describe('"activate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('activate')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.activate); + + expect(type).toEqual('function'); + }); + it('Check called "this.setUnique" inner activate method', function () { + obj.setUnique = jasmine.createSpy().and.callFake(function() { return obj; }); + obj.activate(); + expect(obj.setUnique).toHaveBeenCalled(); + }); + it('Check observable variable "active" after execution activate method', function () { + obj.activate(); + expect(obj.active()).toEqual(true); + }); + it('Check observable variable "wasActivated" after execution activate method', function () { + obj.activate(); + expect(obj.wasActivated()).toEqual(true); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js new file mode 100644 index 0000000000000..e3e5711f299a8 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js @@ -0,0 +1,146 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/components/tab_group' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/components/tab_group', function () { + window.FORM_KEY = 'magentoFormKey'; + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + + describe('"initElement" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initElement')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initElement); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with object argument', function () { + var arg = { + initContainer: function () { + }, + on: function () { + }, + active: function () { + } + }; + + expect(obj.initElement(arg)).toBeDefined(); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + initContainer: function () { + }, + on: function () { + }, + active: function () { + } + }, + type = typeof(obj.initElement(arg)); + + expect(type).toEqual('object'); + }); + }); + describe('"initActivation" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initActivation')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.initActivation); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called with object argument', function () { + var arg = { + initContainer: function () { + }, + on: function () { + }, + active: function () { + } + }; + + expect(obj.initActivation(arg)).toBeDefined(); + }); + it('Check returned value type if method called with object argument', function () { + var arg = { + initContainer: function () { + }, + on: function () { + }, + active: function () { + } + }, + type = typeof(obj.initActivation(arg)); + + expect(type).toEqual('object'); + }); + }); + describe('"validate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('validate')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.validate); + + expect(type).toEqual('function'); + }); + it('Check called "argument.delegate" inner validate method', function () { + var arg = { + initContainer: function () { + }, + on: function () { + }, + active: function () { + }, + delegate: jasmine.createSpy() + }; + + obj.validate(arg); + expect(arg.delegate).toHaveBeenCalled(); + }); + }); + describe('"onValidate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('onValidate')).toBeDefined(); + }); + it('Check answer type', function () { + var type = typeof(obj.onValidate); + + expect(type).toEqual('function'); + }); + it('Check called "this.elems.sortBy" inner onValidate method', function () { + obj.elems.sortBy = jasmine.createSpy().and.callFake(function() { return []; }); + obj.onValidate(); + expect(obj.elems.sortBy).toHaveBeenCalled(); + }); + it('Check called "this.validate" in onValidate and count calls', function () { + obj.elems.sortBy = jasmine.createSpy().and.callFake(function() { return ['1', '2', '3']; }); + obj.validate = jasmine.createSpy().and.callFake(function() { return []; }); + obj.onValidate(); + expect(obj.validate.calls.count()).toBe(3); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js new file mode 100644 index 0000000000000..2a3ddef5eb776 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js @@ -0,0 +1,165 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + 'Magento_Ui/js/form/form' +], function (_, registry, constr) { + 'use strict'; + + describe('Magento_Ui/js/form/form', function () { + registry.set('provName', { + on: function () { + }, + get: function () { + }, + set: function () { + } + }); + + var obj = new constr({ + provider: 'provName', + name: '', + index: '' + }); + describe('"initAdapter" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initAdapter')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.save); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initAdapter()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initAdapter()); + + expect(type).toEqual('object'); + }); + }); + describe('"initialize" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initialize')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initialize); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initialize()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initialize()); + + expect(type).toEqual('object'); + }); + }); + describe('"initProperties" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('initProperties')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.initProperties); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.initProperties()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.initProperties()); + + expect(type).toEqual('object'); + }); + it('Check this.selector property (is modify in initProperties method)', function () { + obj.selector = null; + obj.initProperties(); + expect(typeof(obj.selector)).toEqual('string'); + }); + }); + describe('"hideLoader" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('hideLoader')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.hideLoader); + + expect(type).toEqual('function'); + }); + it('Check returned value if method called without arguments', function () { + expect(obj.hideLoader()).toBeDefined(); + }); + it('Check returned value type if method called without arguments', function () { + var type = typeof(obj.hideLoader()); + + expect(type).toEqual('object'); + }); + }); + describe('"save" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('save')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.save); + + expect(type).toEqual('function'); + }); + it('Check call method "this.validate" inner save method', function () { + obj.validate = jasmine.createSpy(); + obj.source.get = jasmine.createSpy().and.callFake(function() { return true; }); + obj.save(); + expect(obj.validate).toHaveBeenCalled(); + }); + it('Check call method "this.source.get" inner save method', function () { + obj.validate = jasmine.createSpy(); + obj.source.get = jasmine.createSpy().and.callFake(function() { return true; }); + obj.save(); + expect(obj.source.get).toHaveBeenCalled(); + }); + it('Check call method "this.submit" inner save method', function () { + obj.validate = jasmine.createSpy(); + obj.source.get = jasmine.createSpy().and.callFake(function() { return false; }); + obj.submit = jasmine.createSpy().and.callFake(function() { return true; }); + obj.save(); + expect(obj.source.get).toHaveBeenCalled(); + }); + }); + describe('"submit" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('submit')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.submit); + + expect(type).toEqual('function'); + }); + }); + describe('"validate" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('validate')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.validate); + + expect(type).toEqual('function'); + }); + }); + describe('"reset" method', function () { + it('Check for defined ', function () { + expect(obj.hasOwnProperty('reset')).toBeDefined(); + }); + it('Check method type', function () { + var type = typeof(obj.reset); + + expect(type).toEqual('function'); + }); + }); + }); +}); From 233a9a6f09e3f0ce733f866ebd9064ec186149b5 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Mon, 27 Jul 2015 13:48:03 +0300 Subject: [PATCH 22/60] MAGETWO-40655: Create templates to support recursive rendering, expanding groups --- .../ui_component/product_listing.xml | 18 ++- .../Ui/view/base/web/js/grid/massactions.js | 30 +--- .../view/base/web/js/grid/tree-massactions.js | 129 ++++++++++++++++++ .../view/base/web/templates/grid/submenu.html | 22 +++ .../web/templates/grid/tree-massactions.html | 33 +++++ .../backend/web/css/source/_actions.less | 12 ++ dev/tools/grunt/tasks/static.js | 2 +- 7 files changed, 217 insertions(+), 29 deletions(-) create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/submenu.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index a779fd63c55f2..c375e94de8ca2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -191,6 +191,7 @@ product_listing.product_listing.product_columns.ids + Magento_Ui/js/grid/tree-massactions bottom @@ -202,12 +203,23 @@ Delete catalog/product/massDelete - + status Change status - catalog/*/massStatus + + + enable + Enable + catalog/product/massEnable + + + disable + Disable + catalog/product/massDisable + + - + attributes Update attributes catalog/product_action_attribute/edit diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js index fb3211a4dc986..0b6b802f123a1 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -3,7 +3,6 @@ * See COPYING.txt for license details. */ define([ - 'ko', 'underscore', 'uiRegistry', 'mageUtils', @@ -11,7 +10,7 @@ define([ 'Magento_Ui/js/modal/confirm', 'Magento_Ui/js/modal/alert', 'mage/translate' -], function (ko, _, registry, utils, Collapsible, confirm, alert, $t) { +], function (_, registry, utils, Collapsible, confirm, alert, $t) { 'use strict'; return Collapsible.extend({ @@ -34,23 +33,9 @@ define([ this._super() .observe('actions'); - this.recursiveObserveActions(this.actions()); - return this; }, - /** - * Initializes observable actions. - * - * Recursive function - */ - recursiveObserveActions: function (actions) { - _.each(actions, function (list, action, context) { - if (action.actions) { - action.visible = ko.observable(false); - context.recursiveObserveActions(action.actions); - } - }); - }, + /** * Applies specified action. * @@ -59,15 +44,9 @@ define([ */ applyAction: function (actionIndex) { var data = this.getSelections(), - action = this.getAction(actionIndex), + action, callback; - if (action.visible) { - action.visible(!action.visible()); - - return this; - } - if (!data.total) { alert({ content: this.noItemsMsg @@ -76,6 +55,7 @@ define([ return this; } + action = this.getAction(actionIndex); callback = this._getCallback(action, data); action.confirm ? @@ -142,7 +122,7 @@ define([ */ _getCallback: function (action, selections) { var callback = action.callback, - args = [action, selections]; + args = [action, selections]; if (utils.isObject(callback)) { args.unshift(callback.target); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js new file mode 100644 index 0000000000000..0472a9184b3d9 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js @@ -0,0 +1,129 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'ko', + 'underscore', + 'Magento_Ui/js/grid/massactions' +], function (ko, _, Massactions) { + 'use strict'; + + return Massactions.extend({ + defaults: { + template: 'ui/grid/tree-massactions', + submenuTemplate: 'ui/grid/submenu', + selectProvider: '', + modules: { + selections: '${ $.selectProvider }' + }, + listens: { + opened: 'hideSubmenus' + } + }, + + /** + * Initializes observable properties. + * + * @returns {Massactions} Chainable. + */ + initObservable: function () { + this._super() + .recursiveObserveActions(this.actions()); + + return this; + }, + + /** + * Recursive initializes observable actions. + * + * @param {Array} actions - Action objects. + * @returns {Massactions} Chainable. + */ + recursiveObserveActions: function (actions) { + _.each(actions, function (action) { + if (action.actions) { + action.visible = ko.observable(false); + action.parent = actions; + this.recursiveObserveActions(action.actions); + } + }, this); + + return this; + }, + + /** + * Applies specified action. + * + * @param {String} actionIndex - Actions' identifier. + * @returns {Massactions} Chainable. + */ + applyAction: function (actionIndex) { + var action = this.getAction(actionIndex), + visibility; + + if (action.visible) { + visibility = action.visible(); + + this.hideSubmenus(action.parent); + action.visible(!visibility); + + return this; + } + + return this._super(actionIndex); + }, + + /** + * Retrieves action object associated with a specified index. + * + * @param {String} actionIndex - Actions' identifier. + * @param {Array} actions - Action objects. + * @returns {Object} Action object. + */ + getAction: function (actionIndex, actions) { + var currentActions = actions || this.actions(), + result = false; + + _.find(currentActions, function (action) { + if (action.type === actionIndex) { + result = action; + + return true; + } + + if (action.actions) { + result = this.getAction(actionIndex, action.actions); + + return result; + } + }, this); + + return result; + + }, + + /** + * Recursive hide all sub folders in given array. + * + * @param {Array} actions - Action objects. + * @returns {Massactions} Chainable. + */ + hideSubmenus: function (actions) { + var currentActions = actions || this.actions(); + + _.each(currentActions, function (action) { + if (action.visible && action.visible()) { + action.visible(false); + } + + if (action.actions) { + this.hideSubmenus(action.actions); + } + }, this); + + return this; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html b/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html new file mode 100644 index 0000000000000..f9460305c0d63 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html @@ -0,0 +1,22 @@ + + +
    +
  • + + + + + +
  • +
diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html b/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html new file mode 100644 index 0000000000000..71bee895caeff --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html @@ -0,0 +1,33 @@ + +
+
+ +
    +
  • + + + + + + +
  • +
+
+
diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_actions.less b/app/design/adminhtml/Magento/backend/web/css/source/_actions.less index 99d3f60854103..6d00627722d38 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_actions.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_actions.less @@ -390,6 +390,7 @@ button { .appearing__on(); } > li { + position: relative; display: block; border: none; // ToDo UI: Should be deleted with old styles padding: 0; @@ -399,6 +400,9 @@ button { text-decoration: none; } } + &._visible-submenu { + background-color: @action-menu__hover__background-color; + } &:hover { background-color: @action-menu__hover__background-color; } @@ -412,6 +416,14 @@ button { padding: .6875em 1em; cursor: pointer; } + .action-submenu { + &:extend(.action-menu all); + position: absolute; + top: 0; + right: auto; + left: 100%; + margin-top: -1px; + } a { &.action-menu-item { color: @text__color; diff --git a/dev/tools/grunt/tasks/static.js b/dev/tools/grunt/tasks/static.js index 433e7a2b161f3..7cd6b2c8ce976 100644 --- a/dev/tools/grunt/tasks/static.js +++ b/dev/tools/grunt/tasks/static.js @@ -29,7 +29,7 @@ module.exports = function (grunt) { grunt.option('force', true); grunt.task.run(tasks); - if (!grunt.option('path')) { + if (!grunt.option('file')) { fs.unlinkSync(pc.static.tmp); } }); From 48f32383c060225f88f4552ec8f6eb3a776883b6 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Mon, 27 Jul 2015 15:26:08 +0300 Subject: [PATCH 23/60] MAGETWO-40655: Create templates to support recursive rendering, expanding groups --- app/code/Magento/Ui/view/base/web/templates/grid/submenu.html | 2 +- .../Ui/view/base/web/templates/grid/tree-massactions.html | 2 +- .../adminhtml/Magento/backend/web/css/source/_actions.less | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html b/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html index f9460305c0d63..8cd8cc6592960 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/submenu.html @@ -9,7 +9,7 @@ class="action-submenu" data-bind="foreach: {data: action.actions, as: 'action'}, css: { _active: action.visible }"> -
  • +
  • -
  • +
  • Date: Tue, 28 Jul 2015 10:35:27 +0300 Subject: [PATCH 27/60] MAGETWO-40657: Cover code w. unit tests --- .../code/Magento/Ui/base/js/grid/tree-massactions.test.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/tree-massactions.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/tree-massactions.test.js index fbbe63ab94c7a..2396898adb227 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/tree-massactions.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/tree-massactions.test.js @@ -3,11 +3,6 @@ * See COPYING.txt for license details. */ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - /*eslint max-nested-callbacks: 0*/ /*jscs:disable requirePaddingNewLinesInObjects*/ From bf0442e315ffb900fb0b73faab7a810338d5e601 Mon Sep 17 00:00:00 2001 From: Zaets Volodymyr Date: Tue, 28 Jul 2015 12:59:34 +0300 Subject: [PATCH 28/60] MAGETWO-40668: Replace all entries of $t wrapper --- .../payment/authorizenet-directpost.html | 2 +- .../payment/braintree-paypal-form.html | 2 +- .../web/template/payment/cc-form.html | 18 +++++------ .../web/template/checkout/captcha.html | 6 ++-- .../frontend/templates/cart/minicart.phtml | 2 +- .../frontend/web/template/authentication.html | 12 +++---- .../web/template/billing-address.html | 6 ++-- .../web/template/billing-address/details.html | 2 +- .../web/template/billing-address/form.html | 2 +- .../web/template/billing-address/list.html | 2 +- .../frontend/web/template/estimation.html | 4 +-- .../web/template/minicart/content.html | 16 +++++----- .../web/template/minicart/item/default.html | 16 +++++----- .../web/template/minicart/subtotal.html | 2 +- .../web/template/payment-methods/list.html | 2 +- .../view/frontend/web/template/payment.html | 4 +-- .../frontend/web/template/progress-bar.html | 2 +- .../frontend/web/template/registration.html | 6 ++-- .../web/template/review/actions/default.html | 6 ++-- .../address-renderer/default.html | 4 +-- .../web/template/shipping-address/form.html | 2 +- .../web/template/shipping-information.html | 10 +++--- .../view/frontend/web/template/shipping.html | 24 +++++++------- .../view/frontend/web/template/summary.html | 2 +- .../web/template/summary/cart-items.html | 4 +-- .../web/template/summary/grand-total.html | 2 +- .../web/template/summary/item/details.html | 10 +++--- .../web/template/summary/shipping.html | 8 ++--- .../web/template/summary/subtotal.html | 2 +- .../frontend/web/template/summary/totals.html | 2 +- .../payment/checkout-agreements-link.html | 6 ++-- .../catalog/product/edit/super/matrix.phtml | 4 +-- .../web/template/authentication-popup.html | 22 ++++++------- .../frontend/web/template/customer-email.html | 12 +++---- .../web/template/gift-message-form.html | 12 +++---- .../web/template/gift-message-item-level.html | 8 ++--- .../frontend/web/template/gift-message.html | 8 ++--- .../web/template/payment/banktransfer.html | 2 +- .../web/template/payment/cashondelivery.html | 2 +- .../web/template/payment/checkmo.html | 8 ++--- .../template/payment/purchaseorder-form.html | 4 +-- .../web/template/payment/cc-form.html | 18 +++++------ .../frontend/web/template/payment/free.html | 2 +- .../frontend/web/template/payment/iframe.html | 6 ++-- .../payment/express/billing-agreement.html | 2 +- .../web/template/payment/iframe-methods.html | 4 +-- .../template/payment/payflow-express-bml.html | 6 ++-- .../web/template/payment/payflow-express.html | 6 ++-- .../web/template/payment/payflowpro-form.html | 2 +- .../template/payment/paypal-express-bml.html | 6 ++-- .../web/template/payment/paypal-express.html | 6 ++-- .../paypal_billing_agreement-form.html | 2 +- .../frontend/web/template/remember-me.html | 6 ++-- .../web/template/payment/discount.html | 8 ++--- .../checkout/shipping/shipping-policy.html | 2 +- .../checkout/summary/grand-total.html | 8 ++--- .../template/checkout/summary/shipping.html | 32 +++++++++---------- .../template/checkout/summary/subtotal.html | 12 +++---- .../web/template/checkout/summary/tax.html | 12 +++---- .../view/base/web/templates/grid/actions.html | 4 +-- .../web/templates/grid/cells/actions.html | 2 +- .../templates/grid/columns/multiselect.html | 2 +- .../grid/controls/bookmarks/bookmarks.html | 4 +-- .../grid/controls/bookmarks/view.html | 6 ++-- .../web/templates/grid/controls/columns.html | 6 ++-- .../base/web/templates/grid/dnd/listing.html | 2 +- .../base/web/templates/grid/exportButton.html | 6 ++-- .../web/templates/grid/filters/chips.html | 6 ++-- .../web/templates/grid/filters/filters.html | 8 ++--- .../view/base/web/templates/grid/listing.html | 2 +- .../web/templates/grid/search/search.html | 2 +- .../Ui/view/base/web/templates/tab.html | 2 +- 72 files changed, 231 insertions(+), 231 deletions(-) diff --git a/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html b/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html index e596ced5d7834..170de87cfd767 100644 --- a/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html +++ b/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html @@ -61,7 +61,7 @@ " class="action primary checkout" disabled> - + diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/braintree-paypal-form.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/braintree-paypal-form.html index 149e1bdfd5420..0d009a345871a 100644 --- a/app/code/Magento/Braintree/view/frontend/web/template/payment/braintree-paypal-form.html +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/braintree-paypal-form.html @@ -41,7 +41,7 @@ " class="action primary checkout" disabled> - + diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/cc-form.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/cc-form.html index 8073eb00f64e4..748133c319757 100644 --- a/app/code/Magento/Braintree/view/frontend/web/template/payment/cc-form.html +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/cc-form.html @@ -36,12 +36,12 @@
    -
    +
    @@ -148,7 +148,7 @@
    - +
    @@ -212,7 +212,7 @@ css: {disabled: !isPlaceOrderActionAllowed()} " disabled> - +
    diff --git a/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html b/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html index 3b294d904b2cb..0282f24e480da 100644 --- a/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html +++ b/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html @@ -6,7 +6,7 @@ -->
    - +
    @@ -20,12 +20,12 @@ }" class="captcha-img"/>
    -
    +
    diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml index 6f05b3b6a4cb5..2dc516c80d005 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml @@ -19,7 +19,7 @@ - + diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html index f6a1e6e73a2bf..00e2f5ba63abd 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html @@ -9,7 +9,7 @@ type="button" class="action action-auth-toggle" data-trigger="authentication"> - +
    - +
    - +
    - +
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html index 895f94e4cbd94..3c87e88b6ad65 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html @@ -6,7 +6,7 @@ -->
    - +
    @@ -16,10 +16,10 @@
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html index 3d7d38a0f4aa8..fba076380a5af 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html @@ -13,6 +13,6 @@
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html index 4174aa194d635..e433f0ab13f02 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -17,7 +17,7 @@
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html index f826ede448372..3df8446b3ffdf 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html @@ -5,7 +5,7 @@ */ -->
    - +
    - +
    @@ -95,14 +95,14 @@
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/subtotal.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/subtotal.html index 7f075dc088224..24009d53ea89d 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/subtotal.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/subtotal.html @@ -6,7 +6,7 @@ -->
    - + diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html index 386f34af57ecc..c0499e1d900e7 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html @@ -9,4 +9,4 @@
    -
    +
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment.html b/app/code/Magento/Checkout/view/frontend/web/template/payment.html index 2f9d709dda115..5de9657e22ee7 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/payment.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/payment.html @@ -5,7 +5,7 @@ */ -->
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html index af87b5805b51e..8d3e26dae0539 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html @@ -13,9 +13,9 @@
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html index e450ee3fd9c3d..f0257cfdfda44 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html @@ -16,7 +16,7 @@
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html index 6d262c39d9f0c..3462a7cf295a6 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html @@ -9,9 +9,9 @@
    - +
    @@ -22,13 +22,13 @@
    - +
    - +
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html index 90be6f79f25d4..fdbc7815f946b 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html @@ -5,7 +5,7 @@ */ -->
  • -
    +
    @@ -29,7 +29,7 @@ +
    @@ -53,7 +53,7 @@ data-bind="fadeVisible: visible(), blockLoader: isLoading" role="presentation">
    -
    +
    @@ -69,9 +69,9 @@   - - - + + + @@ -102,15 +102,15 @@ - - + +
    -
    +
    @@ -131,19 +131,19 @@
    - +
    -
    +
  • diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary.html b/app/code/Magento/Checkout/view/frontend/web/template/summary.html index 322ef76b8f053..459d2f505f592 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary.html @@ -5,7 +5,7 @@ */ -->
    - + diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html index bd6c7efd470fd..b51a70273b250 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html @@ -8,7 +8,7 @@
    - +
    @@ -32,7 +32,7 @@
    - +
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html index 78954c0a4feff..107907b157acf 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html @@ -6,7 +6,7 @@ --> - + diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html index dab4d8393326c..05b39a8f11e00 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html @@ -12,9 +12,9 @@
    - +
    - +
    @@ -25,12 +25,12 @@
    - +
    - +
    -
    +
    diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html index 34707698e61b6..f3a22cef746e5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html @@ -7,17 +7,17 @@ - - + + + data-bind="i18n: getValue(), attr: {'data-th': $t(title)}"> + data-bind="i18n: getValue(), attr: {'data-th': $t(title)}"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html index f241430924ac8..e217668f605f1 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html @@ -6,7 +6,7 @@ --> - + diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html index 074024dee00d9..12fb8acb37d77 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html @@ -5,7 +5,7 @@ */ --> - + diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html index 315bc47af7dac..364d060893812 100644 --- a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html +++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html @@ -6,9 +6,9 @@ -->
    - + - +
    diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml index e0b892f53c3cd..0724d6e3bb245 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml @@ -239,7 +239,7 @@ if ($variations) { }, outerClick: $parent.closeList.bind($parent, $index())">
    • @@ -249,7 +249,7 @@ if ($variations) {
    • diff --git a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html index a2d2941754ff8..fd9bf048afd35 100644 --- a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html +++ b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html @@ -10,19 +10,19 @@
      - +
      -

      +

        -
      • -
      • -
      • +
      • +
      • +
      @@ -31,7 +31,7 @@