mirror of
https://github.com/discourse/discourse.git
synced 2025-02-16 08:15:00 +00:00
performance/memory optimizations
This commit is contained in:
parent
2a0dcedb3d
commit
6a4d74d9f8
@ -12,41 +12,30 @@ export const EMOJI_USAGE = "emojiUsage";
|
|||||||
export const EMOJI_SCROLL_Y = "emojiScrollY";
|
export const EMOJI_SCROLL_Y = "emojiScrollY";
|
||||||
export const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity";
|
export const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity";
|
||||||
const PER_ROW = 11;
|
const PER_ROW = 11;
|
||||||
|
const customEmojis = _.map(_.keys(extendedEmojiList()), function(code) {
|
||||||
|
return { code, src: emojiUrlFor(code) };
|
||||||
|
});
|
||||||
|
let $picker, $modal, $filter, $results, $list;
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
customEmojis: _.map(_.keys(extendedEmojiList()), function(code) {
|
|
||||||
return { code, src: emojiUrlFor(code) };
|
|
||||||
}),
|
|
||||||
|
|
||||||
$picker: Ember.computed("active", function() {
|
|
||||||
return this.$(".emoji-picker");
|
|
||||||
}),
|
|
||||||
|
|
||||||
$filter: Ember.computed("$picker", function() {
|
|
||||||
return this.get("$picker").find(".filter");
|
|
||||||
}),
|
|
||||||
|
|
||||||
$results: Ember.computed("$picker", function() {
|
|
||||||
return this.get("$picker").find(".results");
|
|
||||||
}),
|
|
||||||
|
|
||||||
$list: Ember.computed("$picker", function() {
|
|
||||||
return this.get("$picker").find(".list");
|
|
||||||
}),
|
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
this._unbindEvents();
|
this._unbindEvents();
|
||||||
|
|
||||||
|
$picker = null;
|
||||||
|
$modal = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
|
$picker = this.$(".emoji-picker");
|
||||||
|
$modal = this.$(".emoji-picker-modal");
|
||||||
|
|
||||||
if (!keyValueStore.getObject(EMOJI_USAGE)) {
|
if (!keyValueStore.getObject(EMOJI_USAGE)) {
|
||||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: {} });
|
keyValueStore.setObject({ key: EMOJI_USAGE, value: {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set("selectedDiversity", keyValueStore.getObject(EMOJI_SELECTED_DIVERSITY) || 1);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
didUpdateAttrs() {
|
didUpdateAttrs() {
|
||||||
@ -61,7 +50,7 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
@observes("filter")
|
@observes("filter")
|
||||||
filterChanged() {
|
filterChanged() {
|
||||||
this.get("$filter").find(".clear-filter").toggle(!_.isEmpty(this.get("filter")));
|
$filter.find(".clear-filter").toggle(!_.isEmpty(this.get("filter")));
|
||||||
Ember.run.debounce(this, this._filterEmojisList, 250);
|
Ember.run.debounce(this, this._filterEmojisList, 250);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -69,12 +58,12 @@ export default Ember.Component.extend({
|
|||||||
selectedDiversityChanged() {
|
selectedDiversityChanged() {
|
||||||
keyValueStore.setObject({key: EMOJI_SELECTED_DIVERSITY, value: this.get("selectedDiversity")});
|
keyValueStore.setObject({key: EMOJI_SELECTED_DIVERSITY, value: this.get("selectedDiversity")});
|
||||||
|
|
||||||
$.each(this.get("$list").find(".emoji.diversity[src!='']"), (_, icon) => {
|
$.each($list.find(".emoji.diversity[src!='']"), (_, icon) => {
|
||||||
this._updateIconSrc(icon);
|
this._updateIconSrc(icon);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(this.get("filter") !== "") {
|
if(this.get("filter") !== "") {
|
||||||
$.each(this.get("$results").find(".emoji.diversity"), (_, icon) => {
|
$.each($results.find(".emoji.diversity"), (_, icon) => {
|
||||||
this._updateIconSrc(icon);
|
this._updateIconSrc(icon);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -82,9 +71,9 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
@observes("recentEmojis")
|
@observes("recentEmojis")
|
||||||
recentEmojisChanged() {
|
recentEmojisChanged() {
|
||||||
const $recentSection = this.get("$list").find(".section[data-section='recent']");
|
const $recentSection = $list.find(".section[data-section='recent']");
|
||||||
const $recentSectionGroup = $recentSection.find(".section-group");
|
const $recentSectionGroup = $recentSection.find(".section-group");
|
||||||
const $recentCategory = this.get("$picker").find(".category-icon a[title='recent']").parent();
|
const $recentCategory = $picker.find(".category-icon a[title='recent']").parent();
|
||||||
if(_.isEmpty(this.get("recentEmojis"))) {
|
if(_.isEmpty(this.get("recentEmojis"))) {
|
||||||
$recentCategory.hide();
|
$recentCategory.hide();
|
||||||
$recentSection.css("height", 0).hide();
|
$recentSection.css("height", 0).hide();
|
||||||
@ -99,22 +88,29 @@ export default Ember.Component.extend({
|
|||||||
const model = { recentEmojis };
|
const model = { recentEmojis };
|
||||||
const template = recentTemplate(model);
|
const template = recentTemplate(model);
|
||||||
$recentSectionGroup.html(template);
|
$recentSectionGroup.html(template);
|
||||||
this._bindHover($recentSectionGroup.find("a"));
|
this._bindHover($recentSectionGroup);
|
||||||
},
|
},
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.get("$picker")
|
$picker
|
||||||
.css({width: "", left: "", bottom: ""})
|
.css({width: "", left: "", bottom: ""})
|
||||||
.empty();
|
.empty();
|
||||||
this.$(".emoji-picker-modal").removeClass("fadeIn");
|
$modal.removeClass("fadeIn");
|
||||||
|
|
||||||
this._unbindEvents();
|
this._unbindEvents();
|
||||||
|
|
||||||
|
$filter, $results, $list = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
const model = { customEmojis: this.get("customEmojis") };
|
const template = pickerTemplate({ customEmojis });
|
||||||
const template = pickerTemplate(model);
|
$picker.html(template);
|
||||||
this.get("$picker").html(template);
|
|
||||||
|
$filter = $picker.find(".filter");
|
||||||
|
$results = $picker.find(".results");
|
||||||
|
$list = $picker.find(".list");
|
||||||
|
|
||||||
|
this.set("selectedDiversity", keyValueStore.getObject(EMOJI_SELECTED_DIVERSITY) || 1);
|
||||||
|
|
||||||
this._bindEvents();
|
this._bindEvents();
|
||||||
|
|
||||||
@ -129,14 +125,14 @@ export default Ember.Component.extend({
|
|||||||
_bindEvents() {
|
_bindEvents() {
|
||||||
this._bindDiversityClick();
|
this._bindDiversityClick();
|
||||||
this._bindSectionsScroll();
|
this._bindSectionsScroll();
|
||||||
this._bindEmojiClick();
|
this._bindEmojiClick($list.find(".section-group"));
|
||||||
this._bindClearRecentEmojisGroup();
|
this._bindClearRecentEmojisGroup();
|
||||||
this._bindResizing();
|
this._bindResizing();
|
||||||
this._bindHover();
|
this._bindHover();
|
||||||
this._bindCategoryClick();
|
this._bindCategoryClick();
|
||||||
this._bindModalClick();
|
this._bindModalClick();
|
||||||
this._bindFilterInput();
|
this._bindFilterInput();
|
||||||
this._bindEscape();
|
// this._bindEscape();
|
||||||
},
|
},
|
||||||
|
|
||||||
_bindEscape() {
|
_bindEscape() {
|
||||||
@ -149,29 +145,27 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_bindModalClick() {
|
_bindModalClick() {
|
||||||
this.$(".emoji-picker-modal").on("click", () => {
|
$modal.on("click", () => {
|
||||||
this.set("active", false);
|
this.set("active", false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_unbindEvents() {
|
_unbindEvents() {
|
||||||
this.$(window).off("resize");
|
this.$(window).off("resize");
|
||||||
this.$(".emoji-picker-modal").off("click");
|
$modal.off("click");
|
||||||
Ember.$("#reply-control").off("div-resized");
|
Ember.$("#reply-control").off("div-resized");
|
||||||
this.$().off("keydown");
|
// this.$().off("keydown");
|
||||||
},
|
},
|
||||||
|
|
||||||
_filterEmojisList() {
|
_filterEmojisList() {
|
||||||
const $filter = this.get("$picker").find(".filter");
|
|
||||||
|
|
||||||
if (this.get("filter") === "") {
|
if (this.get("filter") === "") {
|
||||||
$filter.find("input[name='filter']").val("");
|
$filter.find("input[name='filter']").val("");
|
||||||
this.get("$results").empty().hide();
|
$results.empty().hide();
|
||||||
this.get("$list").show();
|
$list.show();
|
||||||
} else {
|
} else {
|
||||||
const regexp = new RegExp(this.get("filter"), "g");
|
const regexp = new RegExp(this.get("filter"), "g");
|
||||||
const filteredCodes = _.filter(emojis, code => regexp.test(code)).slice(0, 30);
|
const filteredCodes = _.filter(emojis, code => regexp.test(code)).slice(0, 30);
|
||||||
this.get("$results").empty().html(
|
$results.empty().html(
|
||||||
_.map(filteredCodes, (code) => {
|
_.map(filteredCodes, (code) => {
|
||||||
const hasDiversity = isSkinTonableEmoji(code);
|
const hasDiversity = isSkinTonableEmoji(code);
|
||||||
const diversity = hasDiversity ? "diversity" : "";
|
const diversity = hasDiversity ? "diversity" : "";
|
||||||
@ -181,14 +175,13 @@ export default Ember.Component.extend({
|
|||||||
</a>`;
|
</a>`;
|
||||||
})
|
})
|
||||||
).show();
|
).show();
|
||||||
this._bindHover(this.get("$results").find("a"));
|
this._bindHover($results);
|
||||||
this._bindEmojiClick(this.get("$results"));
|
this._bindEmojiClick($results);
|
||||||
this.get("$list").hide();
|
$list.hide();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_bindFilterInput() {
|
_bindFilterInput() {
|
||||||
const $filter = this.get("$picker").find(".filter");
|
|
||||||
const $input = $filter.find("input");
|
const $input = $filter.find("input");
|
||||||
|
|
||||||
$input.on("input", (event) => {
|
$input.on("input", (event) => {
|
||||||
@ -203,15 +196,14 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_bindCategoryClick() {
|
_bindCategoryClick() {
|
||||||
this.get("$picker").find(".category-icon").on("click", "a", (event) => {
|
$picker.find(".category-icon").on("click", "a", (event) => {
|
||||||
this.set("filter", "");
|
this.set("filter", "");
|
||||||
this.get("$results").empty();
|
$results.empty();
|
||||||
this.get("$list").show();
|
$list.show();
|
||||||
|
|
||||||
const section = $(event.currentTarget).attr("title");
|
const section = $(event.currentTarget).attr("title");
|
||||||
const $section = this.get("$list").find(`.section[data-section="${section}"]`);
|
const $section = $list.find(`.section[data-section="${section}"]`);
|
||||||
const scrollTop = this.get("$list").scrollTop() +
|
const scrollTop = $list.scrollTop() + ($section.offset().top - $list.offset().top);
|
||||||
( $section.offset().top - this.get("$list").offset().top );
|
|
||||||
|
|
||||||
this._scrollTo(scrollTop);
|
this._scrollTo(scrollTop);
|
||||||
return false;
|
return false;
|
||||||
@ -220,17 +212,20 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
_bindHover(hoverables) {
|
_bindHover(hoverables) {
|
||||||
const replaceInfoContent = (html) => {
|
const replaceInfoContent = (html) => {
|
||||||
this.get("$picker").find(".footer .info").html(html || "");
|
$picker.find(".footer .info").html(html || "");
|
||||||
};
|
};
|
||||||
|
|
||||||
(hoverables || this.$(".section-group a")).hover(event => {
|
(hoverables || this.$(".section-group")).on({
|
||||||
|
mouseover: (event) => {
|
||||||
const $a = $(event.currentTarget);
|
const $a = $(event.currentTarget);
|
||||||
const code = this._codeWithDiversity($a.attr("title"), $a.find("img").hasClass("diversity"));
|
const code = this._codeWithDiversity($a.attr("title"), $a.find("img").hasClass("diversity"));
|
||||||
const html = `<img src="${emojiUrlFor(code)}" class="emoji"> <span>:${code}:<span>`;
|
const html = `<img src="${emojiUrlFor(code)}" class="emoji"> <span>:${code}:<span>`;
|
||||||
replaceInfoContent(html);
|
replaceInfoContent(html);
|
||||||
},
|
},
|
||||||
() => replaceInfoContent()
|
mouseleave: () => {
|
||||||
);
|
replaceInfoContent();
|
||||||
|
}
|
||||||
|
}, "a")
|
||||||
},
|
},
|
||||||
|
|
||||||
_bindResizing() {
|
_bindResizing() {
|
||||||
@ -244,7 +239,7 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_bindClearRecentEmojisGroup() {
|
_bindClearRecentEmojisGroup() {
|
||||||
const $recent = this.get("$picker").find(".section[data-section='recent'] .clear-recent");
|
const $recent = $picker.find(".section[data-section='recent'] .clear-recent");
|
||||||
$recent.on("click", () => {
|
$recent.on("click", () => {
|
||||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: {} });
|
keyValueStore.setObject({ key: EMOJI_USAGE, value: {} });
|
||||||
this.set("recentEmojis", {});
|
this.set("recentEmojis", {});
|
||||||
@ -253,8 +248,7 @@ export default Ember.Component.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_bindEmojiClick(emojisContainer) {
|
_bindEmojiClick($emojisContainer) {
|
||||||
const $emojisContainer = emojisContainer || this.get("$list").find(".section-group");
|
|
||||||
$emojisContainer.off("click").on("click", "a", e => {
|
$emojisContainer.off("click").on("click", "a", e => {
|
||||||
const $icon = $(e.currentTarget);
|
const $icon = $(e.currentTarget);
|
||||||
const title = $icon.attr("title");
|
const title = $icon.attr("title");
|
||||||
@ -271,14 +265,14 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_bindSectionsScroll() {
|
_bindSectionsScroll() {
|
||||||
this.get("$list").on("scroll", () => {
|
$list.on("scroll", () => {
|
||||||
Ember.run.debounce(this, this._checkVisibleSection, 150);
|
Ember.run.debounce(this, this._checkVisibleSection, 150);
|
||||||
Ember.run.debounce(this, this._storeScrollPosition, 50);
|
Ember.run.debounce(this, this._storeScrollPosition, 50);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_checkVisibleSection() {
|
_checkVisibleSection() {
|
||||||
const $sections = this.get("$list").find(".section");
|
const $sections = $list.find(".section");
|
||||||
const sections = [];
|
const sections = [];
|
||||||
let cumulatedHeight = 0;
|
let cumulatedHeight = 0;
|
||||||
|
|
||||||
@ -289,11 +283,11 @@ export default Ember.Component.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
let selectedSection;
|
let selectedSection;
|
||||||
const currentScrollTop = this.get("$list").scrollTop();
|
const currentScrollTop = $list.scrollTop();
|
||||||
if (!_.isEmpty(this.get("recentEmojis")) && currentScrollTop === 0) {
|
if (!_.isEmpty(this.get("recentEmojis")) && currentScrollTop === 0) {
|
||||||
selectedSection = _.first(sections);
|
selectedSection = _.first(sections);
|
||||||
} else if (!_.isEmpty(this.get("customEmojis")) &&
|
} else if (!_.isEmpty(customEmojis) &&
|
||||||
currentScrollTop === this.get("$list")[0].scrollHeight - this.get("$list").innerHeight())
|
currentScrollTop === $list[0].scrollHeight - $list.innerHeight())
|
||||||
{
|
{
|
||||||
selectedSection = _.last(sections);
|
selectedSection = _.last(sections);
|
||||||
} else {
|
} else {
|
||||||
@ -303,8 +297,8 @@ export default Ember.Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(selectedSection) {
|
if(selectedSection) {
|
||||||
this.get("$picker").find(".category-icon").removeClass("current");
|
$picker.find(".category-icon").removeClass("current");
|
||||||
this.get("$picker").find(`.category-icon a[title='${selectedSection.$section.data("section")}']`)
|
$picker.find(`.category-icon a[title='${selectedSection.$section.data("section")}']`)
|
||||||
.parent()
|
.parent()
|
||||||
.addClass("current");
|
.addClass("current");
|
||||||
|
|
||||||
@ -325,7 +319,7 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_bindDiversityClick() {
|
_bindDiversityClick() {
|
||||||
const $diversityScales = this.get("$picker").find(".diversity-picker .diversity-scale");
|
const $diversityScales = $picker.find(".diversity-picker .diversity-scale");
|
||||||
$diversityScales.on("click", (event) => {
|
$diversityScales.on("click", (event) => {
|
||||||
const $selectedDiversity = $(event.currentTarget);
|
const $selectedDiversity = $(event.currentTarget);
|
||||||
$diversityScales.removeClass("selected");
|
$diversityScales.removeClass("selected");
|
||||||
@ -336,7 +330,7 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_setDiversity() {
|
_setDiversity() {
|
||||||
this.get("$picker")
|
$picker
|
||||||
.find(`.diversity-picker .diversity-scale[data-level="${this.get("selectedDiversity")}"]`)
|
.find(`.diversity-picker .diversity-scale[data-level="${this.get("selectedDiversity")}"]`)
|
||||||
.addClass("selected");
|
.addClass("selected");
|
||||||
},
|
},
|
||||||
@ -351,11 +345,12 @@ export default Ember.Component.extend({
|
|||||||
let isLargePreview = this.$(window).height() -
|
let isLargePreview = this.$(window).height() -
|
||||||
Ember.$(".d-header").height() -
|
Ember.$(".d-header").height() -
|
||||||
Ember.$("#reply-control").height() <
|
Ember.$("#reply-control").height() <
|
||||||
this.get("$picker").height() + 16;
|
$picker.height() + 16;
|
||||||
|
|
||||||
if(this._isSmallViewport()) {
|
if(this._isSmallViewport()) {
|
||||||
this.$(".emoji-picker-modal").addClass("fadeIn");
|
$modal.addClass("fadeIn");
|
||||||
this.get("$picker").css({
|
|
||||||
|
$picker.css({
|
||||||
width: this.site.isMobileDevice ? this.$(window).width() - 10 : 340,
|
width: this.site.isMobileDevice ? this.$(window).width() - 10 : 340,
|
||||||
marginLeft: this.site.isMobileDevice ? -(this.$(window).width() - 10)/2 : -170,
|
marginLeft: this.site.isMobileDevice ? -(this.$(window).width() - 10)/2 : -170,
|
||||||
marginTop: -150,
|
marginTop: -150,
|
||||||
@ -363,9 +358,10 @@ export default Ember.Component.extend({
|
|||||||
top: "50%"
|
top: "50%"
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$(".emoji-picker-modal").removeClass("fadeIn");
|
$modal.removeClass("fadeIn");
|
||||||
|
|
||||||
let cssAttributes = { width: 400, marginLeft: "", marginTop: "", left: "", top: "" };
|
let cssAttributes = { width: 400, marginLeft: "", marginTop: "", left: "", top: "" };
|
||||||
|
|
||||||
if(isLargePreview) {
|
if(isLargePreview) {
|
||||||
cssAttributes.left = (Ember.$("#reply-control").width() - Ember.$(".d-editor").width() ) / 2 + Ember.$(".d-editor-preview-wrapper").position().left;
|
cssAttributes.left = (Ember.$("#reply-control").width() - Ember.$(".d-editor").width() ) / 2 + Ember.$(".d-editor-preview-wrapper").position().left;
|
||||||
cssAttributes.bottom = 32;
|
cssAttributes.bottom = 32;
|
||||||
@ -374,14 +370,14 @@ export default Ember.Component.extend({
|
|||||||
cssAttributes.bottom = Ember.$("#reply-control").height() - 48;
|
cssAttributes.bottom = Ember.$("#reply-control").height() - 48;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.get("$picker").css(cssAttributes);
|
$picker.css(cssAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const infoMaxWidth = this.get("$picker").width() -
|
const infoMaxWidth = $picker.width() -
|
||||||
this.get("$picker").find(".categories-column").width() -
|
$picker.find(".categories-column").width() -
|
||||||
this.get("$picker").find(".diversity-picker").width() -
|
$picker.find(".diversity-picker").width() -
|
||||||
32;
|
32;
|
||||||
this.get("$picker").find(".info").css("max-width", infoMaxWidth);
|
$picker.find(".info").css("max-width", infoMaxWidth);
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadVisibleEmojis($visibleEmojis) {
|
_loadVisibleEmojis($visibleEmojis) {
|
||||||
@ -403,7 +399,7 @@ export default Ember.Component.extend({
|
|||||||
_storeScrollPosition() {
|
_storeScrollPosition() {
|
||||||
keyValueStore.setObject({
|
keyValueStore.setObject({
|
||||||
key: EMOJI_SCROLL_Y,
|
key: EMOJI_SCROLL_Y,
|
||||||
value: this.get("$list").scrollTop()
|
value: $list.scrollTop()
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -432,11 +428,11 @@ export default Ember.Component.extend({
|
|||||||
_scrollTo(y) {
|
_scrollTo(y) {
|
||||||
const yPosition = _.isUndefined(y) ? keyValueStore.getObject(EMOJI_SCROLL_Y) : y;
|
const yPosition = _.isUndefined(y) ? keyValueStore.getObject(EMOJI_SCROLL_Y) : y;
|
||||||
|
|
||||||
this.get("$list").scrollTop(yPosition);
|
$list.scrollTop(yPosition);
|
||||||
|
|
||||||
// if we don’t actually scroll we need to force it
|
// if we don’t actually scroll we need to force it
|
||||||
if(yPosition === 0) {
|
if(yPosition === 0) {
|
||||||
this.get("$list").scroll();
|
$list.scroll();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user