From fe8e5d7e464c1181fa08b5205430f27fbcd21c3d Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 9 Mar 2017 09:20:23 -0300 Subject: [PATCH] move and adapt manager and completion --- kfet/static/kfet/js/kpsul.js | 226 ++++++++++++ kfet/templates/kfet/kpsul.html | 612 +-------------------------------- 2 files changed, 235 insertions(+), 603 deletions(-) diff --git a/kfet/static/kfet/js/kpsul.js b/kfet/static/kfet/js/kpsul.js index 9dd6ae19..238a40a6 100644 --- a/kfet/static/kfet/js/kpsul.js +++ b/kfet/static/kfet/js/kpsul.js @@ -4,6 +4,7 @@ class KPsulManager { this._env = env; this.account_manager = new AccountManager(this); this.checkout_manager = new CheckoutManager(this); + this.article_manager = new ArticleManager(this); } reset(soft) { @@ -367,3 +368,228 @@ class CheckoutSelection { } } +class ArticleManager { + + constructor(env) { + this._env = env; // Global K-Psul Manager + + this._$container = $('#articles_data tbody'); + this._$input = $('#article_autocomplete'); + this._$nb = $('#article_number'); + this.templates = {'category': '', + 'article' : ''} + + this.selected = new Article() ; + this.list = new ArticleList() ; + this.autocomplete = new ArticleAutocomplete(this); + + this._init_events(); + } + + get nb() { + return this._$nb.val() ; + } + + display_list() { + this.list.display(this._$container, this.templates) ; + } + + validate(article) { + this.selected.from(article) ; + this._$input.val(article.name); + this._$nb.val('1'); + this._$nb.focus().select(); + } + + unset() { + this.selected.clear(); + } + + is_empty() { + return this.selected.is_empty(); + } + + reset_data() { + this._$container.find('tr').remove(); + this.list.clear(); + this.list.fromAPI({}, this.display_list.bind(this), $.noop) ; + } + + update_data(data) { + for (let article_dict of data) { + article = this.list.find(Article, {'id': article_dict['id']}); + + // For now, article additions are disregarded + if (article) { + article.stock = article_dict['stock']; + this._$container.find('#data-article-'+article_dict['id']+' .stock') + .text(article_dict['stock']); + } + } + } + + reset() { + this.unset() ; + this._$nb.val(''); + this._$input.val(''); + this.autocomplete.showAll() ; + } + + _init_events() { + var that = this; + + // 8:Backspace|9:Tab|13:Enter|46:DEL|112-117:F1-6|119-123:F8-F12 + var normalKeys = /^(8|9|13|46|112|113|114|115|116|117|119|120|121|122|123)$/; + var arrowKeys = /^(37|38|39|40)$/; + + //Global input event (to merge ?) + this._$input.on('keydown', function(e) { + if (e.keyCode == 13 && that._$input.val() == '') { + kpsul._env.performOperations(); + } + }); + + this._$container.on('click', '.article', function() { + var id = $(this).attr('data-article-id') ; + var article = that.list.find(Article, { 'id': intCheck(id) }); + if (article) + that.validate(article); + }); + + this._$nb.on('keydown', function(e) { + if (e.keyCode == 13 && that.constructor.check_nb(that.nb) && !that.is_empty()) { + kpsul._env.addPurchase(that.selected, that.nb); + that.reset(); + that.focus(); + } + if (normalKeys.test(e.keyCode) || arrowKeys.test(e.KeyCode) || e.ctrlKey) { + if (e.ctrlKey && e.charCode == 65) + that._$nb.val(''); + return true ; + } + if (that.constructor.check_nb(that.nb+e.key)) + return true; + return false; + + }); + } + + focus() { + this._$input.focus(); + return this; + } + + static check_nb(nb) { + return /^[0-9]+$/.test(nb) && nb > 0 && nb <= 24 ; + } +} + +class ArticleAutocomplete { + + constructor(article_manager) { + this.manager = article_manager; + this.matching = []; + this.active_categories = []; + this._$container = article_manager._$container ; + this._$input = $('#article_autocomplete'); + + this.showAll() ; + this._init_events(); + } + + _init_events() { + var that = this ; + + // 8:Backspace|9:Tab|13:Enter|46:DEL|112-117:F1-6|119-123:F8-F12 + var normalKeys = /^(8|9|13|46|112|113|114|115|116|117|119|120|121|122|123)$/; + + this._$input + .on('keydown', function(e) { + var text = that._$input.val() ; + if (normalKeys.test(e.keyCode) || e.ctrlKey) { + // For the backspace key, we suppose the cursor is at the very end + if(e.keyCode == 8) { + that.update(text.substring(0, text.length-1), true); + } + return true ; + } + that.update(text+e.key, false); + + return false ; + + }); + + } + + update(prefix, backspace) { + + var article_list = this.manager.list ; + var lower = prefix.toLowerCase() ; + var that = this ; + this.matching = article_list.data['article'] + .filter(function(article) { + return article.name.toLowerCase() + .indexOf(lower) === 0 ; + }); + + this.active_categories = article_list.data['category'] + .filter(function(category) { + return that.matching.find(function(article) { + return article.category === category ; + }); + }); + + if (this.matching.length == 1) { + if (!backspace) { + this.manager.validate(this.matching[0]) ; + this.showAll() ; + } else { + this.manager.unset(); + this.updateDisplay(); + } + } else if (this.matching.length > 1) { + this.manager.unset(); + this.updateDisplay() ; + if (!backspace) + this.updatePrefix(); + } + } + + updateDisplay() { + var article_list = this.manager.list ; + for (let article of article_list.data['article']) { + if (this.matching.indexOf(article) > -1) { + this._$container.find('[data-article-id='+article.id+']').show(); + } else { + this._$container.find('[data-article-id='+article.id+']').hide(); + } + } + + for (let category of article_list.data['category']) { + if (this.active_categories.indexOf(category) > -1) { + this._$container.find('[data-category-id='+category.id+']').show(); + } else { + this._$container.find('[data-category-id='+category.id+']').hide(); + } + } + } + + updatePrefix() { + var lower = this.matching.map(function (article) { + return article.name.toLowerCase() ; + }); + + lower.sort() ; + var first = lower[0], last = lower[lower.length-1], + length = first.length, i = 0; + while (i < length && first.charAt(i) === last.charAt(i)) i++; + + this._$input.val(first.substring(0,i)) ; + } + + showAll() { + this.matching = this.manager.list.data['article']; + this.active_categories = this.manager.list.data['category']; + this.updateDisplay(); + } +} diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 6454afa9..05dff009 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -195,398 +195,6 @@ function functionCheck(v) { return function(){}; } -function restrict(obj, attr_list) { - var restricted = {} ; - for (let attr of attr_list) { - restricted[attr] = obj[attr] ; - } - return restricted ; -} - -class ArticleCategory { - - constructor(id, name) { - this.id = id; - this.name = name; - } - - get id() { return this._id; } - - set id(v) { this._id = intCheck(v); } - - html(template) { - var $template = $(template) - $template.attr('id', 'data-category-'+this.id); - $template.find('td').text(this.name); - return $template ; - } - - static compare(a, b) { - return a.name.localeCompare(b.name) ; - } -} - -class Article { - - constructor () { - $.extend(this, this.constructor.default_data); - } - - static get default_data() { - return { - 'id': 0, 'name': '', 'price': 0, 'stock': 0, - 'category': new ArticleCategory(), - }; - } - - get id() { return this._id; } - get price() { return this._price; } - get stock() { return this._stock; } - - set id(v) { this._id = intCheck(v); } - set price(v) { this._price = floatCheck(v); } - set stock(v) { this._stock = intCheck(v); } - - get str_price_ukf() { - return amountToUKF(this.price, false); - } - - static get _data_stock_ok() { return ''; } - static get _data_stock_low() { return 'low'; } - static get _data_stock_neg() { return 'neg'; } - - get data_stock() { - var stock = this.stock ; - if (stock >= 5) { return this.constructor._data_stock_ok; } - else if (stock >= -5) { return this.constructor._data_stock_low; } - else /* stock < -5 */ { return this.constructor._data_stock_neg; } - } - - from(data) { - $.extend(this, this.constructor.default_data, data); - } - - html(template) { - var $template = $(template); - $template - .find('.name').text(this.name).end() - .find('.price').text(this.str_price_ukf).end() - .find('.stock').text(this.stock).end(); - $template.attr('id', 'data-article-'+this.id); - $template.attr('data-stock', this.data_stock); - return $template ; - } - - static compare(a, b) { - return a.name.localeCompare(b.name) ; - } - - reset() { - this.from({}); - } -} - -class ArticleList { - constructor() { - this.articles = []; - this.categories = []; - } - - get_or_create(id, name) { - var category = this.categories.find(c => c.id === id); - if (!category) { - category = new ArticleCategory(id, name); - this.categories.push(category); - } - return category; - } - - from(data, callback) { - callback = functionCheck(callback); - - for (let article_data of data['articles']) { - var category = this.get_or_create(article_data['category_id'], article_data['category__name']) ; - article_data = restrict(article_data, ['name', 'price', 'stock', 'id']) ; - article_data['category'] = category ; - - var article = new Article() ; - article.from(article_data) ; - this.articles.push(article) ; - } - - callback() ; - } - - fromAPI(on_success, on_error) { - on_error = functionCheck(on_error); - var that = this ; - $.ajax({ - dataType: "json", - url : "{% url 'kfet.kpsul.articles_data' %}", - method : "GET", - }) - .done((data) => this.from(data, on_success)) - .fail(on_error); - } - - display($container, $article_template, $category_template) { - this.categories.sort(ArticleCategory.compare) ; - for (let cat of this.categories) { - var cat_articles = this.articles.filter(a => a.category.id === cat.id) ; - cat_articles.sort(Article.compare); - - $container.append(cat.html($category_template)) ; - for (let art of cat_articles) { - $container.append(art.html($article_template)) ; - } - } - } - - clear() { - this.articles = []; - this.categories = [] ; - } - - find_by_id(name) { - return this.articles.find(function(a) { - return a.name === name ; - }); - } - - get_from_elt($elt) { - var id = $elt.attr('id').split('-')[2]; - - return this.articles.find(function(article) { - return (article.id == id) ; - }); - } -} - -class ArticleManager { - - constructor(env) { - this._env = env; // Global K-Psul Manager - - this._$container = $('#articles_data tbody'); - this._$input = $('#article_autocomplete'); - this._$nb = $('#article_number'); - this._category_template = ''; - this._article_template = ''; - - this.selected = new Article() ; - this.list = new ArticleList() ; - this.autocomplete = new ArticleAutocomplete(this); - - this._init_events(); - } - - get nb() { - return this._$nb.val() ; - } - - display_list() { - this.list.display(this._$container, this._article_template, this._category_template) ; - } - - validate(article) { - this.selected.from(article) ; - this._$input.val(article.name); - this._$nb.val('1'); - this._$nb.focus().select(); - } - - unset() { - this.selected.reset(); - } - - is_empty() { - return this.selected.id == 0 ; - } - - reset_data() { - this._$container.find('tr').remove(); - this.list.clear(); - this.list.fromAPI(this.display_list.bind(this)) ; - } - - update_data(data) { - for (let article_dict of data) { - var article = this.list.articles.find(function(art) { - return (art.id == article_dict['id']); - }); - - // For now, article additions are disregarded - if (article) { - article.stock = article_dict['stock']; - this._$container.find('#data-article-'+article_dict['id']+' .stock') - .text(article_dict['stock']); - } - } - } - - reset() { - this.unset() ; - this._$nb.val(''); - this._$input.val(''); - this.autocomplete.showAll() ; - } - - _init_events() { - var that = this; - - // 8:Backspace|9:Tab|13:Enter|46:DEL|112-117:F1-6|119-123:F8-F12 - var normalKeys = /^(8|9|13|46|112|113|114|115|116|117|119|120|121|122|123)$/; - var arrowKeys = /^(37|38|39|40)$/; - - //Global input event (to merge ?) - this._$input.on('keydown', function(e) { - if (e.keyCode == 13 && that._$input.val() == '') { - that._env.performOperations(); - } - }); - - this._$container.on('click', '.article', function() { - var article = that.list.get_from_elt($(this)) ; - that.validate(article); - }); - - this._$nb.on('keydown', function(e) { - if (e.keyCode == 13 && ArticleManager.check_nb(that.nb) && !that.is_empty()) { - that._env.addPurchase(that.selected, that.nb); - that.reset(); - that.focus(); - } - if (normalKeys.test(e.keyCode) || arrowKeys.test(e.KeyCode) || e.ctrlKey) { - if (e.ctrlKey && e.charCode == 65) - that._$nb.val(''); - return true ; - } - if (ArticleManager.check_nb(that.nb+e.key)) - return true; - return false; - - }); - } - - focus() { - this._$input.focus(); - return this; - } - - static check_nb(nb) { - return /^[0-9]+$/.test(nb) && nb > 0 && nb <= 24 ; - } -} - -class ArticleAutocomplete { - - constructor(article_manager) { - this.manager = article_manager; - this.matching = []; - this.active_categories = []; - this._$container = article_manager._$container ; - this._$input = $('#article_autocomplete'); - - this.showAll() ; - this._init_events(); - } - - _init_events() { - var that = this ; - - // 8:Backspace|9:Tab|13:Enter|46:DEL|112-117:F1-6|119-123:F8-F12 - var normalKeys = /^(8|9|13|46|112|113|114|115|116|117|119|120|121|122|123)$/; - - this._$input - .on('keydown', function(e) { - var text = that._$input.val() ; - if (normalKeys.test(e.keyCode) || e.ctrlKey) { - // For the backspace key, we suppose the cursor is at the very end - if(e.keyCode == 8) { - that.update(text.substring(0, text.length-1), true); - } - return true ; - } - that.update(text+e.key, false); - - return false ; - - }); - - } - - update(prefix, backspace) { - - var article_list = this.manager.list ; - var lower = prefix.toLowerCase() ; - var that = this ; - this.matching = article_list.articles.filter(function(article) { - return article.name.toLowerCase() - .indexOf(lower) === 0 ; - }); - - this.active_categories = article_list.categories.filter(function(category) { - return that.matching.find(function(article) { - return article.category === category ; - }); - }); - - if (this.matching.length == 1) { - if (!backspace) { - this.manager.validate(this.matching[0]) ; - this.showAll() ; - } else { - this.manager.unset(); - this.updateDisplay(); - } - } else if (this.matching.length > 1) { - this.manager.unset(); - this.updateDisplay() ; - if (!backspace) - this.updatePrefix(); - } - } - - updateDisplay() { - var article_list = this.manager.list ; - for (let article of article_list.articles) { - if (this.matching.indexOf(article) > -1) { - this._$container.find('#data-article-'+article.id).show(); - } else { - this._$container.find('#data-article-'+article.id).hide(); - } - } - - for (let category of article_list.categories) { - if (this.active_categories.indexOf(category) > -1) { - this._$container.find('#data-category-'+category.id).show(); - } else { - this._$container.find('#data-category-'+category.id).hide(); - } - } - } - - updatePrefix() { - var lower = this.matching.map(function (article) { - return article.name.toLowerCase() ; - }); - - lower.sort() ; - var first = lower[0], last = lower[lower.length-1], - length = first.length, i = 0; - while (i < length && first.charAt(i) === last.charAt(i)) i++; - - this._$input.val(first.substring(0,i)) ; - } - - showAll() { - this.matching = this.manager.list.articles; - this.active_categories = this.manager.list.categories; - this.updateDisplay(); - } -} - - $(document).ready(function() { 'use strict'; // ----- @@ -748,206 +356,11 @@ $(document).ready(function() { // Articles data // ----- - var articles_container = $('#articles_data tbody'); - var article_category_default_html = ''; - var article_default_html = ''; - - function addArticle(article) { - var article_html = $(article_default_html); - article_html.attr('id', 'data-article-'+article['id']); - article_html.addClass('data-category-'+article['category_id']); - for (var elem in article) { - article_html.find('.'+elem).text(article[elem]) - } - article_html.find('.price').text(amountToUKF(article['price'], false)); - var category_html = articles_container - .find('#data-category-'+article['category_id']); - if (category_html.length == 0) { - category_html = $(article_category_default_html); - category_html.attr('id', 'data-category-'+article['category_id']); - category_html.find('td').text(article['category__name']); - var added = false; - articles_container.find('.category').each(function() { - if (article['category__name'].toLowerCase() < $(this).text().toLowerCase()) { - $(this).before(category_html); - added = true; - return false; - } - }); - if (!added) articles_container.append(category_html); - } - var $after = articles_container.find('#data-category-'+article['category_id']); - articles_container - .find('.article.data-category-'+article['category_id']).each(function() { - if (article['name'].toLowerCase < $('.name', this).text().toLowerCase()) - return false; - $after = $(this); - }); - $after.after(article_html); - // Pour l'autocomplétion - articlesList.push([article['name'],article['id'],article['category_id'],article['price']]); - } - - function getArticles() { - $.ajax({ - dataType: "json", - url : "{% url 'kfet.kpsul.articles_data' %}", - method : "GET", - }) - .done(function(data) { - for (var i=0; i -1) { - articles_container.find('#data-article-'+articlesList[i][1]).show(); - if (categories_to_display.indexOf(articlesList[i][2]) == -1) - categories_to_display.push(articlesList[i][2]); - } else { - articles_container.find('#data-article-'+articlesList[i][1]).hide(); - } - } - articles_container.find('.category').hide(); - for (var i=0; i 1) { - articleId.val(0); - if (commit) - articleSelect.val(sharedPrefix(articlesMatch)); - displayMatchedArticles(articlesMatch); - } - return false; - } - - // A utiliser après la sélection d'un article - function goToArticleNb() { - articleNb.val('1'); - articleNb.focus().select(); - } - - articleSelect.on('keydown', function(e) { - var text = articleSelect.val(); - // Comportement normal pour ces touches - if (normalKeys.test(e.keyCode) || e.ctrlKey) { - if (text == '' && e.keyCode == 13) - performOperations(); - if (e.keyCode == 8) - updateMatchedArticles(text.substring(0,text.length-1), false); - if (e.charCode == 65 && e.ctrlKey) { - articleId.val(0); - articleSelect.val(''); - } - return true; - } - if (updateMatchedArticles(text+e.key)) - goToArticleNb(); - return false; - }); - - function getArticleId($article) { - return $article.attr('id').split('-')[2]; - } - - function getArticleName($article) { - return $article.find('.name').text(); - } - - // Sélection des articles à la souris/tactile - articles_container.on('click', '.article', function() { - articleId.val(getArticleId($(this))); - articleSelect.val(getArticleName($(this))); - displayMatchedArticles(articlesList); - goToArticleNb(); - }); - - function is_nb_ok(nb) { - return /^[0-9]+$/.test(nb) && nb > 0 && nb <= 24; - } - - articleNb.on('keydown', function(e) { - if (e.keyCode == 13 && is_nb_ok(articleNb.val()) && articleId.val() > 0) { - addPurchase(articleId.val(), articleNb.val()); - articleSelect.val(''); - articleNb.val(''); - articleSelect.focus(); - displayMatchedArticles(articlesList); - return false; - } - if (normalKeys.test(e.keyCode) || arrowKeys.test(e.keyCode) || e.keyCode == 8 || e.ctrlKey) { - if (e.ctrlKey && e.charCode == 65) - articleNb.val(''); - return true; - } - var nb = articleNb.val()+e.key; - if (is_nb_ok(nb)) - return true; - return false; - }); - // ----- // Basket // ----- @@ -956,8 +369,8 @@ $(document).ready(function() { var basket_container = $('#basket table'); var arrowKeys = /^(37|38|39|40)$/; - function amountEuroPurchase(article_data, nb) { - var amount_euro = - article_data[3] * nb ; + function amountEuroPurchase(article, nb) { + var amount_euro = - article.price * nb ; if (Config.get('addcost_for') && Config.get('addcost_amount') && account_manager.account.trigramme != Config.get('addcost_for')) amount_euro -= Config.get('addcost_amount') * nb; var reduc_divisor = 1; @@ -966,19 +379,15 @@ $(document).ready(function() { return amount_euro / reduc_divisor; } - function addPurchase(id, nb) { + function addPurchase(article, nb) { - var i = 0; - while (i