<ul id="store-shelf"> <li data-article="apple">Apple</li> <li data-article="milk">Milk</li> <li data-article="cacke">Cacke</li> <li data-topping="cherry" data-topping-article="cacke">Cherry Topping</li> <li data-topping="cream" data-topping-article="cacke">Cream Topping</li> </ul> <ul id="shop-cart"></ul> <input name="reset" type="button" value="Reset"/> <input name="submit" type="button" value="Submit"/>
$("#shop-cart").droppable({ accept: 'li[data-article]', activeClass: 'active', hoverClass: 'hover', drop: shopCartDropHandler }); $('#store-shelf li').draggable({ cursor: 'pointer', revert: true, stack: 'li' }); function shopCartDropHandler(event, ui) { var clone, counter, $this = $(this), article = ui.draggable.attr('data-article'), existingGoods = $this.children('[data-article="' + article + '"]:not(:has([data-topping]))'); if (existingGoods.length) { counter = existingGoods.find('input[name="quantity"]'); counter.val(parseInt(counter.val()) + 1); } else { counter = $('<input name="quantity" type="number" value="1" min="1"/>'); clone = ui.draggable.clone().css({left: 0, top: 0}).append(counter); clone.droppable({ accept: 'li[data-topping-article="' + article + '"]', activeClass: 'active', hoverClass: 'hover', drop: shopCartItemDropHandler }); $this.append(clone); } } function shopCartItemDropHandler(event, ui) { var span, $this = $(this), topping = ui.draggable.attr('data-topping'), toppingName = ui.draggable.text(), existingToppings = $this.find('span[data-topping="' + topping + '"]'); if (!existingToppings.length) { span = $('<span/>').attr('data-topping', topping).text(toppingName); $this.append(span); } }
<ul id="shop-cart" class="ui-droppable"> <li data-article="cacke">Cacke <input name="quantity" type="number" value="2" min="1"> <span data-topping="cherry">Cherry Topping</span> <span data-topping="cream">Cream Topping</span> </li> <li data-article="cacke">Cacke <input name="quantity" type="number" value="1" min="1"> <span data-topping="cherry">Cherry Topping</span> </li> <li data-article="milk">Milk <input name="quantity" type="number" value="2" min="1"> </li> <li data-article="apple">Apple <input name="quantity" type="number" value="1" min="1"> </li> </ul>
$('input[name="submit"]').click(function () { var result = {items: []}; shopCart.find('li[data-article]').each(function () { var $this = $(this), toppings = [], article = { id: $this.attr('data-article') }, quantity = $this.find('input[name="quantity"]').val(); $this.find('span[data-topping]').each(function () { toppings.push({ id: $(this).attr('data-topping') }); }); result.items.push({ article: article, toppings: toppings, quantity: parseInt(quantity) }); }); $.ajax('/shopping-cart/webresources/cart', { cache: false, contentType: 'application/json', data: JSON.stringify(result), dataType: 'json', type: 'POST' }); });
@Path("cart") @Singleton @ApplicationScoped public class ShoppingResource { @Inject private Storage storage; @GET @Produces(MediaType.APPLICATION_JSON) public ShoppingCart get() { eturn storage.getShoppingCart(); } @POST @Consumes(MediaType.APPLICATION_JSON) public void post(ShoppingCart shoppingCart) { storage.setShoppingCart(shoppingCart);} } @Named @Singleton @ApplicationScoped public class Storage { private final Map<String, Article> articles = new HashMap<>(); private final Map<String, Topping> toppings = new HashMap<>(); private ShoppingCart shoppingCart; @PostConstruct public void init() { Article cacke = new Article("cacke", "Cacke"); putArticles(cacke, new Article("milk", "Milk"), new Article("apple", "Apple")); putToppings( new Topping("cream", "Cream Topping", cacke), new Topping("cherry", "Cherry Topping", cacke)); } private void putArticles(Article... articles) { for (Article article : articles) { his.articles.put(article.getId(), article); } } private void putToppings(Topping... toppings) { for (Topping topping : toppings) { this.toppings.put(topping.getId(), topping); } } @PreDestroy public void clear() { articles.clear(); toppings.clear(); } public Collection<Article> getArticles() { return articles.values(); } public Collection<Topping> getToppings() { return toppings.values(); } public ShoppingCart getShoppingCart() { return shoppingCart; } public void setShoppingCart(ShoppingCart shoppingCart) { ensureConsistence(shoppingCart); this.shoppingCart = shoppingCart; } private void ensureConsistence(ShoppingCart cart) { /* “” “” */ } }
@Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public abstract class JsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> { private static final Logger LOGGER = Logger.getLogger(JsonProvider.class.getName()); private final ConcurrentMap<T, byte[]> serializedMap = new ConcurrentHashMap<>(); private final ObjectMapper mapper = new ObjectMapper(); protected final ObjectMapper getMapper() { return mapper; } protected abstract Class<T> getType(); // Reader Implementation @Override public final boolean isReadable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) { return mt.equals(MediaType.APPLICATION_JSON_TYPE) && getMapper().canDeserialize(getJavaType()) && getType().isAssignableFrom(type); } private JavaType getJavaType() { return TypeFactory.fromClass(getType()); } @Override public T readFrom(Class<T> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, String> mm, InputStream in) throws IOException, WebApplicationException { return (T) getMapper().readValue(in, getClass()); } // Writer Implementation @Override public final boolean isWriteable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) { return mt.equals(MediaType.APPLICATION_JSON_TYPE) && getMapper().canSerialize(getType()) && getType().isAssignableFrom(type); } @Override public final long getSize(T t, Class<?> type, Type type1, Annotation[] antns, MediaType mt) { byte[] result = new byte[0]; try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); getMapper().writeValue(stream, t); result = stream.toByteArray(); serializedMap.put(t, result); } catch (IOException ex) { LOGGER.log(Level.SEVERE, null, ex); } return result.length; } @Override public final void writeTo(T t, Class<?> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, Object> mm, OutputStream out) throws IOException, WebApplicationException { if (serializedMap.containsKey(t)) { byte[] data = serializedMap.remove(t); out.write(data); } out.flush(); } }
<ul id="store-shelf"> <c:forEach var="article" items="#{storage.articles}"> <li data-article="${article.id}">${article.name}</li> </c:forEach> <c:forEach var="topping" items="#{storage.toppings}"> <li data-topping="${topping.id}" data-topping-article="${topping.article.id}">${topping.name}</li> </c:forEach> </ul> <ul id="shop-cart"> <c:forEach var="item" items="#{storage.shoppingCart.items}"> <li data-article="${item.article.id}">${item.article.name} <c:forEach var="topping" items="${item.toppings}"> <span data-topping="${topping.id}">${topping.name}</span> </c:forEach> <input name="quantity" type="number" value="${item.quantity}" min="1"/> </li> </c:forEach> </ul>
Source: https://habr.com/ru/post/169577/