mirror of
https://github.com/flarum/framework.git
synced 2025-04-02 23:19:04 +08:00
change some typings, rename $.fn.animatedScrollTop to $.fn.animateScrollTop
This commit is contained in:
parent
83d0345e93
commit
0dc846bc4a
3
js/dist/admin.js
vendored
3
js/dist/admin.js
vendored
@ -11812,7 +11812,7 @@ $.fn.hover = function (hover, leave) {
|
|||||||
}; // add animated scroll
|
}; // add animated scroll
|
||||||
|
|
||||||
|
|
||||||
$.fn.animatedScrollTop = function (to, duration, callback) {
|
$.fn.animateScrollTop = function (to, duration, callback) {
|
||||||
if (duration === void 0) {
|
if (duration === void 0) {
|
||||||
duration = $.fx.speeds._default;
|
duration = $.fx.speeds._default;
|
||||||
}
|
}
|
||||||
@ -11848,7 +11848,6 @@ $.fn.extend = $.extend.bind($);
|
|||||||
* Enable special events on Zepto
|
* Enable special events on Zepto
|
||||||
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
|
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
|
||||||
*/
|
*/
|
||||||
// @ts-ignore
|
|
||||||
|
|
||||||
$.event.special = $.event.special || {};
|
$.event.special = $.event.special || {};
|
||||||
var bindBeforeSpecialEvents = $.fn.bind;
|
var bindBeforeSpecialEvents = $.fn.bind;
|
||||||
|
2
js/dist/admin.js.map
vendored
2
js/dist/admin.js.map
vendored
File diff suppressed because one or more lines are too long
104
js/dist/forum.js
vendored
104
js/dist/forum.js
vendored
@ -12767,13 +12767,16 @@ var Application = /*#__PURE__*/function () {
|
|||||||
basePath = '';
|
basePath = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
m.mount(document.getElementById('modal'), this.modal = new _components_ModalManager__WEBPACK_IMPORTED_MODULE_19__["default"]());
|
var $modal = document.getElementById('modal');
|
||||||
m.mount(document.getElementById('alerts'), this.alerts = new _components_AlertManager__WEBPACK_IMPORTED_MODULE_22__["default"]({
|
var $alerts = document.getElementById('alerts');
|
||||||
|
var $content = document.getElementById('content');
|
||||||
|
if ($modal) m.mount($modal, this.modal = new _components_ModalManager__WEBPACK_IMPORTED_MODULE_19__["default"]());
|
||||||
|
if ($alerts) m.mount($alerts, this.alerts = new _components_AlertManager__WEBPACK_IMPORTED_MODULE_22__["default"]({
|
||||||
oninit: function oninit(vnode) {
|
oninit: function oninit(vnode) {
|
||||||
return _this3.alerts = vnode.state;
|
return _this3.alerts = vnode.state;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
m.route(document.getElementById('content'), basePath + '/', Object(_utils_mapRoutes__WEBPACK_IMPORTED_MODULE_6__["default"])(this.routes, basePath)); // Add a class to the body which indicates that the page has been scrolled
|
if ($content) m.route($content, basePath + '/', Object(_utils_mapRoutes__WEBPACK_IMPORTED_MODULE_6__["default"])(this.routes, basePath)); // Add a class to the body which indicates that the page has been scrolled
|
||||||
// down.
|
// down.
|
||||||
|
|
||||||
new _utils_ScrollListener__WEBPACK_IMPORTED_MODULE_10__["default"](function (top) {
|
new _utils_ScrollListener__WEBPACK_IMPORTED_MODULE_10__["default"](function (top) {
|
||||||
@ -13128,8 +13131,6 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/**
|
/**
|
||||||
* The `Model` class represents a local data resource. It provides methods to
|
* The `Model` class represents a local data resource. It provides methods to
|
||||||
* persist changes via the API.
|
* persist changes via the API.
|
||||||
*
|
|
||||||
* @abstract
|
|
||||||
*/
|
*/
|
||||||
var Model = /*#__PURE__*/function () {
|
var Model = /*#__PURE__*/function () {
|
||||||
/**
|
/**
|
||||||
@ -13151,18 +13152,14 @@ var Model = /*#__PURE__*/function () {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data A resource object from the API.
|
* @param data A resource object from the API.
|
||||||
* @param {Store} store The data store that this model should be persisted to.
|
* @param store The data store that this model should be persisted to.
|
||||||
*/
|
*/
|
||||||
function Model(data, store) {
|
function Model(data, store) {
|
||||||
if (data === void 0) {
|
if (data === void 0) {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (store === void 0) {
|
|
||||||
store = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.data = void 0;
|
this.data = void 0;
|
||||||
this.payload = void 0;
|
this.payload = void 0;
|
||||||
this.freshness = void 0;
|
this.freshness = void 0;
|
||||||
@ -13197,7 +13194,6 @@ var Model = /*#__PURE__*/function () {
|
|||||||
* Merge new data into this model locally.
|
* Merge new data into this model locally.
|
||||||
*
|
*
|
||||||
* @param data A resource object to merge into this model
|
* @param data A resource object to merge into this model
|
||||||
* @public
|
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -13232,7 +13228,7 @@ var Model = /*#__PURE__*/function () {
|
|||||||
/**
|
/**
|
||||||
* Merge new attributes into this model locally.
|
* Merge new attributes into this model locally.
|
||||||
*
|
*
|
||||||
* @param {Object} attributes The attributes to merge.
|
* @param attributes The attributes to merge.
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -13247,7 +13243,6 @@ var Model = /*#__PURE__*/function () {
|
|||||||
* @param attributes The attributes to save. If a 'relationships' key
|
* @param attributes The attributes to save. If a 'relationships' key
|
||||||
* exists, it will be extracted and relationships will also be saved.
|
* exists, it will be extracted and relationships will also be saved.
|
||||||
* @param [options]
|
* @param [options]
|
||||||
* @return {Promise}
|
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -13358,7 +13353,7 @@ var Model = /*#__PURE__*/function () {
|
|||||||
/**
|
/**
|
||||||
* Generate a function which returns the value of the given attribute.
|
* Generate a function which returns the value of the given attribute.
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param name
|
||||||
* @param [transform] A function to transform the attribute value
|
* @param [transform] A function to transform the attribute value
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
@ -13384,7 +13379,7 @@ var Model = /*#__PURE__*/function () {
|
|||||||
if (this.data.relationships) {
|
if (this.data.relationships) {
|
||||||
var relationship = this.data.relationships[name];
|
var relationship = this.data.relationships[name];
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship && !Array.isArray(relationship.data)) {
|
||||||
return app.store.getById(relationship.data.type, relationship.data.id);
|
return app.store.getById(relationship.data.type, relationship.data.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13407,7 +13402,7 @@ var Model = /*#__PURE__*/function () {
|
|||||||
if (this.data.relationships) {
|
if (this.data.relationships) {
|
||||||
var relationship = this.data.relationships[name];
|
var relationship = this.data.relationships[name];
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship && Array.isArray(relationship.data)) {
|
||||||
return relationship.data.map(function (data) {
|
return relationship.data.map(function (data) {
|
||||||
return app.store.getById(data.type, data.id);
|
return app.store.getById(data.type, data.id);
|
||||||
});
|
});
|
||||||
@ -13724,10 +13719,6 @@ var Translator = /*#__PURE__*/function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_proto.trans = function trans(id, parameters) {
|
_proto.trans = function trans(id, parameters) {
|
||||||
if (parameters === void 0) {
|
|
||||||
parameters = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var translation = this.translations[id];
|
var translation = this.translations[id];
|
||||||
|
|
||||||
if (translation) {
|
if (translation) {
|
||||||
@ -13738,10 +13729,6 @@ var Translator = /*#__PURE__*/function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_proto.transText = function transText(id, parameters) {
|
_proto.transText = function transText(id, parameters) {
|
||||||
if (parameters === void 0) {
|
|
||||||
parameters = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object(_utils_extractText__WEBPACK_IMPORTED_MODULE_2__["default"])(this.trans(id, parameters));
|
return Object(_utils_extractText__WEBPACK_IMPORTED_MODULE_2__["default"])(this.trans(id, parameters));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13749,7 +13736,6 @@ var Translator = /*#__PURE__*/function () {
|
|||||||
var translation = this.translations[id];
|
var translation = this.translations[id];
|
||||||
|
|
||||||
if (translation) {
|
if (translation) {
|
||||||
number = parseInt(number, 10);
|
|
||||||
translation = this.pluralize(translation, number);
|
translation = this.pluralize(translation, number);
|
||||||
return this.apply(translation, parameters || {});
|
return this.apply(translation, parameters || {});
|
||||||
}
|
}
|
||||||
@ -17256,7 +17242,7 @@ $.fn.hover = function (hover, leave) {
|
|||||||
}; // add animated scroll
|
}; // add animated scroll
|
||||||
|
|
||||||
|
|
||||||
$.fn.animatedScrollTop = function (to, duration, callback) {
|
$.fn.animateScrollTop = function (to, duration, callback) {
|
||||||
if (duration === void 0) {
|
if (duration === void 0) {
|
||||||
duration = $.fx.speeds._default;
|
duration = $.fx.speeds._default;
|
||||||
}
|
}
|
||||||
@ -17292,7 +17278,6 @@ $.fn.extend = $.extend.bind($);
|
|||||||
* Enable special events on Zepto
|
* Enable special events on Zepto
|
||||||
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
|
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
|
||||||
*/
|
*/
|
||||||
// @ts-ignore
|
|
||||||
|
|
||||||
$.event.special = $.event.special || {};
|
$.event.special = $.event.special || {};
|
||||||
var bindBeforeSpecialEvents = $.fn.bind;
|
var bindBeforeSpecialEvents = $.fn.bind;
|
||||||
@ -18815,8 +18800,8 @@ var DiscussionPage = /*#__PURE__*/function (_Page) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_this = _Page.call.apply(_Page, [this].concat(args)) || this;
|
_this = _Page.call.apply(_Page, [this].concat(args)) || this;
|
||||||
_this.discussion = void 0;
|
_this.discussion = null;
|
||||||
_this.near = void 0;
|
_this.near = null;
|
||||||
_this.stream = void 0;
|
_this.stream = void 0;
|
||||||
_this.scrubber = void 0;
|
_this.scrubber = void 0;
|
||||||
_this.includedPosts = [];
|
_this.includedPosts = [];
|
||||||
@ -18999,23 +18984,19 @@ var DiscussionPage = /*#__PURE__*/function (_Page) {
|
|||||||
var $list = $(vnode.dom); // When the mouse enters and leaves the discussions pane, we want to show
|
var $list = $(vnode.dom); // When the mouse enters and leaves the discussions pane, we want to show
|
||||||
// and hide the pane respectively. We also create a 10px 'hot edge' on the
|
// and hide the pane respectively. We also create a 10px 'hot edge' on the
|
||||||
// left of the screen to activate the pane.
|
// left of the screen to activate the pane.
|
||||||
|
// TODO pane
|
||||||
var pane = app.pane;
|
// const pane = app.pane;
|
||||||
$list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
|
// $list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
|
||||||
|
//
|
||||||
var hotEdge = function hotEdge(e) {
|
// const hotEdge = e => {
|
||||||
if (e.pageX < 10) pane.show();
|
// if (e.pageX < 10) pane.show();
|
||||||
};
|
// };
|
||||||
|
// $(document).on('mousemove', hotEdge);
|
||||||
$(document).on('mousemove', hotEdge);
|
// vnode.dom.onunload = () => $(document).off('mousemove', hotEdge);
|
||||||
|
// If the discussion we are viewing is listed in the discussion list, then
|
||||||
vnode.dom.onunload = function () {
|
|
||||||
return $(document).off('mousemove', hotEdge);
|
|
||||||
}; // If the discussion we are viewing is listed in the discussion list, then
|
|
||||||
// we will make sure it is visible in the viewport – if it is not we will
|
// we will make sure it is visible in the viewport – if it is not we will
|
||||||
// scroll the list down to it.
|
// scroll the list down to it.
|
||||||
|
|
||||||
|
|
||||||
var $discussion = $list.find('.DiscussionListItem.active');
|
var $discussion = $list.find('.DiscussionListItem.active');
|
||||||
|
|
||||||
if ($discussion.length) {
|
if ($discussion.length) {
|
||||||
@ -21633,7 +21614,7 @@ var PostStream = /*#__PURE__*/function (_Component) {
|
|||||||
$container.scrollTop(top);
|
$container.scrollTop(top);
|
||||||
resolve();
|
resolve();
|
||||||
} else if (top !== scrollTop) {
|
} else if (top !== scrollTop) {
|
||||||
$container.animatedScrollTop(top, 'fast', resolve);
|
$container.animateScrollTop(top, 'fast', resolve);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
@ -21876,6 +21857,10 @@ var PostStreamScrubber = /*#__PURE__*/function (_Component) {
|
|||||||
;
|
;
|
||||||
|
|
||||||
_proto.update = function update(scrollTop) {
|
_proto.update = function update(scrollTop) {
|
||||||
|
if (scrollTop === void 0) {
|
||||||
|
scrollTop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
var stream = this.stream;
|
var stream = this.stream;
|
||||||
var marginTop = stream.getMarginTop();
|
var marginTop = stream.getMarginTop();
|
||||||
var viewportTop = scrollTop + marginTop;
|
var viewportTop = scrollTop + marginTop;
|
||||||
@ -21924,6 +21909,7 @@ var PostStreamScrubber = /*#__PURE__*/function (_Component) {
|
|||||||
|
|
||||||
var time = $this.data('time');
|
var time = $this.data('time');
|
||||||
if (time) period = time;
|
if (time) period = time;
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.visible = visible;
|
this.visible = visible;
|
||||||
@ -22544,11 +22530,11 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
|
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
|
||||||
_this.value = m.prop('');
|
_this.value = m.prop('');
|
||||||
_this.hasFocus = false;
|
_this.hasFocus = false;
|
||||||
_this.sources = null;
|
_this.sources = void 0;
|
||||||
_this.loadingSources = 0;
|
_this.loadingSources = 0;
|
||||||
_this.searched = [];
|
_this.searched = [];
|
||||||
_this.index = 0;
|
_this.index = 0;
|
||||||
_this.navigator = void 0;
|
_this.navigator = new _utils_KeyboardNavigatable__WEBPACK_IMPORTED_MODULE_4__["default"]();
|
||||||
_this.searchTimeout = void 0;
|
_this.searchTimeout = void 0;
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
@ -22619,7 +22605,6 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
search.setIndex(search.selectableItems().index(this));
|
search.setIndex(search.selectableItems().index(this));
|
||||||
});
|
});
|
||||||
var $input = this.$('input');
|
var $input = this.$('input');
|
||||||
this.navigator = new _utils_KeyboardNavigatable__WEBPACK_IMPORTED_MODULE_4__["default"]();
|
|
||||||
this.navigator.onUp(function () {
|
this.navigator.onUp(function () {
|
||||||
return _this3.setIndex(_this3.getCurrentNumericIndex() - 1, true);
|
return _this3.setIndex(_this3.getCurrentNumericIndex() - 1, true);
|
||||||
}).onDown(function () {
|
}).onDown(function () {
|
||||||
@ -22633,7 +22618,7 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
search.searchTimeout = setTimeout(function () {
|
search.searchTimeout = setTimeout(function () {
|
||||||
if (search.searched.indexOf(query) !== -1) return;
|
if (search.searched.indexOf(query) !== -1) return;
|
||||||
|
|
||||||
if (query.length >= 3) {
|
if (query.length >= 3 && search.sources) {
|
||||||
search.sources.map(function (source) {
|
search.sources.map(function (source) {
|
||||||
if (!source.search) return;
|
if (!source.search) return;
|
||||||
search.loadingSources++;
|
search.loadingSources++;
|
||||||
@ -22655,8 +22640,6 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the active search in the app's current controller.
|
* Get the active search in the app's current controller.
|
||||||
*
|
|
||||||
* @return {String}
|
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -22709,8 +22692,6 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get all of the search result items that are selectable.
|
* Get all of the search result items that are selectable.
|
||||||
*
|
|
||||||
* @return {jQuery}
|
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -22719,8 +22700,6 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the position of the currently selected search result item.
|
* Get the position of the currently selected search result item.
|
||||||
*
|
|
||||||
* @return {Integer}
|
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -22729,9 +22708,6 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the <li> in the search results with the given index (numeric or named).
|
* Get the <li> in the search results with the given index (numeric or named).
|
||||||
*
|
|
||||||
* @param {String} index
|
|
||||||
* @return {DOMElement}
|
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -22767,7 +22743,7 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var $item = $items.removeClass('active').eq(fixedIndex).addClass('active');
|
var $item = $items.removeClass('active').eq(fixedIndex).addClass('active');
|
||||||
this.index = $item.attr('data-index') || fixedIndex;
|
this.index = Number($item.attr('data-index') || fixedIndex);
|
||||||
|
|
||||||
if (scrollToItem) {
|
if (scrollToItem) {
|
||||||
var dropdownScroll = $dropdown.scrollTop();
|
var dropdownScroll = $dropdown.scrollTop();
|
||||||
@ -22784,9 +22760,7 @@ var Search = /*#__PURE__*/function (_Component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof scrollTop !== 'undefined') {
|
if (typeof scrollTop !== 'undefined') {
|
||||||
$dropdown.animate({
|
$dropdown.animateScrollTop(scrollTop, 100);
|
||||||
scrollTop: scrollTop
|
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -24215,9 +24189,9 @@ var History = /*#__PURE__*/function () {
|
|||||||
/**
|
/**
|
||||||
* Push an item to the top of the stack.
|
* Push an item to the top of the stack.
|
||||||
*
|
*
|
||||||
* @param {String} name The name of the route.
|
* @param name The name of the route.
|
||||||
* @param {String} title The title of the route.
|
* @param title The title of the route.
|
||||||
* @param {String} [url] The URL of the route. The current URL will be used if
|
* @param [url] The URL of the route. The current URL will be used if
|
||||||
* not provided.
|
* not provided.
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
|
2
js/dist/forum.js.map
vendored
2
js/dist/forum.js.map
vendored
File diff suppressed because one or more lines are too long
@ -139,11 +139,15 @@ export default abstract class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mount(basePath = '') {
|
mount(basePath = '') {
|
||||||
m.mount(document.getElementById('modal'), (this.modal = new ModalManager()));
|
const $modal = document.getElementById('modal');
|
||||||
|
const $alerts = document.getElementById('alerts');
|
||||||
|
const $content = document.getElementById('content');
|
||||||
|
|
||||||
m.mount(document.getElementById('alerts'), (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) })));
|
if ($modal) m.mount($modal, (this.modal = new ModalManager()));
|
||||||
|
|
||||||
m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath));
|
if ($alerts) m.mount($alerts, (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) })));
|
||||||
|
|
||||||
|
if ($content) m.route($content, basePath + '/', mapRoutes(this.routes, basePath));
|
||||||
|
|
||||||
// Add a class to the body which indicates that the page has been scrolled
|
// Add a class to the body which indicates that the page has been scrolled
|
||||||
// down.
|
// down.
|
||||||
@ -210,7 +214,7 @@ export default abstract class Application {
|
|||||||
if (params.hasOwnProperty(key) && !params[key]) delete params[key];
|
if (params.hasOwnProperty(key) && !params[key]) delete params[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryString = m.buildQueryString(params);
|
const queryString = m.buildQueryString(params as Mithril.Params);
|
||||||
const prefix = m.route.prefix === '' ? this.forum.attribute('basePath') : '';
|
const prefix = m.route.prefix === '' ? this.forum.attribute('basePath') : '';
|
||||||
|
|
||||||
return prefix + url + (queryString ? '?' + queryString : '');
|
return prefix + url + (queryString ? '?' + queryString : '');
|
||||||
@ -221,8 +225,8 @@ export default abstract class Application {
|
|||||||
*
|
*
|
||||||
* @see https://mithril.js.org/request.html
|
* @see https://mithril.js.org/request.html
|
||||||
*/
|
*/
|
||||||
request(originalOptions: Mithril.RequestOptions | any): Promise<any> {
|
request(originalOptions: Mithril.RequestOptions<JSON> | any): Promise<any> {
|
||||||
const options: Mithril.RequestOptions = Object.assign({}, originalOptions);
|
const options: Mithril.RequestOptions<JSON> | any = Object.assign({}, originalOptions);
|
||||||
|
|
||||||
// Set some default options if they haven't been overridden. We want to
|
// Set some default options if they haven't been overridden. We want to
|
||||||
// authenticate all requests with the session token. We also want all
|
// authenticate all requests with the session token. We also want all
|
||||||
@ -230,7 +234,7 @@ export default abstract class Application {
|
|||||||
// prevent redraws from occurring.
|
// prevent redraws from occurring.
|
||||||
options.background = options.background || true;
|
options.background = options.background || true;
|
||||||
|
|
||||||
extend(options, 'config', (result, xhr: XMLHttpRequest) => xhr.setRequestHeader('X-CSRF-Token', this.session.csrfToken));
|
extend(options, 'config', (result, xhr: XMLHttpRequest) => xhr.setRequestHeader('X-CSRF-Token', this.session.csrfToken!));
|
||||||
|
|
||||||
// If the method is something like PATCH or DELETE, which not all servers
|
// If the method is something like PATCH or DELETE, which not all servers
|
||||||
// and clients support, then we'll send it as a POST request with the
|
// and clients support, then we'll send it as a POST request with the
|
||||||
@ -347,7 +351,7 @@ export default abstract class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private showDebug(error: RequestError) {
|
private showDebug(error: RequestError) {
|
||||||
this.alerts.dismiss(this.requestError.alert);
|
this.alerts.dismiss(this.requestError!.alert);
|
||||||
|
|
||||||
this.modal.show(RequestErrorModal, { error });
|
this.modal.show(RequestErrorModal, { error });
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export default class Component<T extends ComponentProps = any> implements ClassC
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return m(this.constructor, this.props);
|
return m(this.constructor as typeof Component, this.props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static component(props: ComponentProps | any = {}, children?: Mithril.Children) {
|
static component(props: ComponentProps | any = {}, children?: Mithril.Children) {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/**
|
|
||||||
* The `Model` class represents a local data resource. It provides methods to
|
|
||||||
* persist changes via the API.
|
|
||||||
*
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
import Store from './Store';
|
import Store from './Store';
|
||||||
|
|
||||||
export interface Identifier {
|
export interface Identifier {
|
||||||
@ -16,7 +10,11 @@ export interface Data extends Identifier {
|
|||||||
relationships?: { [key: string]: { data: Identifier | Identifier[] } };
|
relationships?: { [key: string]: { data: Identifier | Identifier[] } };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Model {
|
/**
|
||||||
|
* The `Model` class represents a local data resource. It provides methods to
|
||||||
|
* persist changes via the API.
|
||||||
|
*/
|
||||||
|
export default abstract class Model {
|
||||||
/**
|
/**
|
||||||
* The resource object from the API.
|
* The resource object from the API.
|
||||||
*/
|
*/
|
||||||
@ -39,13 +37,13 @@ export default class Model {
|
|||||||
/**
|
/**
|
||||||
* The data store that this resource should be persisted to.
|
* The data store that this resource should be persisted to.
|
||||||
*/
|
*/
|
||||||
protected store: Store;
|
protected store?: Store;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data A resource object from the API.
|
* @param data A resource object from the API.
|
||||||
* @param {Store} store The data store that this model should be persisted to.
|
* @param store The data store that this model should be persisted to.
|
||||||
*/
|
*/
|
||||||
constructor(data = {}, store = null) {
|
constructor(data = <Data>{}, store?: Store) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.store = store;
|
this.store = store;
|
||||||
|
|
||||||
@ -73,9 +71,8 @@ export default class Model {
|
|||||||
* Merge new data into this model locally.
|
* Merge new data into this model locally.
|
||||||
*
|
*
|
||||||
* @param data A resource object to merge into this model
|
* @param data A resource object to merge into this model
|
||||||
* @public
|
|
||||||
*/
|
*/
|
||||||
pushData(data: {}) {
|
public pushData(data: {}) {
|
||||||
// Since most of the top-level items in a resource object are objects
|
// Since most of the top-level items in a resource object are objects
|
||||||
// (e.g. relationships, attributes), we'll need to check and perform the
|
// (e.g. relationships, attributes), we'll need to check and perform the
|
||||||
// merge at the second level if that's the case.
|
// merge at the second level if that's the case.
|
||||||
@ -105,7 +102,7 @@ export default class Model {
|
|||||||
/**
|
/**
|
||||||
* Merge new attributes into this model locally.
|
* Merge new attributes into this model locally.
|
||||||
*
|
*
|
||||||
* @param {Object} attributes The attributes to merge.
|
* @param attributes The attributes to merge.
|
||||||
*/
|
*/
|
||||||
pushAttributes(attributes: any) {
|
pushAttributes(attributes: any) {
|
||||||
this.pushData({ attributes });
|
this.pushData({ attributes });
|
||||||
@ -117,7 +114,6 @@ export default class Model {
|
|||||||
* @param attributes The attributes to save. If a 'relationships' key
|
* @param attributes The attributes to save. If a 'relationships' key
|
||||||
* exists, it will be extracted and relationships will also be saved.
|
* exists, it will be extracted and relationships will also be saved.
|
||||||
* @param [options]
|
* @param [options]
|
||||||
* @return {Promise}
|
|
||||||
*/
|
*/
|
||||||
save(attributes: any, options: any = {}): Promise<Model | Model[]> {
|
save(attributes: any, options: any = {}): Promise<Model | Model[]> {
|
||||||
const data: Data = {
|
const data: Data = {
|
||||||
@ -208,7 +204,7 @@ export default class Model {
|
|||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.exists = false;
|
this.exists = false;
|
||||||
this.store.remove(this);
|
this.store!.remove(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +225,7 @@ export default class Model {
|
|||||||
/**
|
/**
|
||||||
* Generate a function which returns the value of the given attribute.
|
* Generate a function which returns the value of the given attribute.
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param name
|
||||||
* @param [transform] A function to transform the attribute value
|
* @param [transform] A function to transform the attribute value
|
||||||
*/
|
*/
|
||||||
static attribute(name: string, transform?: Function): () => any {
|
static attribute(name: string, transform?: Function): () => any {
|
||||||
@ -253,7 +249,7 @@ export default class Model {
|
|||||||
if (this.data.relationships) {
|
if (this.data.relationships) {
|
||||||
const relationship = this.data.relationships[name];
|
const relationship = this.data.relationships[name];
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship && !Array.isArray(relationship.data)) {
|
||||||
return app.store.getById(relationship.data.type, relationship.data.id);
|
return app.store.getById(relationship.data.type, relationship.data.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +271,7 @@ export default class Model {
|
|||||||
if (this.data.relationships) {
|
if (this.data.relationships) {
|
||||||
const relationship = this.data.relationships[name];
|
const relationship = this.data.relationships[name];
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship && Array.isArray(relationship.data)) {
|
||||||
return relationship.data.map(data => app.store.getById(data.type, data.id));
|
return relationship.data.map(data => app.store.getById(data.type, data.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ export default class Store {
|
|||||||
* @param query
|
* @param query
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
find<T extends Model = Model>(type: string, id?: number | number[] | any, query = {}, options = {}): Promise<T[]> {
|
find<T extends Model = Model>(type: string, id?: number | number[] | any, query = {}, options = {}): Promise<T | T[]> {
|
||||||
let params = query;
|
let params = query;
|
||||||
let url = `${app.forum.attribute('apiUrl')}/${type}`;
|
let url = `${app.forum.attribute('apiUrl')}/${type}`;
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ export default class Store {
|
|||||||
url += `/${id}`;
|
url += `/${id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Promise<T[]>>app
|
return <Promise<T | T[]>>app
|
||||||
.request(
|
.request(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ export default class Translator {
|
|||||||
Object.assign(this.translations, translations);
|
Object.assign(this.translations, translations);
|
||||||
}
|
}
|
||||||
|
|
||||||
trans(id: string, parameters = null) {
|
trans(id: string, parameters?: any): string | any[] {
|
||||||
const translation = this.translations[id];
|
const translation = this.translations[id];
|
||||||
|
|
||||||
if (translation) {
|
if (translation) {
|
||||||
@ -25,16 +25,14 @@ export default class Translator {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
transText(id: string, parameters = null) {
|
transText(id: string, parameters?: any): string {
|
||||||
return extractText(this.trans(id, parameters));
|
return extractText(this.trans(id, parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
transChoice(id: string, number: string | number, parameters: any) {
|
transChoice(id: string, number: number, parameters: any): string | any[] {
|
||||||
let translation = this.translations[id];
|
let translation: string = this.translations[id];
|
||||||
|
|
||||||
if (translation) {
|
if (translation) {
|
||||||
number = parseInt(number, 10);
|
|
||||||
|
|
||||||
translation = this.pluralize(translation, number);
|
translation = this.pluralize(translation, number);
|
||||||
|
|
||||||
return this.apply(translation, parameters || {});
|
return this.apply(translation, parameters || {});
|
||||||
@ -77,7 +75,7 @@ export default class Translator {
|
|||||||
return hydrated.filter(part => part);
|
return hydrated.filter(part => part);
|
||||||
}
|
}
|
||||||
|
|
||||||
pluralize(translation: string, number: number) {
|
pluralize(translation: string, number: number): string | undefined {
|
||||||
const sPluralRegex = new RegExp(/^\w+\: +(.+)$/),
|
const sPluralRegex = new RegExp(/^\w+\: +(.+)$/),
|
||||||
cPluralRegex = new RegExp(
|
cPluralRegex = new RegExp(
|
||||||
/^\s*((\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]]))\s?(.+?)$/
|
/^\s*((\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]]))\s?(.+?)$/
|
||||||
@ -137,7 +135,7 @@ export default class Translator {
|
|||||||
return parseInt(number, 10);
|
return parseInt(number, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
pluralPosition(number: number, locale: string) {
|
pluralPosition(number: number, locale: string): number {
|
||||||
if ('pt_BR' === locale) {
|
if ('pt_BR' === locale) {
|
||||||
locale = 'xbr';
|
locale = 'xbr';
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* @param element The element to anchor the scroll position to.
|
* @param element The element to anchor the scroll position to.
|
||||||
* @param callback The callback to run that will change page content.
|
* @param callback The callback to run that will change page content.
|
||||||
*/
|
*/
|
||||||
export default function anchorScroll(element: Element, callback: Function) {
|
export default function anchorScroll(element: HTMLElement, callback: Function) {
|
||||||
const $window = $(window);
|
const $window = $(window);
|
||||||
const $el = $(element);
|
const $el = $(element);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import Tooltip from 'tooltip.js';
|
|||||||
|
|
||||||
// add $.fn.tooltip
|
// add $.fn.tooltip
|
||||||
$.fn.tooltip = function(option) {
|
$.fn.tooltip = function(option) {
|
||||||
return this.each(function() {
|
return this.each(function(this: HTMLElement) {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
let data = $this.data('bs.tooltip');
|
let data = $this.data('bs.tooltip');
|
||||||
const options = (typeof option === 'object' && option) || {};
|
const options = (typeof option === 'object' && option) || {};
|
||||||
@ -59,7 +59,7 @@ $.fn.hover = function(hover, leave) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// add animated scroll
|
// add animated scroll
|
||||||
$.fn.animatedScrollTop = function(to, duration = $.fx.speeds._default, callback) {
|
$.fn.animateScrollTop = function(to, duration = $.fx.speeds._default, callback) {
|
||||||
if (typeof to === 'number') to -= window.scrollY || window.pageYOffset;
|
if (typeof to === 'number') to -= window.scrollY || window.pageYOffset;
|
||||||
|
|
||||||
jump(to, {
|
jump(to, {
|
||||||
@ -94,7 +94,6 @@ $.fn.extend = $.extend.bind($);
|
|||||||
* Enable special events on Zepto
|
* Enable special events on Zepto
|
||||||
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
|
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
|
||||||
*/
|
*/
|
||||||
// @ts-ignore
|
|
||||||
$.event.special = $.event.special || {};
|
$.event.special = $.event.special || {};
|
||||||
|
|
||||||
const bindBeforeSpecialEvents = $.fn.bind;
|
const bindBeforeSpecialEvents = $.fn.bind;
|
||||||
|
@ -18,12 +18,12 @@ export default class DiscussionPage extends Page {
|
|||||||
/**
|
/**
|
||||||
* The discussion that is being viewed.
|
* The discussion that is being viewed.
|
||||||
*/
|
*/
|
||||||
discussion?: Discussion;
|
discussion: Discussion | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of the first post that is currently visible in the viewport.
|
* The number of the first post that is currently visible in the viewport.
|
||||||
*/
|
*/
|
||||||
near?: number;
|
near: number | null = null;
|
||||||
|
|
||||||
stream!: PostStream;
|
stream!: PostStream;
|
||||||
scrubber!: PostStreamScrubber;
|
scrubber!: PostStreamScrubber;
|
||||||
@ -155,7 +155,7 @@ export default class DiscussionPage extends Page {
|
|||||||
// component for the first time on page load, then any calls to m.redraw
|
// component for the first time on page load, then any calls to m.redraw
|
||||||
// will be ineffective and thus any configs (scroll code) will be run
|
// will be ineffective and thus any configs (scroll code) will be run
|
||||||
// before stuff is drawn to the page.
|
// before stuff is drawn to the page.
|
||||||
setTimeout(this.show.bind(this, preloadedDiscussion), 0);
|
setTimeout(this.show.bind(this, preloadedDiscussion as Discussion), 0);
|
||||||
} else {
|
} else {
|
||||||
const params = this.requestParams();
|
const params = this.requestParams();
|
||||||
|
|
||||||
@ -219,14 +219,16 @@ export default class DiscussionPage extends Page {
|
|||||||
// When the mouse enters and leaves the discussions pane, we want to show
|
// When the mouse enters and leaves the discussions pane, we want to show
|
||||||
// and hide the pane respectively. We also create a 10px 'hot edge' on the
|
// and hide the pane respectively. We also create a 10px 'hot edge' on the
|
||||||
// left of the screen to activate the pane.
|
// left of the screen to activate the pane.
|
||||||
const pane = app.pane;
|
|
||||||
$list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
|
|
||||||
|
|
||||||
const hotEdge = e => {
|
// TODO pane
|
||||||
if (e.pageX < 10) pane.show();
|
// const pane = app.pane;
|
||||||
};
|
// $list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
|
||||||
$(document).on('mousemove', hotEdge);
|
//
|
||||||
vnode.dom.onunload = () => $(document).off('mousemove', hotEdge);
|
// const hotEdge = e => {
|
||||||
|
// if (e.pageX < 10) pane.show();
|
||||||
|
// };
|
||||||
|
// $(document).on('mousemove', hotEdge);
|
||||||
|
// vnode.dom.onunload = () => $(document).off('mousemove', hotEdge);
|
||||||
|
|
||||||
// If the discussion we are viewing is listed in the discussion list, then
|
// If the discussion we are viewing is listed in the discussion list, then
|
||||||
// we will make sure it is visible in the viewport – if it is not we will
|
// we will make sure it is visible in the viewport – if it is not we will
|
||||||
|
@ -13,7 +13,7 @@ export default class PostMeta extends Component<PostProp> {
|
|||||||
|
|
||||||
// When the dropdown menu is shown, select the contents of the permalink
|
// When the dropdown menu is shown, select the contents of the permalink
|
||||||
// input so that the user can quickly copy the URL.
|
// input so that the user can quickly copy the URL.
|
||||||
const selectPermalink = function(this: Element) {
|
const selectPermalink = function(this: HTMLElement) {
|
||||||
setTimeout(() =>
|
setTimeout(() =>
|
||||||
$(this)
|
$(this)
|
||||||
.parent()
|
.parent()
|
||||||
|
@ -470,7 +470,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
let startNumber;
|
let startNumber;
|
||||||
let endNumber;
|
let endNumber;
|
||||||
|
|
||||||
this.$('.PostStream-item').each((index, item: Element) => {
|
this.$('.PostStream-item').each((index, item: HTMLElement) => {
|
||||||
const $item = $(item);
|
const $item = $(item);
|
||||||
const top = $item.offset().top;
|
const top = $item.offset().top;
|
||||||
const height = $item.outerHeight(true);
|
const height = $item.outerHeight(true);
|
||||||
@ -557,7 +557,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
$container.scrollTop(top);
|
$container.scrollTop(top);
|
||||||
resolve();
|
resolve();
|
||||||
} else if (top !== scrollTop) {
|
} else if (top !== scrollTop) {
|
||||||
$container.animatedScrollTop(top, 'fast', resolve);
|
$container.animateScrollTop(top, 'fast', resolve);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
|
|||||||
import formatNumber from '../../common/utils/formatNumber';
|
import formatNumber from '../../common/utils/formatNumber';
|
||||||
import PostStream from './PostStream';
|
import PostStream from './PostStream';
|
||||||
import { EventHandler } from '../../common/utils/Evented';
|
import { EventHandler } from '../../common/utils/Evented';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `PostStreamScrubber` component displays a scrubber which can be used to
|
* The `PostStreamScrubber` component displays a scrubber which can be used to
|
||||||
* navigate/scrub through a post stream.
|
* navigate/scrub through a post stream.
|
||||||
@ -176,7 +177,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
* Update the index/visible/description properties according to the window's
|
* Update the index/visible/description properties according to the window's
|
||||||
* current scroll position.
|
* current scroll position.
|
||||||
*/
|
*/
|
||||||
update(scrollTop?: number) {
|
update(scrollTop: number = 0) {
|
||||||
const stream = this.stream;
|
const stream = this.stream;
|
||||||
|
|
||||||
const marginTop = stream.getMarginTop();
|
const marginTop = stream.getMarginTop();
|
||||||
@ -195,7 +196,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
// Now loop through each of the items in the discussion. An 'item' is
|
// Now loop through each of the items in the discussion. An 'item' is
|
||||||
// either a single post or a 'gap' of one or more posts that haven't
|
// either a single post or a 'gap' of one or more posts that haven't
|
||||||
// been loaded yet.
|
// been loaded yet.
|
||||||
$items.each(function() {
|
$items.each(function(this: HTMLElement) {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
const top = $this.offset().top;
|
const top = $this.offset().top;
|
||||||
const height = $this.outerHeight(true);
|
const height = $this.outerHeight(true);
|
||||||
@ -228,6 +229,8 @@ export default class PostStreamScrubber extends Component {
|
|||||||
// scrollbar's current period to a formatted version of this time.
|
// scrollbar's current period to a formatted version of this time.
|
||||||
const time = $this.data('time');
|
const time = $this.data('time');
|
||||||
if (time) period = time;
|
if (time) period = time;
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
@ -269,7 +272,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
|
|
||||||
this.$('.Scrubber-handle')
|
this.$('.Scrubber-handle')
|
||||||
.css('cursor', 'move')
|
.css('cursor', 'move')
|
||||||
.on('mousedown touchstart', this.onmousedown.bind(this))
|
.on('mousedown touchstart', this.onmousedown.bind(this) as ZeptoEventHandler)
|
||||||
|
|
||||||
// Exempt the scrollbar handle from the 'jump to' click event.
|
// Exempt the scrollbar handle from the 'jump to' click event.
|
||||||
.click(e => e.stopPropagation());
|
.click(e => e.stopPropagation());
|
||||||
@ -279,7 +282,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
// some event handlers. These handlers will move the scrollbar/stream-
|
// some event handlers. These handlers will move the scrollbar/stream-
|
||||||
// content as appropriate.
|
// content as appropriate.
|
||||||
$(document)
|
$(document)
|
||||||
.on('mousemove touchmove', (this.handlers.onmousemove = this.onmousemove.bind(this)))
|
.on('mousemove touchmove', (this.handlers.onmousemove = this.onmousemove.bind(this) as ZeptoEventHandler))
|
||||||
.on('mouseup touchend', (this.handlers.onmouseup = this.onmouseup.bind(this)));
|
.on('mouseup touchend', (this.handlers.onmouseup = this.onmouseup.bind(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +313,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
$scrubber.find('.Scrubber-description').text(this.description);
|
$scrubber.find('.Scrubber-description').text(this.description);
|
||||||
$scrubber.toggleClass('disabled', this.disabled());
|
$scrubber.toggleClass('disabled', this.disabled());
|
||||||
|
|
||||||
const heights = {};
|
const heights: { before?: number; handle?: number; after?: number } = {};
|
||||||
heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
|
heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
|
||||||
heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible);
|
heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible);
|
||||||
heights.after = 100 - heights.before - heights.handle;
|
heights.after = 100 - heights.before - heights.handle;
|
||||||
|
@ -32,7 +32,7 @@ export default class Search extends Component {
|
|||||||
/**
|
/**
|
||||||
* An array of SearchSources.
|
* An array of SearchSources.
|
||||||
*/
|
*/
|
||||||
sources: SearchSource[] = null;
|
sources?: SearchSource[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of sources that are still loading results.
|
* The number of sources that are still loading results.
|
||||||
@ -50,11 +50,11 @@ export default class Search extends Component {
|
|||||||
* around as new results load), but otherwise it will be numeric (the
|
* around as new results load), but otherwise it will be numeric (the
|
||||||
* sequential position within the list).
|
* sequential position within the list).
|
||||||
*/
|
*/
|
||||||
index: string | number = 0;
|
index: number = 0;
|
||||||
|
|
||||||
navigator: KeyboardNavigatable;
|
navigator: KeyboardNavigatable = new KeyboardNavigatable();
|
||||||
|
|
||||||
searchTimeout: number;
|
searchTimeout?: number;
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
const currentSearch = this.getCurrentSearch();
|
const currentSearch = this.getCurrentSearch();
|
||||||
@ -124,14 +124,12 @@ export default class Search extends Component {
|
|||||||
.on('click', () => this.$('input').blur())
|
.on('click', () => this.$('input').blur())
|
||||||
|
|
||||||
// Whenever the mouse is hovered over a search result, highlight it.
|
// Whenever the mouse is hovered over a search result, highlight it.
|
||||||
.on('mouseenter', '> li:not(.Dropdown-header)', function() {
|
.on('mouseenter', '> li:not(.Dropdown-header)', function(this: HTMLElement) {
|
||||||
search.setIndex(search.selectableItems().index(this));
|
search.setIndex(search.selectableItems().index(this));
|
||||||
});
|
});
|
||||||
|
|
||||||
const $input = this.$('input');
|
const $input = this.$('input');
|
||||||
|
|
||||||
this.navigator = new KeyboardNavigatable();
|
|
||||||
|
|
||||||
this.navigator
|
this.navigator
|
||||||
.onUp(() => this.setIndex(this.getCurrentNumericIndex() - 1, true))
|
.onUp(() => this.setIndex(this.getCurrentNumericIndex() - 1, true))
|
||||||
.onDown(() => this.setIndex(this.getCurrentNumericIndex() + 1, true))
|
.onDown(() => this.setIndex(this.getCurrentNumericIndex() + 1, true))
|
||||||
@ -150,7 +148,7 @@ export default class Search extends Component {
|
|||||||
search.searchTimeout = setTimeout(() => {
|
search.searchTimeout = setTimeout(() => {
|
||||||
if (search.searched.indexOf(query) !== -1) return;
|
if (search.searched.indexOf(query) !== -1) return;
|
||||||
|
|
||||||
if (query.length >= 3) {
|
if (query.length >= 3 && search.sources) {
|
||||||
search.sources.map(source => {
|
search.sources.map(source => {
|
||||||
if (!source.search) return;
|
if (!source.search) return;
|
||||||
|
|
||||||
@ -168,7 +166,7 @@ export default class Search extends Component {
|
|||||||
}, 250);
|
}, 250);
|
||||||
})
|
})
|
||||||
|
|
||||||
.on('focus', function() {
|
.on('focus', function(this: HTMLElement) {
|
||||||
$(this)
|
$(this)
|
||||||
.one('mouseup', e => e.preventDefault())
|
.one('mouseup', e => e.preventDefault())
|
||||||
.select();
|
.select();
|
||||||
@ -177,10 +175,8 @@ export default class Search extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the active search in the app's current controller.
|
* Get the active search in the app's current controller.
|
||||||
*
|
|
||||||
* @return {String}
|
|
||||||
*/
|
*/
|
||||||
getCurrentSearch() {
|
getCurrentSearch(): string | false {
|
||||||
return app.current && typeof app.current.searching === 'function' && app.current.searching();
|
return app.current && typeof app.current.searching === 'function' && app.current.searching();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,8 +229,6 @@ export default class Search extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all of the search result items that are selectable.
|
* Get all of the search result items that are selectable.
|
||||||
*
|
|
||||||
* @return {jQuery}
|
|
||||||
*/
|
*/
|
||||||
selectableItems() {
|
selectableItems() {
|
||||||
return this.$('.Search-results > li:not(.Dropdown-header)');
|
return this.$('.Search-results > li:not(.Dropdown-header)');
|
||||||
@ -242,20 +236,15 @@ export default class Search extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the position of the currently selected search result item.
|
* Get the position of the currently selected search result item.
|
||||||
*
|
|
||||||
* @return {Integer}
|
|
||||||
*/
|
*/
|
||||||
getCurrentNumericIndex() {
|
getCurrentNumericIndex(): number {
|
||||||
return this.selectableItems().index(this.getItem(this.index));
|
return this.selectableItems().index(this.getItem(this.index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the <li> in the search results with the given index (numeric or named).
|
* Get the <li> in the search results with the given index (numeric or named).
|
||||||
*
|
|
||||||
* @param {String} index
|
|
||||||
* @return {DOMElement}
|
|
||||||
*/
|
*/
|
||||||
getItem(index) {
|
getItem(index: number): ZeptoCollection {
|
||||||
const $items = this.selectableItems();
|
const $items = this.selectableItems();
|
||||||
let $item = $items.filter(`[data-index="${index}"]`);
|
let $item = $items.filter(`[data-index="${index}"]`);
|
||||||
|
|
||||||
@ -290,7 +279,7 @@ export default class Search extends Component {
|
|||||||
.eq(fixedIndex)
|
.eq(fixedIndex)
|
||||||
.addClass('active');
|
.addClass('active');
|
||||||
|
|
||||||
this.index = $item.attr('data-index') || fixedIndex;
|
this.index = Number($item.attr('data-index') || fixedIndex);
|
||||||
|
|
||||||
if (scrollToItem) {
|
if (scrollToItem) {
|
||||||
const dropdownScroll = $dropdown.scrollTop();
|
const dropdownScroll = $dropdown.scrollTop();
|
||||||
@ -307,7 +296,7 @@ export default class Search extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof scrollTop !== 'undefined') {
|
if (typeof scrollTop !== 'undefined') {
|
||||||
$dropdown.animate({ scrollTop }, 100);
|
$dropdown.animateScrollTop(scrollTop, 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export interface StackItem {
|
export interface StackItem {
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title?: string;
|
||||||
url?: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,9 +38,9 @@ export default class History {
|
|||||||
/**
|
/**
|
||||||
* Push an item to the top of the stack.
|
* Push an item to the top of the stack.
|
||||||
*
|
*
|
||||||
* @param {String} name The name of the route.
|
* @param name The name of the route.
|
||||||
* @param {String} title The title of the route.
|
* @param title The title of the route.
|
||||||
* @param {String} [url] The URL of the route. The current URL will be used if
|
* @param [url] The URL of the route. The current URL will be used if
|
||||||
* not provided.
|
* not provided.
|
||||||
*/
|
*/
|
||||||
push(name: string, title?: string, url: string = m.route.get()) {
|
push(name: string, title?: string, url: string = m.route.get()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user