Skip to content

Instantly share code, notes, and snippets.

@iancover
Last active February 5, 2022 12:56
Show Gist options
  • Select an option

  • Save iancover/b0b4337aad9f4373c4d361b75be73f6c to your computer and use it in GitHub Desktop.

Select an option

Save iancover/b0b4337aad9f4373c4d361b75be73f6c to your computer and use it in GitHub Desktop.

Revisions

  1. iancover revised this gist Feb 5, 2022. 4 changed files with 140 additions and 116 deletions.
    114 changes: 0 additions & 114 deletions SL-apps.js
    Original file line number Diff line number Diff line change
    @@ -1,114 +0,0 @@
    // **** GLOBAL STATE OBJECT ****

    var state = {
    items: []
    };

    // **** HTML TO RENDER ****

    var listItemTemplate = (
    '<li>' +
    '<span class="shopping-item js-shopping-item"></span>' +
    '<div class="shopping-items-controls">' +
    '<button class="js-shopping-item-toggle">' +
    '<span class="button-label">Check</span>' +
    '</button>' +
    '<button class="js-shopping-item-delete">' +
    '<span class="button-label">Delete</span>' +
    '</button>' +
    '</div>' +
    '</li>'
    );


    // **** STATE MGMT ****

    function addItem(state, item) {
    state.items.push({
    displayName: item,
    checkedOff: false
    });
    }

    function getItem(state, itemIndex) {
    return state.items[itemIndex];
    }

    function deleteItem(state, itemIndex) {
    state.items.splice(itemIndex, 1);
    }

    function updateItem(state, itemIndex) {
    state.items[itemIndex] = newItemState;
    }

    // **** DOM MANIPULATION ****

    function renderItem(item, itemId, itemTemplate, itemDataAttr) {
    var element = $(itemTemplate);
    element.find('.js-shopping-item').text(item.displayName);
    if (item.checkedOff) {
    element.find('.js-shopping-item').addClass('shopping-item_checked');
    }
    element.find('.js-shopping-item-toggle');
    element.attr(itemDataAttr,itemId);
    return element;
    }

    function renderList(state, listElement, itemDataAttr) {
    var itemsHTML = state.items.map(function(item, index) {
    return renderItem(item, index, listItemTemplate, itemDataAttr);
    });
    listElement.html(itemsHTML);
    }


    // **** LISTENERS ****

    function handleItemAdds(formElement, newItemIdentifier, itemDataAttr, listElement, state) {
    formElement.submit(function(event) {
    event.preventDefault();
    var newItem = formElement.find(newItemIdentifier).val();
    addItem(state, newItem);
    renderList(state, listElement, itemDataAttr);
    this.reset();
    });
    }

    function handleItemDeletes(formElement, removeIdentifier, itemDataAttr, listElement, state) {
    listElement.on('click', removeIdentifier, function(event) {
    var itemIndex = parseInt($(this).closest('li').attr(itemDataAttr));
    deleteItem(state, itemIndex);
    renderList(state, listElement, itemDataAttr);
    });
    }

    function handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state) {
    listElement.on('click', toggleIdentifier, function(event) {
    var itemId = $(event.currentTarget.closest('li')).attr(itemDataAttr);
    var oldItem = getItem(state, itemId);
    updateItem(state, itemId, {
    displayName: oldItem.displayName,
    checkedOff: !oldItem.checkedOff
    });
    renderList(state, listElement, itemDataAttr)
    });
    }


    // **** CONTROLLER ****

    $(function() {
    var formElement = $('#js-shopping-list-form');
    var listElement = $('.js-shopping-list');
    var newItemIdentifier = '#js-new-item';
    var removeIdentifier = '.js-shopping-item-delete';
    var itemDataAttr = 'data-list-item-id';
    var toggleIdentifier = '.js-shopping-item-toggle';

    handleItemAdds(formElement, newItemIdentifier, itemDataAttr, listElement, state);
    handleItemDeletes(formElement, removeIdentifier, itemDataAttr, listElement, state);
    handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state);
    });


    137 changes: 137 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,137 @@
    // **** GLOBAL STATE OBJECT ****

    var state = {
    items: [],
    };

    // **** HTML TO RENDER ****

    var listItemTemplate =
    '<li>' +
    '<span class="shopping-item js-shopping-item"></span>' +
    '<div class="shopping-items-controls">' +
    '<button class="js-shopping-item-toggle">' +
    '<span class="button-label">Check</span>' +
    '</button>' +
    '<button class="js-shopping-item-delete">' +
    '<span class="button-label">Delete</span>' +
    '</button>' +
    '</div>' +
    '</li>';

    // **** STATE MGMT ****

    function addItem(state, item) {
    state.items.push({
    displayName: item,
    checkedOff: false,
    });
    }

    function getItem(state, itemIndex) {
    return state.items[itemIndex];
    }

    function deleteItem(state, itemIndex) {
    state.items.splice(itemIndex, 1);
    }

    function updateItem(state, itemIndex) {
    state.items[itemIndex] = newItemState;
    }

    // **** DOM MANIPULATION ****

    function renderItem(item, itemId, itemTemplate, itemDataAttr) {
    var element = $(itemTemplate);
    element.find('.js-shopping-item').text(item.displayName);
    if (item.checkedOff) {
    element.find('.js-shopping-item').addClass('shopping-item_checked');
    }
    element.find('.js-shopping-item-toggle');
    element.attr(itemDataAttr, itemId);
    return element;
    }

    function renderList(state, listElement, itemDataAttr) {
    var itemsHTML = state.items.map(function (item, index) {
    return renderItem(item, index, listItemTemplate, itemDataAttr);
    });
    listElement.html(itemsHTML);
    }

    // **** LISTENERS ****

    function handleItemAdds(
    formElement,
    newItemIdentifier,
    itemDataAttr,
    listElement,
    state
    ) {
    formElement.submit(function (event) {
    event.preventDefault();
    var newItem = formElement.find(newItemIdentifier).val();
    addItem(state, newItem);
    renderList(state, listElement, itemDataAttr);
    this.reset();
    });
    }

    function handleItemDeletes(
    formElement,
    removeIdentifier,
    itemDataAttr,
    listElement,
    state
    ) {
    listElement.on('click', removeIdentifier, function (event) {
    var itemIndex = parseInt($(this).closest('li').attr(itemDataAttr));
    deleteItem(state, itemIndex);
    renderList(state, listElement, itemDataAttr);
    });
    }

    function handleItemToggles(
    listElement,
    toggleIdentifier,
    itemDataAttr,
    state
    ) {
    listElement.on('click', toggleIdentifier, function (event) {
    var itemId = $(event.currentTarget.closest('li')).attr(itemDataAttr);
    var oldItem = getItem(state, itemId);
    updateItem(state, itemId, {
    displayName: oldItem.displayName,
    checkedOff: !oldItem.checkedOff,
    });
    renderList(state, listElement, itemDataAttr);
    });
    }

    // **** CONTROLLER ****

    $(function () {
    var formElement = $('#js-shopping-list-form');
    var listElement = $('.js-shopping-list');
    var newItemIdentifier = '#js-new-item';
    var removeIdentifier = '.js-shopping-item-delete';
    var itemDataAttr = 'data-list-item-id';
    var toggleIdentifier = '.js-shopping-item-toggle';

    handleItemAdds(
    formElement,
    newItemIdentifier,
    itemDataAttr,
    listElement,
    state
    );
    handleItemDeletes(
    formElement,
    removeIdentifier,
    itemDataAttr,
    listElement,
    state
    );
    handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state);
    });
    File renamed without changes.
    5 changes: 3 additions & 2 deletions SL-main.css → main.css
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,8 @@ body {
    font-family: 'Roboto', sans-serif;
    }

    button, input[type="text"] {
    button,
    input[type='text'] {
    padding: 5px;
    }

    @@ -44,4 +45,4 @@ button:hover {

    .shopping-item__checked {
    text-decoration: line-through;
    }
    }
  2. iancover created this gist Jun 6, 2017.
    114 changes: 114 additions & 0 deletions SL-apps.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,114 @@
    // **** GLOBAL STATE OBJECT ****

    var state = {
    items: []
    };

    // **** HTML TO RENDER ****

    var listItemTemplate = (
    '<li>' +
    '<span class="shopping-item js-shopping-item"></span>' +
    '<div class="shopping-items-controls">' +
    '<button class="js-shopping-item-toggle">' +
    '<span class="button-label">Check</span>' +
    '</button>' +
    '<button class="js-shopping-item-delete">' +
    '<span class="button-label">Delete</span>' +
    '</button>' +
    '</div>' +
    '</li>'
    );


    // **** STATE MGMT ****

    function addItem(state, item) {
    state.items.push({
    displayName: item,
    checkedOff: false
    });
    }

    function getItem(state, itemIndex) {
    return state.items[itemIndex];
    }

    function deleteItem(state, itemIndex) {
    state.items.splice(itemIndex, 1);
    }

    function updateItem(state, itemIndex) {
    state.items[itemIndex] = newItemState;
    }

    // **** DOM MANIPULATION ****

    function renderItem(item, itemId, itemTemplate, itemDataAttr) {
    var element = $(itemTemplate);
    element.find('.js-shopping-item').text(item.displayName);
    if (item.checkedOff) {
    element.find('.js-shopping-item').addClass('shopping-item_checked');
    }
    element.find('.js-shopping-item-toggle');
    element.attr(itemDataAttr,itemId);
    return element;
    }

    function renderList(state, listElement, itemDataAttr) {
    var itemsHTML = state.items.map(function(item, index) {
    return renderItem(item, index, listItemTemplate, itemDataAttr);
    });
    listElement.html(itemsHTML);
    }


    // **** LISTENERS ****

    function handleItemAdds(formElement, newItemIdentifier, itemDataAttr, listElement, state) {
    formElement.submit(function(event) {
    event.preventDefault();
    var newItem = formElement.find(newItemIdentifier).val();
    addItem(state, newItem);
    renderList(state, listElement, itemDataAttr);
    this.reset();
    });
    }

    function handleItemDeletes(formElement, removeIdentifier, itemDataAttr, listElement, state) {
    listElement.on('click', removeIdentifier, function(event) {
    var itemIndex = parseInt($(this).closest('li').attr(itemDataAttr));
    deleteItem(state, itemIndex);
    renderList(state, listElement, itemDataAttr);
    });
    }

    function handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state) {
    listElement.on('click', toggleIdentifier, function(event) {
    var itemId = $(event.currentTarget.closest('li')).attr(itemDataAttr);
    var oldItem = getItem(state, itemId);
    updateItem(state, itemId, {
    displayName: oldItem.displayName,
    checkedOff: !oldItem.checkedOff
    });
    renderList(state, listElement, itemDataAttr)
    });
    }


    // **** CONTROLLER ****

    $(function() {
    var formElement = $('#js-shopping-list-form');
    var listElement = $('.js-shopping-list');
    var newItemIdentifier = '#js-new-item';
    var removeIdentifier = '.js-shopping-item-delete';
    var itemDataAttr = 'data-list-item-id';
    var toggleIdentifier = '.js-shopping-item-toggle';

    handleItemAdds(formElement, newItemIdentifier, itemDataAttr, listElement, state);
    handleItemDeletes(formElement, removeIdentifier, itemDataAttr, listElement, state);
    handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state);
    });


    31 changes: 31 additions & 0 deletions SL-index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <title>Shopping List</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css">
    <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">

    <link rel="stylesheet" href="main.css">
    </head>
    <body>

    <div class="container">
    <h1>Shopping List</h1>

    <form id="js-shopping-list-form">
    <label for="shopping-list-entry">Add an item</label>
    <input type="text" name="shopping-list-entry" id="shopping-list-entry" placeholder="e.g., broccoli">
    <button type="submit">Add item</button>
    </form>

    <ul class="shopping-list">

    </ul>

    <script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>

    <script type="text/javascript" src="app.js"></script>

    </body>
    </html>
    47 changes: 47 additions & 0 deletions SL-main.css
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    * {
    box-sizing: border-box;
    }

    body {
    font-family: 'Roboto', sans-serif;
    }

    button, input[type="text"] {
    padding: 5px;
    }

    button:hover {
    cursor: pointer;
    }

    #shopping-list-item {
    width: 250px;
    }

    .container {
    max-width: 600px;
    margin: 0 auto;
    }

    .shopping-list {
    list-style: none;
    padding-left: 0;
    }

    .shopping-list > li {
    margin-bottom: 20px;
    border: 1px solid grey;
    padding: 20px;
    }

    .shopping-item {
    display: block;
    color: grey;
    font-style: italic;
    font-size: 20px;
    margin-bottom: 15px;
    }

    .shopping-item__checked {
    text-decoration: line-through;
    }