diff --git a/apps/course/templates/course/courses.html b/apps/course/templates/course/courses.html
index 72a4c155..2a2ab173 100644
--- a/apps/course/templates/course/courses.html
+++ b/apps/course/templates/course/courses.html
@@ -35,7 +35,7 @@
+
{% endfor %}
\ No newline at end of file
diff --git a/web/build/js/app.js b/web/build/js/app.js
index 68475053..c881e6ba 100755
--- a/web/build/js/app.js
+++ b/web/build/js/app.js
@@ -61,7 +61,7 @@ var app =
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
-/******/ return __webpack_require__(__webpack_require__.s = 2);
+/******/ return __webpack_require__(__webpack_require__.s = 6);
/******/ })
/************************************************************************/
/******/ ([
@@ -10445,7 +10445,15 @@ return jQuery;
Object.defineProperty(exports, "__esModule", {
value: true
});
-var MOBILE_WIDTH = exports.MOBILE_WIDTH = 600;
+exports.default = assertString;
+function assertString(input) {
+ var isString = typeof input === 'string' || input instanceof String;
+
+ if (!isString) {
+ throw new TypeError('This library (validator.js) validates strings only');
+ }
+}
+module.exports = exports['default'];
/***/ }),
/* 2 */
@@ -10454,13 +10462,175 @@ var MOBILE_WIDTH = exports.MOBILE_WIDTH = 600;
"use strict";
-__webpack_require__(3);
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+var MOBILE_WIDTH = exports.MOBILE_WIDTH = 600;
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = merge;
+function merge() {
+ var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ var defaults = arguments[1];
+
+ for (var key in defaults) {
+ if (typeof obj[key] === 'undefined') {
+ obj[key] = defaults[key];
+ }
+ }
+ return obj;
+}
+module.exports = exports['default'];
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/**
+ * Copyright 2014-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+
+
+/**
+ * Similar to invariant but only logs a warning if the condition is not met.
+ * This can be used to log issues in development environments in critical
+ * paths. Removing the logging code for production environments will keep the
+ * same logic and follow the same code paths.
+ */
+
+var warning = function() {};
+
+if (true) {
+ warning = function(condition, format, args) {
+ var len = arguments.length;
+ args = new Array(len > 2 ? len - 2 : 0);
+ for (var key = 2; key < len; key++) {
+ args[key - 2] = arguments[key];
+ }
+ if (format === undefined) {
+ throw new Error(
+ '`warning(condition, format, ...args)` requires a warning ' +
+ 'message argument'
+ );
+ }
+
+ if (format.length < 10 || (/^[s\W]*$/).test(format)) {
+ throw new Error(
+ 'The warning format should be able to uniquely identify this ' +
+ 'warning. Please, use a more descriptive format than: ' + format
+ );
+ }
+
+ if (!condition) {
+ var argIndex = 0;
+ var message = 'Warning: ' +
+ format.replace(/%s/g, function() {
+ return args[argIndex++];
+ });
+ if (typeof console !== 'undefined') {
+ console.error(message);
+ }
+ try {
+ // This error was thrown as a convenience so that you can use this stack
+ // to find the callsite that caused this warning to fire.
+ throw new Error(message);
+ } catch(x) {}
+ }
+ };
+}
+
+module.exports = warning;
+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+var addLeadingSlash = exports.addLeadingSlash = function addLeadingSlash(path) {
+ return path.charAt(0) === '/' ? path : '/' + path;
+};
+
+var stripLeadingSlash = exports.stripLeadingSlash = function stripLeadingSlash(path) {
+ return path.charAt(0) === '/' ? path.substr(1) : path;
+};
+
+var hasBasename = exports.hasBasename = function hasBasename(path, prefix) {
+ return new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path);
+};
+
+var stripBasename = exports.stripBasename = function stripBasename(path, prefix) {
+ return hasBasename(path, prefix) ? path.substr(prefix.length) : path;
+};
+
+var stripTrailingSlash = exports.stripTrailingSlash = function stripTrailingSlash(path) {
+ return path.charAt(path.length - 1) === '/' ? path.slice(0, -1) : path;
+};
+
+var parsePath = exports.parsePath = function parsePath(path) {
+ var pathname = path || '/';
+ var search = '';
+ var hash = '';
+
+ var hashIndex = pathname.indexOf('#');
+ if (hashIndex !== -1) {
+ hash = pathname.substr(hashIndex);
+ pathname = pathname.substr(0, hashIndex);
+ }
+
+ var searchIndex = pathname.indexOf('?');
+ if (searchIndex !== -1) {
+ search = pathname.substr(searchIndex);
+ pathname = pathname.substr(0, searchIndex);
+ }
+
+ return {
+ pathname: pathname,
+ search: search === '?' ? '' : search,
+ hash: hash === '#' ? '' : hash
+ };
+};
+
+var createPath = exports.createPath = function createPath(location) {
+ var pathname = location.pathname,
+ search = location.search,
+ hash = location.hash;
+
+
+ var path = pathname || '/';
+
+ if (search && search !== '?') path += search.charAt(0) === '?' ? search : '?' + search;
+
+ if (hash && hash !== '#') path += hash.charAt(0) === '#' ? hash : '#' + hash;
+
+ return path;
+};
-__webpack_require__(4);
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
-__webpack_require__(5);
+"use strict";
-__webpack_require__(6);
__webpack_require__(7);
@@ -10470,8 +10640,18 @@ __webpack_require__(9);
__webpack_require__(10);
+__webpack_require__(11);
+
+__webpack_require__(17);
+
+__webpack_require__(18);
+
+__webpack_require__(19);
+
+__webpack_require__(20);
+
/***/ }),
-/* 3 */
+/* 7 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -10493,7 +10673,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
});
/***/ }),
-/* 4 */
+/* 8 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -10503,7 +10683,7 @@ var _jquery = __webpack_require__(0);
var _jquery2 = _interopRequireDefault(_jquery);
-var _constants = __webpack_require__(1);
+var _constants = __webpack_require__(2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -10542,7 +10722,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
});
/***/ }),
-/* 5 */
+/* 9 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -10552,7 +10732,7 @@ var _jquery = __webpack_require__(0);
var _jquery2 = _interopRequireDefault(_jquery);
-var _constants = __webpack_require__(1);
+var _constants = __webpack_require__(2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -10584,7 +10764,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
});
/***/ }),
-/* 6 */
+/* 10 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -10606,7 +10786,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
});
/***/ }),
-/* 7 */
+/* 11 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -10616,15 +10796,15 @@ var _jquery = __webpack_require__(0);
var _jquery2 = _interopRequireDefault(_jquery);
-var _isEmail = __webpack_require__(33);
+var _isEmail = __webpack_require__(12);
var _isEmail2 = _interopRequireDefault(_isEmail);
-var _isEmpty = __webpack_require__(55);
+var _isEmpty = __webpack_require__(15);
var _isEmpty2 = _interopRequireDefault(_isEmpty);
-var _isLength = __webpack_require__(56);
+var _isLength = __webpack_require__(16);
var _isLength2 = _interopRequireDefault(_isLength);
@@ -10862,208 +11042,141 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
});
/***/ }),
-/* 8 */
+/* 12 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var _jquery = __webpack_require__(0);
-
-var _jquery2 = _interopRequireDefault(_jquery);
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = isEmail;
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+var _assertString = __webpack_require__(1);
-(0, _jquery2.default)(document).ready(function () {
- var select = (0, _jquery2.default)('.js-select');
- if (select.length) {
- select.each(function () {
- var _this = (0, _jquery2.default)(this),
- head = _this.find('.js-select-head'),
- option = _this.find('.js-select-option'),
- input = _this.find('.js-select-input');
+var _assertString2 = _interopRequireDefault(_assertString);
- head.on('click', function (e) {
- e.preventDefault();
- e.stopPropagation();
+var _merge = __webpack_require__(3);
- if (_this.hasClass('active')) {
- _this.removeClass('active');
- } else {
- select.removeClass('active');
- _this.addClass('active');
- }
- });
+var _merge2 = _interopRequireDefault(_merge);
- option.on('click', function (e) {
- e.preventDefault();
- _this.addClass('selected');
+var _isByteLength = __webpack_require__(13);
- var _thisOption = (0, _jquery2.default)(this),
- value = _thisOption.text();
+var _isByteLength2 = _interopRequireDefault(_isByteLength);
- head.text(value);
+var _isFQDN = __webpack_require__(14);
- option.removeClass('active');
- _thisOption.addClass('active');
+var _isFQDN2 = _interopRequireDefault(_isFQDN);
- input.val(value);
- });
- });
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- (0, _jquery2.default)(document).on('click', function () {
- select.removeClass('active');
- });
- }
-});
+var default_email_options = {
+ allow_display_name: false,
+ require_display_name: false,
+ allow_utf8_local_part: true,
+ require_tld: true
+};
-/***/ }),
-/* 9 */
-/***/ (function(module, exports, __webpack_require__) {
+/* eslint-disable max-len */
+/* eslint-disable no-control-regex */
+var displayName = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\,\.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF\s]*<(.+)>$/i;
+var emailUserPart = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i;
+var quotedEmailUser = /^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i;
+var emailUserUtf8Part = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i;
+var quotedEmailUserUtf8 = /^([\s\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]))*$/i;
+/* eslint-enable max-len */
+/* eslint-enable no-control-regex */
-"use strict";
+function isEmail(str, options) {
+ (0, _assertString2.default)(str);
+ options = (0, _merge2.default)(options, default_email_options);
+ if (options.require_display_name || options.allow_display_name) {
+ var display_email = str.match(displayName);
+ if (display_email) {
+ str = display_email[1];
+ } else if (options.require_display_name) {
+ return false;
+ }
+ }
-var _jquery = __webpack_require__(0);
+ var parts = str.split('@');
+ var domain = parts.pop();
+ var user = parts.join('@');
-var _jquery2 = _interopRequireDefault(_jquery);
+ var lower_domain = domain.toLowerCase();
+ if (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com') {
+ user = user.replace(/\./g, '').toLowerCase();
+ }
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+ if (!(0, _isByteLength2.default)(user, { max: 64 }) || !(0, _isByteLength2.default)(domain, { max: 254 })) {
+ return false;
+ }
-(0, _jquery2.default)(document).ready(function () {
- var tabs = (0, _jquery2.default)('.js-tabs');
- if (tabs.length) {
- tabs.each(function () {
- var _this = (0, _jquery2.default)(this),
- btn = _this.find('.js-tabs-btn'),
- item = _this.find('.js-tabs-item');
+ if (!(0, _isFQDN2.default)(domain, { require_tld: options.require_tld })) {
+ return false;
+ }
- btn.on('click', function (e) {
- e.preventDefault();
+ if (user[0] === '"') {
+ user = user.slice(1, user.length - 1);
+ return options.allow_utf8_local_part ? quotedEmailUserUtf8.test(user) : quotedEmailUser.test(user);
+ }
- var _thisBtn = (0, _jquery2.default)(this),
- index = _thisBtn.index();
+ var pattern = options.allow_utf8_local_part ? emailUserUtf8Part : emailUserPart;
- btn.removeClass('active');
- _thisBtn.addClass('active');
- item.hide();
- item.eq(index).fadeIn();
- });
- });
+ var user_parts = user.split('.');
+ for (var i = 0; i < user_parts.length; i++) {
+ if (!pattern.test(user_parts[i])) {
+ return false;
}
-});
+ }
+
+ return true;
+}
+module.exports = exports['default'];
/***/ }),
-/* 10 */
+/* 13 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var _jquery = __webpack_require__(0);
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
-var _jquery2 = _interopRequireDefault(_jquery);
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+exports.default = isByteLength;
-(0, _jquery2.default)(document).ready(function () {
- var body = (0, _jquery2.default)('body'),
- popup = void 0;
-
- body.on('click', '[data-popup]', function (e) {
- e.preventDefault();
- e.stopPropagation();
-
- var data = (0, _jquery2.default)(this).data('popup');
- popup = (0, _jquery2.default)(data);
- showPopup();
- });
-
- (0, _jquery2.default)('.js-popup-close').on('click', function (e) {
- e.preventDefault();
- hidePopup();
- });
-
- body.on('click', '.js-outer', function () {
- if (popup !== undefined) {
- hidePopup();
- }
- });
-
- (0, _jquery2.default)('.js-popup-wrap').on('click', function (e) {
- e.stopPropagation();
- });
-
- (0, _jquery2.default)(document).keyup(function (e) {
- if (e.keyCode === 27) hidePopup();
- });
-
- function showPopup() {
- body.addClass('no-scroll');
- popup.addClass('open');
- setTimeout(function () {
- popup.addClass('visible');
- }, 100);
- }
-
- function hidePopup() {
- body.removeClass('no-scroll');
- popup.removeClass('visible');
- setTimeout(function () {
- popup.removeClass('open');
- }, 300);
- }
-});
-
-/***/ }),
-/* 11 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = assertString;
-function assertString(input) {
- var isString = typeof input === 'string' || input instanceof String;
-
- if (!isString) {
- throw new TypeError('This library (validator.js) validates strings only');
- }
-}
-module.exports = exports['default'];
-
-/***/ }),
-/* 12 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
+var _assertString = __webpack_require__(1);
+var _assertString2 = _interopRequireDefault(_assertString);
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = merge;
-function merge() {
- var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var defaults = arguments[1];
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- for (var key in defaults) {
- if (typeof obj[key] === 'undefined') {
- obj[key] = defaults[key];
- }
+/* eslint-disable prefer-rest-params */
+function isByteLength(str, options) {
+ (0, _assertString2.default)(str);
+ var min = void 0;
+ var max = void 0;
+ if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
+ min = options.min || 0;
+ max = options.max;
+ } else {
+ // backwards compatibility: isByteLength(str, min [, max])
+ min = arguments[1];
+ max = arguments[2];
}
- return obj;
+ var len = encodeURI(str).split(/%..|./).length - 1;
+ return len >= min && (typeof max === 'undefined' || len <= max);
}
module.exports = exports['default'];
/***/ }),
-/* 13 */,
-/* 14 */,
-/* 15 */,
-/* 16 */
+/* 14 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -11074,11 +11187,11 @@ Object.defineProperty(exports, "__esModule", {
});
exports.default = isFQDN;
-var _assertString = __webpack_require__(11);
+var _assertString = __webpack_require__(1);
var _assertString2 = _interopRequireDefault(_assertString);
-var _merge = __webpack_require__(12);
+var _merge = __webpack_require__(3);
var _merge2 = _interopRequireDefault(_merge);
@@ -11130,8 +11243,31 @@ function isFQDN(str, options) {
module.exports = exports['default'];
/***/ }),
-/* 17 */,
-/* 18 */
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = isEmpty;
+
+var _assertString = __webpack_require__(1);
+
+var _assertString2 = _interopRequireDefault(_assertString);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function isEmpty(str) {
+ (0, _assertString2.default)(str);
+ return str.length === 0;
+}
+module.exports = exports['default'];
+
+/***/ }),
+/* 16 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -11143,16 +11279,16 @@ Object.defineProperty(exports, "__esModule", {
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-exports.default = isByteLength;
+exports.default = isLength;
-var _assertString = __webpack_require__(11);
+var _assertString = __webpack_require__(1);
var _assertString2 = _interopRequireDefault(_assertString);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable prefer-rest-params */
-function isByteLength(str, options) {
+function isLength(str, options) {
(0, _assertString2.default)(str);
var min = void 0;
var max = void 0;
@@ -11160,208 +11296,961 @@ function isByteLength(str, options) {
min = options.min || 0;
max = options.max;
} else {
- // backwards compatibility: isByteLength(str, min [, max])
+ // backwards compatibility: isLength(str, min [, max])
min = arguments[1];
max = arguments[2];
}
- var len = encodeURI(str).split(/%..|./).length - 1;
+ var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || [];
+ var len = str.length - surrogatePairs.length;
return len >= min && (typeof max === 'undefined' || len <= max);
}
module.exports = exports['default'];
/***/ }),
-/* 19 */,
-/* 20 */,
-/* 21 */,
-/* 22 */,
-/* 23 */,
-/* 24 */,
-/* 25 */,
-/* 26 */,
-/* 27 */,
-/* 28 */,
-/* 29 */,
-/* 30 */,
-/* 31 */,
-/* 32 */,
-/* 33 */
+/* 17 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = isEmail;
-
-var _assertString = __webpack_require__(11);
-
-var _assertString2 = _interopRequireDefault(_assertString);
-
-var _merge = __webpack_require__(12);
-
-var _merge2 = _interopRequireDefault(_merge);
-
-var _isByteLength = __webpack_require__(18);
-
-var _isByteLength2 = _interopRequireDefault(_isByteLength);
-
-var _isFQDN = __webpack_require__(16);
+var _jquery = __webpack_require__(0);
-var _isFQDN2 = _interopRequireDefault(_isFQDN);
+var _jquery2 = _interopRequireDefault(_jquery);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-var default_email_options = {
- allow_display_name: false,
- require_display_name: false,
- allow_utf8_local_part: true,
- require_tld: true
-};
-
-/* eslint-disable max-len */
-/* eslint-disable no-control-regex */
-var displayName = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\,\.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF\s]*<(.+)>$/i;
-var emailUserPart = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i;
-var quotedEmailUser = /^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i;
-var emailUserUtf8Part = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i;
-var quotedEmailUserUtf8 = /^([\s\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]))*$/i;
-/* eslint-enable max-len */
-/* eslint-enable no-control-regex */
-
-function isEmail(str, options) {
- (0, _assertString2.default)(str);
- options = (0, _merge2.default)(options, default_email_options);
+(0, _jquery2.default)(document).ready(function () {
+ var select = (0, _jquery2.default)('.js-select');
+ if (select.length) {
+ select.each(function () {
+ var _this = (0, _jquery2.default)(this),
+ head = _this.find('.js-select-head'),
+ option = _this.find('.js-select-option'),
+ input = _this.find('.js-select-input');
- if (options.require_display_name || options.allow_display_name) {
- var display_email = str.match(displayName);
- if (display_email) {
- str = display_email[1];
- } else if (options.require_display_name) {
- return false;
- }
- }
+ head.on('click', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
- var parts = str.split('@');
- var domain = parts.pop();
- var user = parts.join('@');
+ if (_this.hasClass('active')) {
+ _this.removeClass('active');
+ } else {
+ select.removeClass('active');
+ _this.addClass('active');
+ }
+ });
- var lower_domain = domain.toLowerCase();
- if (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com') {
- user = user.replace(/\./g, '').toLowerCase();
- }
+ option.on('click', function (e) {
+ e.preventDefault();
+ _this.addClass('selected');
- if (!(0, _isByteLength2.default)(user, { max: 64 }) || !(0, _isByteLength2.default)(domain, { max: 254 })) {
- return false;
- }
+ var _thisOption = (0, _jquery2.default)(this),
+ value = _thisOption.text();
- if (!(0, _isFQDN2.default)(domain, { require_tld: options.require_tld })) {
- return false;
- }
+ head.text(value);
- if (user[0] === '"') {
- user = user.slice(1, user.length - 1);
- return options.allow_utf8_local_part ? quotedEmailUserUtf8.test(user) : quotedEmailUser.test(user);
- }
+ option.removeClass('active');
+ _thisOption.addClass('active');
- var pattern = options.allow_utf8_local_part ? emailUserUtf8Part : emailUserPart;
+ input.val(value);
+ });
+ });
- var user_parts = user.split('.');
- for (var i = 0; i < user_parts.length; i++) {
- if (!pattern.test(user_parts[i])) {
- return false;
+ (0, _jquery2.default)(document).on('click', function () {
+ select.removeClass('active');
+ });
}
- }
-
- return true;
-}
-module.exports = exports['default'];
+});
/***/ }),
-/* 34 */,
-/* 35 */,
-/* 36 */,
-/* 37 */,
-/* 38 */,
-/* 39 */,
-/* 40 */,
-/* 41 */,
-/* 42 */,
-/* 43 */,
-/* 44 */,
-/* 45 */,
-/* 46 */,
-/* 47 */,
-/* 48 */,
-/* 49 */,
-/* 50 */,
-/* 51 */,
-/* 52 */,
-/* 53 */,
-/* 54 */,
-/* 55 */
+/* 18 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = isEmpty;
-
-var _assertString = __webpack_require__(11);
+var _jquery = __webpack_require__(0);
-var _assertString2 = _interopRequireDefault(_assertString);
+var _jquery2 = _interopRequireDefault(_jquery);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-function isEmpty(str) {
- (0, _assertString2.default)(str);
- return str.length === 0;
-}
-module.exports = exports['default'];
-
-/***/ }),
-/* 56 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
+(0, _jquery2.default)(document).ready(function () {
+ var tabs = (0, _jquery2.default)('.js-tabs');
+ if (tabs.length) {
+ tabs.each(function () {
+ var _this = (0, _jquery2.default)(this),
+ btn = _this.find('.js-tabs-btn'),
+ item = _this.find('.js-tabs-item');
+ btn.on('click', function (e) {
+ e.preventDefault();
-Object.defineProperty(exports, "__esModule", {
- value: true
+ var _thisBtn = (0, _jquery2.default)(this),
+ index = _thisBtn.index();
+
+ btn.removeClass('active');
+ _thisBtn.addClass('active');
+ item.hide();
+ item.eq(index).fadeIn();
+ });
+ });
+ }
+});
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _jquery = __webpack_require__(0);
+
+var _jquery2 = _interopRequireDefault(_jquery);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+(0, _jquery2.default)(document).ready(function () {
+ var body = (0, _jquery2.default)('body'),
+ popup = void 0;
+
+ body.on('click', '[data-popup]', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ var data = (0, _jquery2.default)(this).data('popup');
+ popup = (0, _jquery2.default)(data);
+ showPopup();
+ });
+
+ (0, _jquery2.default)('.js-popup-close').on('click', function (e) {
+ e.preventDefault();
+ hidePopup();
+ });
+
+ body.on('click', '.js-outer', function () {
+ if (popup !== undefined) {
+ hidePopup();
+ }
+ });
+
+ (0, _jquery2.default)('.js-popup-wrap').on('click', function (e) {
+ e.stopPropagation();
+ });
+
+ (0, _jquery2.default)(document).keyup(function (e) {
+ if (e.keyCode === 27) hidePopup();
+ });
+
+ function showPopup() {
+ body.addClass('no-scroll');
+ popup.addClass('open');
+ setTimeout(function () {
+ popup.addClass('visible');
+ }, 100);
+ }
+
+ function hidePopup() {
+ body.removeClass('no-scroll');
+ popup.removeClass('visible');
+ setTimeout(function () {
+ popup.removeClass('open');
+ }, 300);
+ }
+});
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _jquery = __webpack_require__(0);
+
+var _jquery2 = _interopRequireDefault(_jquery);
+
+var _createBrowserHistory = __webpack_require__(21);
+
+var _createBrowserHistory2 = _interopRequireDefault(_createBrowserHistory);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// Создаем объект history API
+var history = (0, _createBrowserHistory2.default)();
+
+(0, _jquery2.default)(document).ready(function () {
+ // Обработчик кнопки "Подгрузить еще"
+ (0, _jquery2.default)('.courses').on('click', 'button.load__btn', function () {
+ load_courses((0, _jquery2.default)(this).attr('data-next-page-url'), false);
+ });
+
+ // Обработчик выбора категории
+ (0, _jquery2.default)('div.js-select-option[data-category-option]').on('click', function (e) {
+ e.preventDefault();
+ history.replace((0, _jquery2.default)(this).attr('data-category-url'));
+ load_courses((0, _jquery2.default)(this).attr('data-category-url'), true);
+ });
});
+function load_courses(coursesUrl, fromStart) {
+ (0, _jquery2.default)('.courses__list').css('opacity', '0.9');
+ var buttonElement = (0, _jquery2.default)('.courses').find('button.load__btn');
+ if (!fromStart) {
+ buttonElement.addClass('loading');
+ }
+ _jquery2.default.ajax(coursesUrl, {
+ method: 'GET'
+ }).done(function (data) {
+ if (data.success === true) {
+ if (!fromStart) {
+ (0, _jquery2.default)('.courses__list').append(data.content);
+ } else {
+ (0, _jquery2.default)('.courses__list').html(data.content);
+ }
+ if (data.next_url) {
+ buttonElement.attr('data-next-page-url', data.next_url);
+ } else {
+ buttonElement.hide();
+ }
+ }
+ }).fail(function (xhr) {}).always(function () {
+ (0, _jquery2.default)('.courses__list').css('opacity', '1');
+ if (buttonElement) {
+ buttonElement.removeClass('loading');
+ }
+ });
+}
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-exports.default = isLength;
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-var _assertString = __webpack_require__(11);
+var _warning = __webpack_require__(4);
-var _assertString2 = _interopRequireDefault(_assertString);
+var _warning2 = _interopRequireDefault(_warning);
+
+var _invariant = __webpack_require__(22);
+
+var _invariant2 = _interopRequireDefault(_invariant);
+
+var _LocationUtils = __webpack_require__(23);
+
+var _PathUtils = __webpack_require__(5);
+
+var _createTransitionManager = __webpack_require__(26);
+
+var _createTransitionManager2 = _interopRequireDefault(_createTransitionManager);
+
+var _DOMUtils = __webpack_require__(27);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-/* eslint-disable prefer-rest-params */
-function isLength(str, options) {
- (0, _assertString2.default)(str);
- var min = void 0;
- var max = void 0;
- if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
- min = options.min || 0;
- max = options.max;
+var PopStateEvent = 'popstate';
+var HashChangeEvent = 'hashchange';
+
+var getHistoryState = function getHistoryState() {
+ try {
+ return window.history.state || {};
+ } catch (e) {
+ // IE 11 sometimes throws when accessing window.history.state
+ // See https://github.com/ReactTraining/history/pull/289
+ return {};
+ }
+};
+
+/**
+ * Creates a history object that uses the HTML5 history API including
+ * pushState, replaceState, and the popstate event.
+ */
+var createBrowserHistory = function createBrowserHistory() {
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ (0, _invariant2.default)(_DOMUtils.canUseDOM, 'Browser history needs a DOM');
+
+ var globalHistory = window.history;
+ var canUseHistory = (0, _DOMUtils.supportsHistory)();
+ var needsHashChangeListener = !(0, _DOMUtils.supportsPopStateOnHashChange)();
+
+ var _props$forceRefresh = props.forceRefresh,
+ forceRefresh = _props$forceRefresh === undefined ? false : _props$forceRefresh,
+ _props$getUserConfirm = props.getUserConfirmation,
+ getUserConfirmation = _props$getUserConfirm === undefined ? _DOMUtils.getConfirmation : _props$getUserConfirm,
+ _props$keyLength = props.keyLength,
+ keyLength = _props$keyLength === undefined ? 6 : _props$keyLength;
+
+ var basename = props.basename ? (0, _PathUtils.stripTrailingSlash)((0, _PathUtils.addLeadingSlash)(props.basename)) : '';
+
+ var getDOMLocation = function getDOMLocation(historyState) {
+ var _ref = historyState || {},
+ key = _ref.key,
+ state = _ref.state;
+
+ var _window$location = window.location,
+ pathname = _window$location.pathname,
+ search = _window$location.search,
+ hash = _window$location.hash;
+
+
+ var path = pathname + search + hash;
+
+ (0, _warning2.default)(!basename || (0, _PathUtils.hasBasename)(path, basename), 'You are attempting to use a basename on a page whose URL path does not begin ' + 'with the basename. Expected path "' + path + '" to begin with "' + basename + '".');
+
+ if (basename) path = (0, _PathUtils.stripBasename)(path, basename);
+
+ return (0, _LocationUtils.createLocation)(path, state, key);
+ };
+
+ var createKey = function createKey() {
+ return Math.random().toString(36).substr(2, keyLength);
+ };
+
+ var transitionManager = (0, _createTransitionManager2.default)();
+
+ var setState = function setState(nextState) {
+ _extends(history, nextState);
+
+ history.length = globalHistory.length;
+
+ transitionManager.notifyListeners(history.location, history.action);
+ };
+
+ var handlePopState = function handlePopState(event) {
+ // Ignore extraneous popstate events in WebKit.
+ if ((0, _DOMUtils.isExtraneousPopstateEvent)(event)) return;
+
+ handlePop(getDOMLocation(event.state));
+ };
+
+ var handleHashChange = function handleHashChange() {
+ handlePop(getDOMLocation(getHistoryState()));
+ };
+
+ var forceNextPop = false;
+
+ var handlePop = function handlePop(location) {
+ if (forceNextPop) {
+ forceNextPop = false;
+ setState();
+ } else {
+ var action = 'POP';
+
+ transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {
+ if (ok) {
+ setState({ action: action, location: location });
+ } else {
+ revertPop(location);
+ }
+ });
+ }
+ };
+
+ var revertPop = function revertPop(fromLocation) {
+ var toLocation = history.location;
+
+ // TODO: We could probably make this more reliable by
+ // keeping a list of keys we've seen in sessionStorage.
+ // Instead, we just default to 0 for keys we don't know.
+
+ var toIndex = allKeys.indexOf(toLocation.key);
+
+ if (toIndex === -1) toIndex = 0;
+
+ var fromIndex = allKeys.indexOf(fromLocation.key);
+
+ if (fromIndex === -1) fromIndex = 0;
+
+ var delta = toIndex - fromIndex;
+
+ if (delta) {
+ forceNextPop = true;
+ go(delta);
+ }
+ };
+
+ var initialLocation = getDOMLocation(getHistoryState());
+ var allKeys = [initialLocation.key];
+
+ // Public interface
+
+ var createHref = function createHref(location) {
+ return basename + (0, _PathUtils.createPath)(location);
+ };
+
+ var push = function push(path, state) {
+ (0, _warning2.default)(!((typeof path === 'undefined' ? 'undefined' : _typeof(path)) === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to push when the 1st ' + 'argument is a location-like object that already has state; it is ignored');
+
+ var action = 'PUSH';
+ var location = (0, _LocationUtils.createLocation)(path, state, createKey(), history.location);
+
+ transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {
+ if (!ok) return;
+
+ var href = createHref(location);
+ var key = location.key,
+ state = location.state;
+
+
+ if (canUseHistory) {
+ globalHistory.pushState({ key: key, state: state }, null, href);
+
+ if (forceRefresh) {
+ window.location.href = href;
+ } else {
+ var prevIndex = allKeys.indexOf(history.location.key);
+ var nextKeys = allKeys.slice(0, prevIndex === -1 ? 0 : prevIndex + 1);
+
+ nextKeys.push(location.key);
+ allKeys = nextKeys;
+
+ setState({ action: action, location: location });
+ }
+ } else {
+ (0, _warning2.default)(state === undefined, 'Browser history cannot push state in browsers that do not support HTML5 history');
+
+ window.location.href = href;
+ }
+ });
+ };
+
+ var replace = function replace(path, state) {
+ (0, _warning2.default)(!((typeof path === 'undefined' ? 'undefined' : _typeof(path)) === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to replace when the 1st ' + 'argument is a location-like object that already has state; it is ignored');
+
+ var action = 'REPLACE';
+ var location = (0, _LocationUtils.createLocation)(path, state, createKey(), history.location);
+
+ transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {
+ if (!ok) return;
+
+ var href = createHref(location);
+ var key = location.key,
+ state = location.state;
+
+
+ if (canUseHistory) {
+ globalHistory.replaceState({ key: key, state: state }, null, href);
+
+ if (forceRefresh) {
+ window.location.replace(href);
+ } else {
+ var prevIndex = allKeys.indexOf(history.location.key);
+
+ if (prevIndex !== -1) allKeys[prevIndex] = location.key;
+
+ setState({ action: action, location: location });
+ }
+ } else {
+ (0, _warning2.default)(state === undefined, 'Browser history cannot replace state in browsers that do not support HTML5 history');
+
+ window.location.replace(href);
+ }
+ });
+ };
+
+ var go = function go(n) {
+ globalHistory.go(n);
+ };
+
+ var goBack = function goBack() {
+ return go(-1);
+ };
+
+ var goForward = function goForward() {
+ return go(1);
+ };
+
+ var listenerCount = 0;
+
+ var checkDOMListeners = function checkDOMListeners(delta) {
+ listenerCount += delta;
+
+ if (listenerCount === 1) {
+ (0, _DOMUtils.addEventListener)(window, PopStateEvent, handlePopState);
+
+ if (needsHashChangeListener) (0, _DOMUtils.addEventListener)(window, HashChangeEvent, handleHashChange);
+ } else if (listenerCount === 0) {
+ (0, _DOMUtils.removeEventListener)(window, PopStateEvent, handlePopState);
+
+ if (needsHashChangeListener) (0, _DOMUtils.removeEventListener)(window, HashChangeEvent, handleHashChange);
+ }
+ };
+
+ var isBlocked = false;
+
+ var block = function block() {
+ var prompt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+
+ var unblock = transitionManager.setPrompt(prompt);
+
+ if (!isBlocked) {
+ checkDOMListeners(1);
+ isBlocked = true;
+ }
+
+ return function () {
+ if (isBlocked) {
+ isBlocked = false;
+ checkDOMListeners(-1);
+ }
+
+ return unblock();
+ };
+ };
+
+ var listen = function listen(listener) {
+ var unlisten = transitionManager.appendListener(listener);
+ checkDOMListeners(1);
+
+ return function () {
+ checkDOMListeners(-1);
+ unlisten();
+ };
+ };
+
+ var history = {
+ length: globalHistory.length,
+ action: 'POP',
+ location: initialLocation,
+ createHref: createHref,
+ push: push,
+ replace: replace,
+ go: go,
+ goBack: goBack,
+ goForward: goForward,
+ block: block,
+ listen: listen
+ };
+
+ return history;
+};
+
+exports.default = createBrowserHistory;
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+
+
+/**
+ * Use invariant() to assert state which your program assumes to be true.
+ *
+ * Provide sprintf-style format (only %s is supported) and arguments
+ * to provide information about what broke and what you were
+ * expecting.
+ *
+ * The invariant message will be stripped in production, but the invariant
+ * will remain to ensure logic does not differ in production.
+ */
+
+var invariant = function(condition, format, a, b, c, d, e, f) {
+ if (true) {
+ if (format === undefined) {
+ throw new Error('invariant requires an error message argument');
+ }
+ }
+
+ if (!condition) {
+ var error;
+ if (format === undefined) {
+ error = new Error(
+ 'Minified exception occurred; use the non-minified dev environment ' +
+ 'for the full error message and additional helpful warnings.'
+ );
+ } else {
+ var args = [a, b, c, d, e, f];
+ var argIndex = 0;
+ error = new Error(
+ format.replace(/%s/g, function() { return args[argIndex++]; })
+ );
+ error.name = 'Invariant Violation';
+ }
+
+ error.framesToPop = 1; // we don't care about invariant's own frame
+ throw error;
+ }
+};
+
+module.exports = invariant;
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+exports.locationsAreEqual = exports.createLocation = undefined;
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _resolvePathname = __webpack_require__(24);
+
+var _resolvePathname2 = _interopRequireDefault(_resolvePathname);
+
+var _valueEqual = __webpack_require__(25);
+
+var _valueEqual2 = _interopRequireDefault(_valueEqual);
+
+var _PathUtils = __webpack_require__(5);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var createLocation = exports.createLocation = function createLocation(path, state, key, currentLocation) {
+ var location = void 0;
+ if (typeof path === 'string') {
+ // Two-arg form: push(path, state)
+ location = (0, _PathUtils.parsePath)(path);
+ location.state = state;
} else {
- // backwards compatibility: isLength(str, min [, max])
- min = arguments[1];
- max = arguments[2];
+ // One-arg form: push(location)
+ location = _extends({}, path);
+
+ if (location.pathname === undefined) location.pathname = '';
+
+ if (location.search) {
+ if (location.search.charAt(0) !== '?') location.search = '?' + location.search;
+ } else {
+ location.search = '';
+ }
+
+ if (location.hash) {
+ if (location.hash.charAt(0) !== '#') location.hash = '#' + location.hash;
+ } else {
+ location.hash = '';
+ }
+
+ if (state !== undefined && location.state === undefined) location.state = state;
}
- var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || [];
- var len = str.length - surrogatePairs.length;
- return len >= min && (typeof max === 'undefined' || len <= max);
+
+ try {
+ location.pathname = decodeURI(location.pathname);
+ } catch (e) {
+ if (e instanceof URIError) {
+ throw new URIError('Pathname "' + location.pathname + '" could not be decoded. ' + 'This is likely caused by an invalid percent-encoding.');
+ } else {
+ throw e;
+ }
+ }
+
+ if (key) location.key = key;
+
+ if (currentLocation) {
+ // Resolve incomplete/relative pathname relative to current location.
+ if (!location.pathname) {
+ location.pathname = currentLocation.pathname;
+ } else if (location.pathname.charAt(0) !== '/') {
+ location.pathname = (0, _resolvePathname2.default)(location.pathname, currentLocation.pathname);
+ }
+ } else {
+ // When there is no prior location and pathname is empty, set it to /
+ if (!location.pathname) {
+ location.pathname = '/';
+ }
+ }
+
+ return location;
+};
+
+var locationsAreEqual = exports.locationsAreEqual = function locationsAreEqual(a, b) {
+ return a.pathname === b.pathname && a.search === b.search && a.hash === b.hash && a.key === b.key && (0, _valueEqual2.default)(a.state, b.state);
+};
+
+/***/ }),
+/* 24 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+function isAbsolute(pathname) {
+ return pathname.charAt(0) === '/';
}
-module.exports = exports['default'];
+
+// About 1.5x faster than the two-arg version of Array#splice()
+function spliceOne(list, index) {
+ for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) {
+ list[i] = list[k];
+ }
+
+ list.pop();
+}
+
+// This implementation is based heavily on node's url.parse
+function resolvePathname(to) {
+ var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
+
+ var toParts = to && to.split('/') || [];
+ var fromParts = from && from.split('/') || [];
+
+ var isToAbs = to && isAbsolute(to);
+ var isFromAbs = from && isAbsolute(from);
+ var mustEndAbs = isToAbs || isFromAbs;
+
+ if (to && isAbsolute(to)) {
+ // to is absolute
+ fromParts = toParts;
+ } else if (toParts.length) {
+ // to is relative, drop the filename
+ fromParts.pop();
+ fromParts = fromParts.concat(toParts);
+ }
+
+ if (!fromParts.length) return '/';
+
+ var hasTrailingSlash = void 0;
+ if (fromParts.length) {
+ var last = fromParts[fromParts.length - 1];
+ hasTrailingSlash = last === '.' || last === '..' || last === '';
+ } else {
+ hasTrailingSlash = false;
+ }
+
+ var up = 0;
+ for (var i = fromParts.length; i >= 0; i--) {
+ var part = fromParts[i];
+
+ if (part === '.') {
+ spliceOne(fromParts, i);
+ } else if (part === '..') {
+ spliceOne(fromParts, i);
+ up++;
+ } else if (up) {
+ spliceOne(fromParts, i);
+ up--;
+ }
+ }
+
+ if (!mustEndAbs) for (; up--; up) {
+ fromParts.unshift('..');
+ }if (mustEndAbs && fromParts[0] !== '' && (!fromParts[0] || !isAbsolute(fromParts[0]))) fromParts.unshift('');
+
+ var result = fromParts.join('/');
+
+ if (hasTrailingSlash && result.substr(-1) !== '/') result += '/';
+
+ return result;
+}
+
+/* harmony default export */ __webpack_exports__["default"] = (resolvePathname);
+
+/***/ }),
+/* 25 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+function valueEqual(a, b) {
+ if (a === b) return true;
+
+ if (a == null || b == null) return false;
+
+ if (Array.isArray(a)) {
+ return Array.isArray(b) && a.length === b.length && a.every(function (item, index) {
+ return valueEqual(item, b[index]);
+ });
+ }
+
+ var aType = typeof a === 'undefined' ? 'undefined' : _typeof(a);
+ var bType = typeof b === 'undefined' ? 'undefined' : _typeof(b);
+
+ if (aType !== bType) return false;
+
+ if (aType === 'object') {
+ var aValue = a.valueOf();
+ var bValue = b.valueOf();
+
+ if (aValue !== a || bValue !== b) return valueEqual(aValue, bValue);
+
+ var aKeys = Object.keys(a);
+ var bKeys = Object.keys(b);
+
+ if (aKeys.length !== bKeys.length) return false;
+
+ return aKeys.every(function (key) {
+ return valueEqual(a[key], b[key]);
+ });
+ }
+
+ return false;
+}
+
+/* harmony default export */ __webpack_exports__["default"] = (valueEqual);
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _warning = __webpack_require__(4);
+
+var _warning2 = _interopRequireDefault(_warning);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var createTransitionManager = function createTransitionManager() {
+ var prompt = null;
+
+ var setPrompt = function setPrompt(nextPrompt) {
+ (0, _warning2.default)(prompt == null, 'A history supports only one prompt at a time');
+
+ prompt = nextPrompt;
+
+ return function () {
+ if (prompt === nextPrompt) prompt = null;
+ };
+ };
+
+ var confirmTransitionTo = function confirmTransitionTo(location, action, getUserConfirmation, callback) {
+ // TODO: If another transition starts while we're still confirming
+ // the previous one, we may end up in a weird state. Figure out the
+ // best way to handle this.
+ if (prompt != null) {
+ var result = typeof prompt === 'function' ? prompt(location, action) : prompt;
+
+ if (typeof result === 'string') {
+ if (typeof getUserConfirmation === 'function') {
+ getUserConfirmation(result, callback);
+ } else {
+ (0, _warning2.default)(false, 'A history needs a getUserConfirmation function in order to use a prompt message');
+
+ callback(true);
+ }
+ } else {
+ // Return false from a transition hook to cancel the transition.
+ callback(result !== false);
+ }
+ } else {
+ callback(true);
+ }
+ };
+
+ var listeners = [];
+
+ var appendListener = function appendListener(fn) {
+ var isActive = true;
+
+ var listener = function listener() {
+ if (isActive) fn.apply(undefined, arguments);
+ };
+
+ listeners.push(listener);
+
+ return function () {
+ isActive = false;
+ listeners = listeners.filter(function (item) {
+ return item !== listener;
+ });
+ };
+ };
+
+ var notifyListeners = function notifyListeners() {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ listeners.forEach(function (listener) {
+ return listener.apply(undefined, args);
+ });
+ };
+
+ return {
+ setPrompt: setPrompt,
+ confirmTransitionTo: confirmTransitionTo,
+ appendListener: appendListener,
+ notifyListeners: notifyListeners
+ };
+};
+
+exports.default = createTransitionManager;
+
+/***/ }),
+/* 27 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+var canUseDOM = exports.canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
+
+var addEventListener = exports.addEventListener = function addEventListener(node, event, listener) {
+ return node.addEventListener ? node.addEventListener(event, listener, false) : node.attachEvent('on' + event, listener);
+};
+
+var removeEventListener = exports.removeEventListener = function removeEventListener(node, event, listener) {
+ return node.removeEventListener ? node.removeEventListener(event, listener, false) : node.detachEvent('on' + event, listener);
+};
+
+var getConfirmation = exports.getConfirmation = function getConfirmation(message, callback) {
+ return callback(window.confirm(message));
+}; // eslint-disable-line no-alert
+
+/**
+ * Returns true if the HTML5 history API is supported. Taken from Modernizr.
+ *
+ * https://github.com/Modernizr/Modernizr/blob/master/LICENSE
+ * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
+ * changed to avoid false negatives for Windows Phones: https://github.com/reactjs/react-router/issues/586
+ */
+var supportsHistory = exports.supportsHistory = function supportsHistory() {
+ var ua = window.navigator.userAgent;
+
+ if ((ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) && ua.indexOf('Mobile Safari') !== -1 && ua.indexOf('Chrome') === -1 && ua.indexOf('Windows Phone') === -1) return false;
+
+ return window.history && 'pushState' in window.history;
+};
+
+/**
+ * Returns true if browser fires popstate on hash change.
+ * IE10 and IE11 do not.
+ */
+var supportsPopStateOnHashChange = exports.supportsPopStateOnHashChange = function supportsPopStateOnHashChange() {
+ return window.navigator.userAgent.indexOf('Trident') === -1;
+};
+
+/**
+ * Returns false if using go(n) with hash history causes a full page reload.
+ */
+var supportsGoWithoutReloadUsingHash = exports.supportsGoWithoutReloadUsingHash = function supportsGoWithoutReloadUsingHash() {
+ return window.navigator.userAgent.indexOf('Firefox') === -1;
+};
+
+/**
+ * Returns true if a given popstate event is an extraneous WebKit event.
+ * Accounts for the fact that Chrome on iOS fires real popstate events
+ * containing undefined state when pressing the back button.
+ */
+var isExtraneousPopstateEvent = exports.isExtraneousPopstateEvent = function isExtraneousPopstateEvent(event) {
+ return event.state === undefined && navigator.userAgent.indexOf('CriOS') === -1;
+};
/***/ })
/******/ ]);
diff --git a/web/package-lock.json b/web/package-lock.json
index c494f8ca..7862fdee 100755
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -5597,6 +5597,18 @@
"sntp": "1.0.9"
}
},
+ "history": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz",
+ "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==",
+ "requires": {
+ "invariant": "2.2.2",
+ "loose-envify": "1.3.1",
+ "resolve-pathname": "2.2.0",
+ "value-equal": "0.4.0",
+ "warning": "3.0.0"
+ }
+ },
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -5756,7 +5768,6 @@
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
"integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
- "dev": true,
"requires": {
"loose-envify": "1.3.1"
}
@@ -6151,8 +6162,7 @@
"js-tokens": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
- "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
- "dev": true
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
},
"js-yaml": {
"version": "3.10.0",
@@ -6780,7 +6790,6 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
"integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
- "dev": true,
"requires": {
"js-tokens": "3.0.2"
}
@@ -8550,6 +8559,11 @@
"global-modules": "1.0.0"
}
},
+ "resolve-pathname": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz",
+ "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg=="
+ },
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -10098,6 +10112,11 @@
"resolved": "https://registry.npmjs.org/validator/-/validator-9.2.0.tgz",
"integrity": "sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA=="
},
+ "value-equal": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz",
+ "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw=="
+ },
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -10248,6 +10267,14 @@
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
"dev": true
},
+ "warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
+ "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
"watchpack": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz",
diff --git a/web/package.json b/web/package.json
index a369db17..bba81df4 100755
--- a/web/package.json
+++ b/web/package.json
@@ -44,6 +44,7 @@
"webpack": "^3.10.0"
},
"dependencies": {
+ "history": "^4.7.2",
"jquery": "^3.3.1",
"owl.carousel": "^2.2.0",
"validator": "^9.2.0"
diff --git a/web/src/js/app.js b/web/src/js/app.js
index 9eb50dea..20fdb786 100644
--- a/web/src/js/app.js
+++ b/web/src/js/app.js
@@ -10,3 +10,5 @@ import "./modules/select";
// import "./modules/datepicker";
import "./modules/tabs";
import "./modules/popup";
+
+import "./modules/courses";
diff --git a/web/src/js/modules/courses.js b/web/src/js/modules/courses.js
index ce7eebe3..7e0d0e14 100644
--- a/web/src/js/modules/courses.js
+++ b/web/src/js/modules/courses.js
@@ -1,39 +1,53 @@
import $ from 'jquery';
+import createHistory from 'history/createBrowserHistory';
+
+// Создаем объект history API
+const history = createHistory();
$(document).ready(function () {
// Обработчик кнопки "Подгрузить еще"
- $('.courses__list').on('click', 'button.load__btn', function () {
- load_courses($(this).attr('data-next-page-url'), $(this));
+ $('.courses').on('click', 'button.load__btn', function () {
+ load_courses($(this).attr('data-next-page-url'), false);
});
// Обработчик выбора категории
$('div.js-select-option[data-category-option]').on('click', function (e) {
e.preventDefault();
- load_courses($(this).attr('data-category-url'), null);
+ history.replace($(this).attr('data-category-url'));
+ load_courses($(this).attr('data-category-url'), true);
});
});
-function load_courses(coursesUrl, buttonElement) {
- if (buttonElement) {
+function load_courses(coursesUrl, fromStart) {
+ $('.courses__list').css('opacity', '0.9');
+ const buttonElement = $('.courses').find('button.load__btn');
+ if (!fromStart) {
buttonElement.addClass('loading');
- } else {
- $('.courses__list').css('opacity', '0.9');
}
$.ajax(coursesUrl, {
- method: 'GET',
- dataType: 'html',
+ method: 'GET'
})
.done(function (data) {
- $('.courses__list').html(data);
+ if (data.success === true) {
+ if (!fromStart) {
+ $('.courses__list').append(data.content);
+ } else {
+ $('.courses__list').html(data.content);
+ }
+ if (data.next_url) {
+ buttonElement.attr('data-next-page-url', data.next_url)
+ } else {
+ buttonElement.hide()
+ }
+ }
})
.fail(function (xhr) {
- if (buttonElement) {
- buttonElement.removeClass('loading');
- }
+
})
.always(function () {
- if (!buttonElement) {
- $('.courses__list').css('opacity', '1');
+ $('.courses__list').css('opacity', '1');
+ if (buttonElement) {
+ buttonElement.removeClass('loading');
}
});
}
\ No newline at end of file