Added autocompletion
This commit is contained in:
parent
b57fee0ad8
commit
adfc120642
11 changed files with 320 additions and 31 deletions
3
TODO
3
TODO
|
@ -20,8 +20,9 @@ everything related to posts:
|
||||||
(move post snapshot factory methods to PostService)
|
(move post snapshot factory methods to PostService)
|
||||||
|
|
||||||
everything related to tags:
|
everything related to tags:
|
||||||
|
- automatic tag removal
|
||||||
|
- tag refresh when editing post
|
||||||
- tag listing
|
- tag listing
|
||||||
- tag autocompletion (difficult)
|
|
||||||
- time of last tag usage
|
- time of last tag usage
|
||||||
- time of tag addition
|
- time of tag addition
|
||||||
- mass tag
|
- mass tag
|
||||||
|
|
23
public_html/css/tags.css
Normal file
23
public_html/css/tags.css
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
.autocomplete {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.autocomplete ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border: 2px solid #5da;
|
||||||
|
background: white;
|
||||||
|
display: block !important;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.1em 0.5em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete li.active {
|
||||||
|
background: #5da;
|
||||||
|
}
|
|
@ -37,6 +37,7 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/css/home.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/home.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/history.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/history.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/comments.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/comments.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/tags.css"/>
|
||||||
<!-- /build -->
|
<!-- /build -->
|
||||||
|
|
||||||
<!-- build:remove -->
|
<!-- build:remove -->
|
||||||
|
@ -86,9 +87,11 @@
|
||||||
<script type="text/javascript" src="/js/Pager.js"></script>
|
<script type="text/javascript" src="/js/Pager.js"></script>
|
||||||
<script type="text/javascript" src="/js/BrowsingSettings.js"></script>
|
<script type="text/javascript" src="/js/BrowsingSettings.js"></script>
|
||||||
<script type="text/javascript" src="/js/Controls/FileDropper.js"></script>
|
<script type="text/javascript" src="/js/Controls/FileDropper.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/Controls/AutoCompleteInput.js"></script>
|
||||||
<script type="text/javascript" src="/js/Controls/TagInput.js"></script>
|
<script type="text/javascript" src="/js/Controls/TagInput.js"></script>
|
||||||
<script type="text/javascript" src="/js/PresenterManager.js"></script>
|
<script type="text/javascript" src="/js/PresenterManager.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/Services/TagList.js"></script>
|
||||||
<script type="text/javascript" src="/js/Services/PostsAroundCalculator.js"></script>
|
<script type="text/javascript" src="/js/Services/PostsAroundCalculator.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/Presenters/TopNavigationPresenter.js"></script>
|
<script type="text/javascript" src="/js/Presenters/TopNavigationPresenter.js"></script>
|
||||||
|
|
223
public_html/js/Controls/AutoCompleteInput.js
Normal file
223
public_html/js/Controls/AutoCompleteInput.js
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
var App = App || {};
|
||||||
|
App.Controls = App.Controls || {};
|
||||||
|
|
||||||
|
App.Controls.AutoCompleteInput = function($input) {
|
||||||
|
var _ = App.DI.get('_');
|
||||||
|
var jQuery = App.DI.get('jQuery');
|
||||||
|
var tagList = App.DI.get('tagList');
|
||||||
|
|
||||||
|
var KEY_RETURN = 13;
|
||||||
|
var KEY_ESCAPE = 27;
|
||||||
|
var KEY_UP = 38;
|
||||||
|
var KEY_DOWN = 40;
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
caseSensitive: false,
|
||||||
|
source: null,
|
||||||
|
maxResults: 15,
|
||||||
|
minLengthToArbitrarySearch: 3,
|
||||||
|
onApply: null,
|
||||||
|
additionalFilter: null,
|
||||||
|
};
|
||||||
|
var showTimeout = null;
|
||||||
|
var cachedSource = null;
|
||||||
|
var results = [];
|
||||||
|
var activeResult = -1;
|
||||||
|
|
||||||
|
if ($input.length === 0) {
|
||||||
|
throw new Error('Input element was not found');
|
||||||
|
}
|
||||||
|
if ($input.length > 1) {
|
||||||
|
throw new Error('Cannot add autocompletion to more than one element at once');
|
||||||
|
}
|
||||||
|
if ($input.attr('data-autocomplete')) {
|
||||||
|
throw new Error('Autocompletion was already added for this element');
|
||||||
|
}
|
||||||
|
$input.attr('data-autocomplete', true);
|
||||||
|
$input.attr('autocomplete', 'off');
|
||||||
|
|
||||||
|
var $div = jQuery('<div>');
|
||||||
|
var $list = jQuery('<ul>');
|
||||||
|
$div.addClass('autocomplete');
|
||||||
|
$div.append($list);
|
||||||
|
jQuery(document.body).append($div);
|
||||||
|
|
||||||
|
function getSource() {
|
||||||
|
if (cachedSource) {
|
||||||
|
return cachedSource;
|
||||||
|
} else {
|
||||||
|
var source = source || tagList.getTags();
|
||||||
|
source = _.pairs(source);
|
||||||
|
source = _.sortBy(source, function(a) { return -a[1]; });
|
||||||
|
source = _.filter(source, function(a) { return a[1] > 0; });
|
||||||
|
source = _.map(source, function(a) { return [a[0], a[0] + ' (' + a[1] + ')']; });
|
||||||
|
cachedSource = source;
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$input.bind('keydown', function(e) {
|
||||||
|
if (isShown() && e.which === KEY_ESCAPE) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
hide();
|
||||||
|
} else if (isShown() && e.which === KEY_DOWN) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
selectNext();
|
||||||
|
} else if (isShown() && e.which === KEY_UP) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
selectPrevious();
|
||||||
|
} else if (isShown() && e.which === KEY_RETURN && activeResult >= 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
applyAutocomplete();
|
||||||
|
hide();
|
||||||
|
} else {
|
||||||
|
window.clearTimeout(showTimeout);
|
||||||
|
showTimeout = window.setTimeout(showOrHide, 250);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$input.blur(function(e) {
|
||||||
|
window.clearTimeout(showTimeout);
|
||||||
|
window.setTimeout(function() { hide(); }, 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
function getSelectionStart(){
|
||||||
|
var input = $input.get(0);
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('selectionStart' in input) {
|
||||||
|
return input.selectionStart;
|
||||||
|
} else if (document.selection) {
|
||||||
|
input.focus();
|
||||||
|
var sel = document.selection.createRange();
|
||||||
|
var selLen = document.selection.createRange().text.length;
|
||||||
|
sel.moveStart('character', -input.value.length);
|
||||||
|
return sel.text.length - selLen;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTextToFind() {
|
||||||
|
var val = $input.val();
|
||||||
|
var start = getSelectionStart();
|
||||||
|
return val.substring(0, start).replace(/.*\s/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showOrHide() {
|
||||||
|
var textToFind = getTextToFind();
|
||||||
|
if (textToFind.length === 0) {
|
||||||
|
hide();
|
||||||
|
} else {
|
||||||
|
updateResults(textToFind);
|
||||||
|
refreshList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isShown() {
|
||||||
|
return $div.is(':visible');
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide() {
|
||||||
|
$div.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectPrevious() {
|
||||||
|
select(activeResult === -1 ? results.length - 1 : activeResult - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectNext() {
|
||||||
|
select(activeResult === -1 ? 0 : activeResult + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(newActiveResult) {
|
||||||
|
if (newActiveResult >= 0 && newActiveResult < results.length) {
|
||||||
|
activeResult = newActiveResult;
|
||||||
|
refreshActiveResult();
|
||||||
|
} else {
|
||||||
|
activeResult = - 1;
|
||||||
|
refreshActiveResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getResultsFilter(textToFind) {
|
||||||
|
if (textToFind.length < options.minLengthToArbitrarySearch) {
|
||||||
|
return options.caseSensitive ?
|
||||||
|
function(resultItem) { return resultItem[0].indexOf(textToFind) === 0; } :
|
||||||
|
function(resultItem) { return resultItem[0].toLowerCase().indexOf(textToFind.toLowerCase()) === 0; };
|
||||||
|
} else {
|
||||||
|
return options.caseSensitive ?
|
||||||
|
function(resultItem) { return resultItem[0].indexOf(textToFind) >= 0; } :
|
||||||
|
function(resultItem) { return resultItem[0].toLowerCase().indexOf(textToFind.toLowerCase()) >= 0; };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateResults(textToFind) {
|
||||||
|
var source = getSource();
|
||||||
|
var filter = getResultsFilter(textToFind);
|
||||||
|
results = _.filter(source, filter);
|
||||||
|
if (options.additionalFilter) {
|
||||||
|
results = options.additionalFilter(results);
|
||||||
|
}
|
||||||
|
results = results.slice(0, options.maxResults);
|
||||||
|
activeResult = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyAutocomplete() {
|
||||||
|
if (options.onApply) {
|
||||||
|
options.onApply(results[activeResult][0]);
|
||||||
|
} else {
|
||||||
|
var val = $input.val();
|
||||||
|
var start = getSelectionStart();
|
||||||
|
var prefix = '';
|
||||||
|
var suffix = val.substring(start);
|
||||||
|
var middle = val.substring(0, start);
|
||||||
|
var index = middle.lastIndexOf(' ');
|
||||||
|
if (index !== -1) {
|
||||||
|
prefix = val.substring(0, index + 1);
|
||||||
|
middle = val.substring(index + 1);
|
||||||
|
}
|
||||||
|
$input.val(prefix + results[activeResult][0] + ' ' + suffix.trimLeft());
|
||||||
|
$input.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshList() {
|
||||||
|
if (results.length === 0) {
|
||||||
|
hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$list.empty();
|
||||||
|
_.each(results, function(resultItem) {
|
||||||
|
var $listItem = jQuery('<li/>');
|
||||||
|
$listItem.text(resultItem[1]);
|
||||||
|
$listItem.attr('data-key', resultItem[0]);
|
||||||
|
$list.append($listItem);
|
||||||
|
});
|
||||||
|
refreshActiveResult();
|
||||||
|
$div.css({
|
||||||
|
left: ($input.offset().left) + 'px',
|
||||||
|
top: ($input.offset().top + $input.outerHeight() - 2) + 'px',
|
||||||
|
});
|
||||||
|
$div.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshActiveResult() {
|
||||||
|
$list.find('li.active').removeClass('active');
|
||||||
|
if (activeResult >= 0) {
|
||||||
|
$list.find('li').eq(activeResult).addClass('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
|
@ -1,10 +1,9 @@
|
||||||
var App = App || {};
|
var App = App || {};
|
||||||
App.Controls = App.Controls || {};
|
App.Controls = App.Controls || {};
|
||||||
|
|
||||||
App.Controls.FileDropper = function(
|
App.Controls.FileDropper = function($fileInput) {
|
||||||
$fileInput,
|
var _ = App.DI.get('_');
|
||||||
_,
|
var jQuery = App.DI.get('jQuery');
|
||||||
jQuery) {
|
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
onChange: null,
|
onChange: null,
|
||||||
|
@ -63,7 +62,4 @@ App.Controls.FileDropper = function(
|
||||||
});
|
});
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
App.DI.register('fileDropper', App.Controls.FileDropper);
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
var App = App || {};
|
var App = App || {};
|
||||||
App.Controls = App.Controls || {};
|
App.Controls = App.Controls || {};
|
||||||
|
|
||||||
//todo: autocomplete
|
App.Controls.TagInput = function($underlyingInput) {
|
||||||
|
var _ = App.DI.get('_');
|
||||||
App.Controls.TagInput = function(
|
var jQuery = App.DI.get('jQuery');
|
||||||
$underlyingInput,
|
|
||||||
_,
|
|
||||||
jQuery) {
|
|
||||||
|
|
||||||
var KEY_RETURN = 13;
|
var KEY_RETURN = 13;
|
||||||
var KEY_SPACE = 32;
|
var KEY_SPACE = 32;
|
||||||
|
@ -48,21 +45,36 @@ App.Controls.TagInput = function(
|
||||||
});
|
});
|
||||||
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
||||||
|
|
||||||
var tagsToAdd = $underlyingInput.val().split(/\s+/);
|
addTagsFromText($underlyingInput.val());
|
||||||
_.map(tagsToAdd, addTag);
|
|
||||||
$underlyingInput.val('');
|
$underlyingInput.val('');
|
||||||
|
|
||||||
$input.unbind('focus').bind('focus', function(e) {
|
initAutocomplete();
|
||||||
|
|
||||||
|
function initAutocomplete() {
|
||||||
|
var autocomplete = new App.Controls.AutoCompleteInput($input);
|
||||||
|
autocomplete.onApply = function(text) {
|
||||||
|
addTagsFromText(text);
|
||||||
|
$input.val('');
|
||||||
|
};
|
||||||
|
autocomplete.additionalFilter = function(results) {
|
||||||
|
var tags = getTags();
|
||||||
|
return _.filter(results, function(resultItem) {
|
||||||
|
return !_.contains(tags, resultItem[0]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$input.bind('focus', function(e) {
|
||||||
$wrapper.addClass('focused');
|
$wrapper.addClass('focused');
|
||||||
});
|
});
|
||||||
$input.unbind('blur').bind('blur', function(e) {
|
$input.bind('blur', function(e) {
|
||||||
$wrapper.removeClass('focused');
|
$wrapper.removeClass('focused');
|
||||||
var tag = $input.val();
|
var tag = $input.val();
|
||||||
addTag(tag);
|
addTag(tag);
|
||||||
$input.val('');
|
$input.val('');
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.unbind('paste').bind('paste', function(e) {
|
$input.bind('paste', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var pastedText;
|
var pastedText;
|
||||||
if (window.clipboardData) {
|
if (window.clipboardData) {
|
||||||
|
@ -82,7 +94,7 @@ App.Controls.TagInput = function(
|
||||||
$input.val(lastTag);
|
$input.val(lastTag);
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.unbind('keydown').bind('keydown', function(e) {
|
$input.bind('keydown', function(e) {
|
||||||
if (_.contains(inputConfirmKeys, e.which) && !$input.val()) {
|
if (_.contains(inputConfirmKeys, e.which) && !$input.val()) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (typeof(options.inputConfirmed) !== 'undefined') {
|
if (typeof(options.inputConfirmed) !== 'undefined') {
|
||||||
|
@ -99,6 +111,11 @@ App.Controls.TagInput = function(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function addTagsFromText(text) {
|
||||||
|
var tagsToAdd = text.split(/\s+/);
|
||||||
|
_.map(tagsToAdd, addTag);
|
||||||
|
}
|
||||||
|
|
||||||
function addTag(tag) {
|
function addTag(tag) {
|
||||||
tag = tag.trim();
|
tag = tag.trim();
|
||||||
if (tag.length === 0) {
|
if (tag.length === 0) {
|
||||||
|
@ -185,5 +202,3 @@ App.Controls.TagInput = function(
|
||||||
});
|
});
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
App.DI.register('tagInput', App.Controls.TagInput);
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ App.Presenters.PostListPresenter = function(
|
||||||
function render() {
|
function render() {
|
||||||
$el.html(templates.list());
|
$el.html(templates.list());
|
||||||
$searchInput = $el.find('input[name=query]');
|
$searchInput = $el.find('input[name=query]');
|
||||||
|
App.Controls.AutoCompleteInput($searchInput);
|
||||||
|
|
||||||
$searchInput.val(searchArgs.query);
|
$searchInput.val(searchArgs.query);
|
||||||
$searchInput.keydown(searchInputKeyPressed);
|
$searchInput.keydown(searchInputKeyPressed);
|
||||||
|
@ -80,7 +81,7 @@ App.Presenters.PostListPresenter = function(
|
||||||
});
|
});
|
||||||
|
|
||||||
keyboard.keyup('q', function() {
|
keyboard.keyup('q', function() {
|
||||||
$searchInput.eq(0).focus();
|
$searchInput.eq(0).focus().select();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ App.Presenters.PostListPresenter = function(
|
||||||
var $post = jQuery('<li>' + templates.listItem({
|
var $post = jQuery('<li>' + templates.listItem({
|
||||||
searchArgs: searchArgs,
|
searchArgs: searchArgs,
|
||||||
post: post,
|
post: post,
|
||||||
}) + '</li>')
|
}) + '</li>');
|
||||||
util.loadImagesNicely($post.find('img'));
|
util.loadImagesNicely($post.find('img'));
|
||||||
$target.append($post);
|
$target.append($post);
|
||||||
});
|
});
|
||||||
|
@ -116,7 +117,7 @@ App.Presenters.PostListPresenter = function(
|
||||||
function updateSearch() {
|
function updateSearch() {
|
||||||
$searchInput.blur();
|
$searchInput.blur();
|
||||||
pagerPresenter.setSearchParams({
|
pagerPresenter.setSearchParams({
|
||||||
query: $searchInput.val(),
|
query: $searchInput.val().trim(),
|
||||||
order: searchArgs.order});
|
order: searchArgs.order});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,14 +135,14 @@ App.Presenters.PostPresenter = function(
|
||||||
$messages = $el.find('.messages');
|
$messages = $el.find('.messages');
|
||||||
|
|
||||||
if (editPrivileges.canChangeTags) {
|
if (editPrivileges.canChangeTags) {
|
||||||
tagInput = App.Controls.TagInput($el.find('form [name=tags]'), _, jQuery);
|
tagInput = new App.Controls.TagInput($el.find('form [name=tags]'));
|
||||||
tagInput.inputConfirmed = editPost;
|
tagInput.inputConfirmed = editPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
postContentFileDropper = new App.Controls.FileDropper($el.find('form [name=content]'), _, jQuery);
|
postContentFileDropper = new App.Controls.FileDropper($el.find('form [name=content]'));
|
||||||
postContentFileDropper.onChange = postContentChanged;
|
postContentFileDropper.onChange = postContentChanged;
|
||||||
postContentFileDropper.setNames = true;
|
postContentFileDropper.setNames = true;
|
||||||
postThumbnailFileDropper = new App.Controls.FileDropper($el.find('form [name=thumbnail]'), _, jQuery);
|
postThumbnailFileDropper = new App.Controls.FileDropper($el.find('form [name=thumbnail]'));
|
||||||
postThumbnailFileDropper.onChange = postThumbnailChanged;
|
postThumbnailFileDropper.onChange = postThumbnailChanged;
|
||||||
postThumbnailFileDropper.setNames = true;
|
postThumbnailFileDropper.setNames = true;
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,8 @@ App.Presenters.PostUploadPresenter = function(
|
||||||
}));
|
}));
|
||||||
$messages = $el.find('.messages');
|
$messages = $el.find('.messages');
|
||||||
|
|
||||||
tagInput = new App.Controls.TagInput($el.find('form [name=tags]'), _, jQuery);
|
tagInput = new App.Controls.TagInput($el.find('form [name=tags]'));
|
||||||
fileDropper = App.Controls.FileDropper($el.find('[name=post-content]'), _, jQuery);
|
fileDropper = new App.Controls.FileDropper($el.find('[name=post-content]'));
|
||||||
fileDropper.onChange = fileHandlerChanged;
|
fileDropper.onChange = fileHandlerChanged;
|
||||||
|
|
||||||
$el.find('.url-handler input').keydown(urlHandlerKeyPressed);
|
$el.find('.url-handler input').keydown(urlHandlerKeyPressed);
|
||||||
|
|
|
@ -54,7 +54,7 @@ App.Presenters.UserAccountSettingsPresenter = function(
|
||||||
$el.find('form').submit(accountSettingsFormSubmitted);
|
$el.find('form').submit(accountSettingsFormSubmitted);
|
||||||
$el.find('form [name=avatar-style]').change(avatarStyleChanged);
|
$el.find('form [name=avatar-style]').change(avatarStyleChanged);
|
||||||
avatarStyleChanged();
|
avatarStyleChanged();
|
||||||
fileDropper = new App.Controls.FileDropper($el.find('[name=avatar-content]'), _, jQuery);
|
fileDropper = new App.Controls.FileDropper($el.find('[name=avatar-content]'));
|
||||||
fileDropper.onChange = avatarContentChanged;
|
fileDropper.onChange = avatarContentChanged;
|
||||||
fileDropper.setNames = true;
|
fileDropper.setNames = true;
|
||||||
}
|
}
|
||||||
|
|
27
public_html/js/Services/TagList.js
Normal file
27
public_html/js/Services/TagList.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
var App = App || {};
|
||||||
|
App.Services = App.Services || {};
|
||||||
|
|
||||||
|
App.Services.TagList = function(jQuery) {
|
||||||
|
var tags = [];
|
||||||
|
|
||||||
|
jQuery.ajax({
|
||||||
|
success: function(data, textStatus, xhr) {
|
||||||
|
tags = data;
|
||||||
|
},
|
||||||
|
error: function(xhr, textStatus, errorThrown) {
|
||||||
|
console.log(new Error(errorThrown));
|
||||||
|
},
|
||||||
|
type: 'GET',
|
||||||
|
url: '/data/tags.json',
|
||||||
|
});
|
||||||
|
|
||||||
|
function getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getTags: getTags,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
App.DI.registerSingleton('tagList', ['jQuery'], App.Services.TagList);
|
Loading…
Reference in a new issue