<commit_before>/*
 * Copyright 2014 WebFilings, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(function(require) {
    'use strict';

    var requestAnimFrame = require('wf-js-common/requestAnimationFrame');
    var EventTypes = require('wf-js-uicomponents/awesome_map/EventTypes');

    /**
     * Creates a new ScrollBar with the given ScrollList and options.
     *
     * @classdesc
     *
     * A ScrollBar provides a UI based on the traditional browser scrollbar
     * for users to scroll the ScrollList.
     *
     * @name ScrollBar
     * @constructor
     *
     * @param {ScrollList} scrollList
     *        The ScrollList that the ScrollBar is constructed for
     *
     * @param {HTMLElement} parent
     *        The parent element for the ScrollBar to be created within
     *
     * @param {Object} options
     *        An object with optional classes and ids to be placed on the
     *        scrollbarEL and scrollbarContainerEL.
     *
     * @param {number} options.minHeight
     *        The minimum height, in pixels, of the ScrollBar
     *        If not provided, the minHeight will default to 16
     *
     *
     * @example
     *
     * var parent = getElementById('parent');
     * var options = {};
     *
     * options.scrollbarId = "scrollbar";
     * options.scrollbarClass = "scrollbar";
     * options.scrollbarContainerId = "scrollbar-container";
     * options.scrollbarContainerClass = "scrollbar-container";
     * options.minHeight = 8;
     *
     * scrollBar = new ScrollBar(scrollList, parent, options);
     */

    var ScrollBar = function(scrollList, parent, options) {
        var offset;
        var that = this;

        if (!scrollList) {
            throw new Error('ScrollBar#ScrollBar: scrollList is required');
        }
        else {
            this._scrollList = scrollList;
        }

        if (!parent) {
            throw new Error('ScrollBar#ScrollBar: parent is required.');
        }
        else {
            this._parent = parent;
        }

        this._options = options;

        this._layout = scrollList.getLayout();

        this._TOTAL_ITEMS = scrollList.getItemSizeCollection ? scrollList.getItemSizeCollection()._items.length :
                            scrollList.getItemMetadata().length;

        this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;

        this._virtualHeight = this._layout.getSize().height - this._viewportHeight;

        this._scrollableVirtualHeight = this._layout.getSize().height;

        this._listMap = this._scrollList.getListMap();

        this._setUpDOM();

        this._availableScrollbarHeight = this._viewportHeight - this._scrollbarHeight;

        // Set scrollbarScrolling to initially false
        this._scrollbarScrolling = false;

        this._clickOffset = null;

        // Get the initial position, in case it's not at 0, and set the scrollbar position
        requestAnimFrame(function() {
            that._placeScrollBar(that, that._elements.scrollbar);
        });

        // Match the scroll bar positioning to the users scrolling
        this._listMap.onTranslationChanged(function() {
            if (that._scrollbarScrolling) {
                return;
            }
            requestAnimFrame(function() {
                that._placeScrollBar();
            });
        });

        // Make necessary adjustments when the users zooms in or out
        this._listMap.onScaleChanged(function() {
            that._adjustScale();
            that._placeScrollBar();
        });

        this._scrollList.onItemsInserted(function() {
            that._TOTAL_ITEMS = scrollList.getItemSizeCollection()._items.length;
            that._adjustScale();
            that._placeScrollBar();
        });

        // Make adjustments when the scrollList is resized
        this._scrollList.onInteraction(function(scrollList, args) {
            if (args.event.type === EventTypes.RESIZE) {
                that._resize = true;
            }

            if (args.event.type === EventTypes.RELEASE && that._resize === true) {
                that._adjustScale();
                that._resize = false;
            }
        });

        // Attach handlers for scrolling the ScrollBar
        this._elements.scrollbar.addEventListener('mousedown', function(event) {
            offset = that._elements.scrollbar.offsetTop + that._elements.scrollbarContainer.offsetTop;
            that._clickOffset = event.clientY - offset + that._elements.scrollbarContainer.offsetTop;
            that._scrollbarScrolling = true;

            that._mouseupHandler = function() {
                that._stopUpdatingScrollbar();
            };

            that._mousemoveHandler = function(e) {
                that._updateScrollBar(e, that._clickOffset);
            };

            document.addEventListener('mousemove', that._mousemoveHandler);

            document.addEventListener('mouseup', that._mouseupHandler);
        });

    };

    ScrollBar.prototype = {

        //---------------------------------------------------------
        // Public methods
        //---------------------------------------------------------

        /**
         * Destruct the ScrollBar created HTML elements
         * @method ScrollBar#dispose
         */
        dispose: function() {
            this._elements.scrollbarContainer.removeChild(this._elements.scrollbar);
            this._parent.removeChild(this._elements.scrollbarContainer);
        },

        //---------------------------------------------------------
        // Private methods
        //---------------------------------------------------------

        /**
         * Initialize the HTML elements used by this instance of ScrollBar
         * @private
         */
        _setUpDOM: function() {
            // Create the scrollbar's container
            var scrollbarContainerEL = document.createElement('div');
            var scrollbarEL = document.createElement('div');

            // Set the given classes and ids scrollbar and it's container
            if (this._options.scrollbarId) {
                scrollbarEL.setAttribute('id', this._options.scrollbarId);
            }
            if (this._options.scrollbarClass) {
                scrollbarEL.className += ' ' + this._options.scrollbarClass;
            }
            if (this._options.scrollbarContainerId) {
                scrollbarContainerEL.setAttribute('id', this._options.scrollbarContainerId);
            }
            if (this._options.scrollbarContainerClass) {
                scrollbarContainerEL.className += ' ' + this._options.scrollbarContainerClass;
            }

            // Append the scrollbar and it's parent container to the given parent element
            scrollbarContainerEL.appendChild(scrollbarEL);
            this._parent.appendChild(scrollbarContainerEL);

            this._elements = { scrollbar: scrollbarEL, scrollbarContainer: scrollbarContainerEL };

            this._adjustScale();

            // Set the container height to the viewport height
            scrollbarContainerEL.style.height = this._layout.getViewportSize().height + 'px';
            // Set the scrollbar height
            scrollbarEL.style.height = this._scrollbarHeight + 'px';
        },

        /**
         * Position the scrollbar based on the current position of the ScrollList
         */
        _placeScrollBar: function() {
            var currentPosition = this._layout.getVisiblePosition().top;
            var translatedPosition = this._availableScrollbarHeight / this._virtualHeight * currentPosition;
            this._elements.scrollbar.style.top = translatedPosition + 'px';
        },

        /**
         * Position the scrollbar based on the position of a click event
         */
        _updateScrollBar: function(event, clickOffset) {
            // Don't go past the window bounds
            var scrollbarPos = Math.max(0, event.clientY - clickOffset);
            // maxPos expresses the maximum distance the top of the scrollbar can be from the top of the container
            // Unlike availableScrollBarHeight, this is scaled.
            var maxPos = this._layout.getViewportSize().height - (this._scrollbarHeight * this._scale);
            scrollbarPos = Math.min(scrollbarPos, maxPos);

            // Use the ratio of scrollbar position inside the scrolling area to calculate
            // the current item we should be interested in.
            var positionOfInterest = ((scrollbarPos) / (this._viewportHeight - this._scrollbarHeight)) * (this._virtualHeight);

            // Ensure that positionOfInterest isn't undefined.
            if (!positionOfInterest) {
                positionOfInterest = 0;
            }

            var x = this._listMap.getCurrentTransformState().translateX;

            this._listMap.transform({
                x: x,
                y: -positionOfInterest,
                scale: this._scale
            });

            this._scrollList.render();
            this._placeScrollBar();
        },

        /**
         * Remove the event listeners that update the scrollbar from the document
         */
        _stopUpdatingScrollbar: function() {
            this._clickOffset = undefined;
            document.removeEventListener('mousemove', this._mousemoveHandler);
            this._scrollbarScrolling = false;
            this._removeDocumentEventWatching(this);
        },

        /**
         * Remove the mouseup listener from the document
         */
        _removeDocumentEventWatching: function() {
            document.removeEventListener('mouseup', this._mouseupHandler);
        },

        /**
         * Calculate the scroll bar height based on the viewport height and the scaled virtual height
         */
        _calculateScrollBarHeight: function() {
            // Calculate the size of the scrollbar depending on the virtual height
            // The scrollbar shouldn't be shorter than MIN_HEIGHT
            var MIN_HEIGHT = this._options.minHeight || 8;
            var height = Math.max(MIN_HEIGHT, (this._viewportHeight / this._scrollableVirtualHeight) * this._layout.getViewportSize().height);

            return height;
        },

        /**
         * Scale the virtual height and re-calculate the scroll bar height
         */
        _adjustScale: function() {
            this._scale = this._listMap.getCurrentTransformState().scale;
            this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;
            this._virtualHeight = this._layout.getSize().height - this._viewportHeight;
            this._scrollableVirtualHeight = this._layout.getSize().height;
            this._scrollbarHeight = this._calculateScrollBarHeight();
            this._elements.scrollbar.style.height = this._scrollbarHeight + 'px';
            this._elements.scrollbarContainer.style.height = this._layout.getViewportSize().height + 'px';
            this._availableScrollbarHeight = this._layout.getViewportSize().height - this._scrollbarHeight;
        }

    };

    return ScrollBar;

});
<commit_msg>Refactor ScrollBar._updateScrollBar to not use _placeScrollBar<commit_after>/*
 * Copyright 2014 WebFilings, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(function(require) {
    'use strict';

    var requestAnimFrame = require('wf-js-common/requestAnimationFrame');
    var EventTypes = require('wf-js-uicomponents/awesome_map/EventTypes');

    /**
     * Creates a new ScrollBar with the given ScrollList and options.
     *
     * @classdesc
     *
     * A ScrollBar provides a UI based on the traditional browser scrollbar
     * for users to scroll the ScrollList.
     *
     * @name ScrollBar
     * @constructor
     *
     * @param {ScrollList} scrollList
     *        The ScrollList that the ScrollBar is constructed for
     *
     * @param {HTMLElement} parent
     *        The parent element for the ScrollBar to be created within
     *
     * @param {Object} options
     *        An object with optional classes and ids to be placed on the
     *        scrollbarEL and scrollbarContainerEL.
     *
     * @param {number} options.minHeight
     *        The minimum height, in pixels, of the ScrollBar
     *        If not provided, the minHeight will default to 16
     *
     *
     * @example
     *
     * var parent = getElementById('parent');
     * var options = {};
     *
     * options.scrollbarId = "scrollbar";
     * options.scrollbarClass = "scrollbar";
     * options.scrollbarContainerId = "scrollbar-container";
     * options.scrollbarContainerClass = "scrollbar-container";
     * options.minHeight = 8;
     *
     * scrollBar = new ScrollBar(scrollList, parent, options);
     */

    var ScrollBar = function(scrollList, parent, options) {
        var offset;
        var that = this;

        if (!scrollList) {
            throw new Error('ScrollBar#ScrollBar: scrollList is required');
        }
        else {
            this._scrollList = scrollList;
        }

        if (!parent) {
            throw new Error('ScrollBar#ScrollBar: parent is required.');
        }
        else {
            this._parent = parent;
        }

        this._options = options;

        this._layout = scrollList.getLayout();

        this._TOTAL_ITEMS = scrollList.getItemSizeCollection ? scrollList.getItemSizeCollection()._items.length :
                            scrollList.getItemMetadata().length;

        this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;

        this._virtualHeight = this._layout.getSize().height - this._viewportHeight;

        this._scrollableVirtualHeight = this._layout.getSize().height;

        this._listMap = this._scrollList.getListMap();

        this._setUpDOM();

        this._availableScrollbarHeight = this._viewportHeight - this._scrollbarHeight;

        // Set scrollbarScrolling to initially false
        this._scrollbarScrolling = false;

        this._clickOffset = null;

        // Get the initial position, in case it's not at 0, and set the scrollbar position
        requestAnimFrame(function() {
            that._placeScrollBar(that, that._elements.scrollbar);
        });

        // Match the scroll bar positioning to the users scrolling
        this._listMap.onTranslationChanged(function() {
            if (that._scrollbarScrolling) {
                return;
            }
            requestAnimFrame(function() {
                that._placeScrollBar();
            });
        });

        // Make necessary adjustments when the users zooms in or out
        this._listMap.onScaleChanged(function() {
            that._adjustScale();
            that._placeScrollBar();
        });

        this._scrollList.onItemsInserted(function() {
            that._TOTAL_ITEMS = scrollList.getItemSizeCollection()._items.length;
            that._adjustScale();
            that._placeScrollBar();
        });

        // Make adjustments when the scrollList is resized
        this._scrollList.onInteraction(function(scrollList, args) {
            if (args.event.type === EventTypes.RESIZE) {
                that._resize = true;
            }

            if (args.event.type === EventTypes.RELEASE && that._resize === true) {
                that._adjustScale();
                that._resize = false;
            }
        });

        // Attach handlers for scrolling the ScrollBar
        this._elements.scrollbar.addEventListener('mousedown', function(event) {
            offset = that._elements.scrollbar.offsetTop + that._elements.scrollbarContainer.offsetTop;
            that._clickOffset = event.clientY - offset + that._elements.scrollbarContainer.offsetTop;
            that._scrollbarScrolling = true;

            that._mouseupHandler = function() {
                that._stopUpdatingScrollbar();
            };

            that._mousemoveHandler = function(e) {
                that._updateScrollBar(e, that._clickOffset);
            };

            document.addEventListener('mousemove', that._mousemoveHandler);

            document.addEventListener('mouseup', that._mouseupHandler);
        });

    };

    ScrollBar.prototype = {

        //---------------------------------------------------------
        // Public methods
        //---------------------------------------------------------

        /**
         * Destruct the ScrollBar created HTML elements
         * @method ScrollBar#dispose
         */
        dispose: function() {
            this._elements.scrollbarContainer.removeChild(this._elements.scrollbar);
            this._parent.removeChild(this._elements.scrollbarContainer);
        },

        //---------------------------------------------------------
        // Private methods
        //---------------------------------------------------------

        /**
         * Initialize the HTML elements used by this instance of ScrollBar
         * @private
         */
        _setUpDOM: function() {
            // Create the scrollbar's container
            var scrollbarContainerEL = document.createElement('div');
            var scrollbarEL = document.createElement('div');

            // Set the given classes and ids scrollbar and it's container
            if (this._options.scrollbarId) {
                scrollbarEL.setAttribute('id', this._options.scrollbarId);
            }
            if (this._options.scrollbarClass) {
                scrollbarEL.className += ' ' + this._options.scrollbarClass;
            }
            if (this._options.scrollbarContainerId) {
                scrollbarContainerEL.setAttribute('id', this._options.scrollbarContainerId);
            }
            if (this._options.scrollbarContainerClass) {
                scrollbarContainerEL.className += ' ' + this._options.scrollbarContainerClass;
            }

            // Append the scrollbar and it's parent container to the given parent element
            scrollbarContainerEL.appendChild(scrollbarEL);
            this._parent.appendChild(scrollbarContainerEL);

            this._elements = { scrollbar: scrollbarEL, scrollbarContainer: scrollbarContainerEL };

            this._adjustScale();

            // Set the container height to the viewport height
            scrollbarContainerEL.style.height = this._layout.getViewportSize().height + 'px';
            // Set the scrollbar height
            scrollbarEL.style.height = this._scrollbarHeight + 'px';
        },

        /**
         * Position the scrollbar based on the current position of the ScrollList
         */
        _placeScrollBar: function() {
            var currentPosition = this._layout.getVisiblePosition().top;
            var translatedPosition = this._availableScrollbarHeight / this._virtualHeight * currentPosition;
            this._elements.scrollbar.style.top = translatedPosition + 'px';
        },

        /**
         * Position the scrollbar based on the position of a click event
         */
        _updateScrollBar: function(event, clickOffset) {
            var scrollbarPos = Math.max(0, event.clientY - clickOffset);
            var scrollListPos = scrollbarPos;
            // Don't go past the bounds of the scrollbar container
            scrollbarPos = Math.min(scrollbarPos, this._availableScrollbarHeight);
            this._elements.scrollbar.style.top = scrollbarPos + 'px';

            // Use the ratio of scrollbar position inside the scrolling area to calculate
            // the current item we should be interested in.
            var positionOfInterest = (scrollListPos * this._scale / this._availableScrollbarHeight) * this._virtualHeight;

            // Ensure that positionOfInterest isn't undefined.
            if (!positionOfInterest) {
                positionOfInterest = 0;
            }
            positionOfInterest = Math.min(positionOfInterest, this._virtualHeight * this._scale);

            var x = this._listMap.getCurrentTransformState().translateX;

            this._listMap.transform({
                x: x,
                y: -positionOfInterest,
                scale: this._scale
            });

            this._scrollList.render();
        },

        /**
         * Remove the event listeners that update the scrollbar from the document
         */
        _stopUpdatingScrollbar: function() {
            this._clickOffset = undefined;
            document.removeEventListener('mousemove', this._mousemoveHandler);
            this._scrollbarScrolling = false;
            this._removeDocumentEventWatching(this);
        },

        /**
         * Remove the mouseup listener from the document
         */
        _removeDocumentEventWatching: function() {
            document.removeEventListener('mouseup', this._mouseupHandler);
        },

        /**
         * Calculate the scroll bar height based on the viewport height and the scaled virtual height
         */
        _calculateScrollBarHeight: function() {
            // Calculate the size of the scrollbar depending on the virtual height
            // The scrollbar shouldn't be shorter than MIN_HEIGHT
            var MIN_HEIGHT = this._options.minHeight || 8;
            var height = Math.max(MIN_HEIGHT, (this._viewportHeight / this._scrollableVirtualHeight) * this._layout.getViewportSize().height);

            return height;
        },

        /**
         * Scale the virtual height and re-calculate the scroll bar height
         */
        _adjustScale: function() {
            this._scale = this._listMap.getCurrentTransformState().scale;
            this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;
            this._virtualHeight = this._layout.getSize().height - this._viewportHeight;
            this._scrollableVirtualHeight = this._layout.getSize().height;
            this._scrollbarHeight = this._calculateScrollBarHeight();
            this._elements.scrollbar.style.height = this._scrollbarHeight + 'px';
            this._elements.scrollbarContainer.style.height = this._layout.getViewportSize().height + 'px';
            this._availableScrollbarHeight = this._layout.getViewportSize().height - this._scrollbarHeight;
        }

    };

    return ScrollBar;

});
<|endoftext|>


<commit_before>import { selectValueByKey } from './'

// allow for setting the default root selector by type
const __DEFAULT_ROOT_SELECTOR__ = '@@redux-data/__DEFAULT__'
const rootSelectorsByType = {
  [__DEFAULT_ROOT_SELECTOR__]: state => type => state[type]
}

export const setCollectionRootSelector = (type, reducer) => {
  rootSelectorsByType[type] = reducer
}

export const selectRootOfType = state => type => {
  const selector = rootSelectorsByType[type]
  if (!selector) {
    return rootSelectorsByType[__DEFAULT_ROOT_SELECTOR__](state)(type)
  }
  return selector(state)
}

export const selectItems = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const data = selectCollectionData(collection)
  if (key) {
    let set
    if (options && options.page) {
      const page = selectSet({ type, key, options })
      set = page && page.data
    } else {
      set = selectFullSetItems(state)({ type, key, options })
    }
    if (!set) { return [] }
    return set.map(({ type, id }) => data.find(item => item.type === type && item.id === id))
  }
  return data
}

export const selectSet = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  const { sets } = meta
  if (!sets) { return }
  let page = '1'
  if (options && options.page) { page = `${options.page}` }
  const set = sets[key]
  if (!set) { return }
  return set[page]
}

export const selectFullSetItems = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  const { sets } = meta
  if (!sets) { return }
  const set = sets[key]
  if (!set) { return }
  const items = Object.keys(set).sort().reduce((list, page) => {
    const setPage = set[page]
    const { data } = setPage
    if (data) { return list.concat(data) }
    return list
  }, [])
  return items
}

// ----

export const selectCollectionData = (collection) => selectValueByKey(collection)('data')
export const selectCollectionMeta = (collection) => selectValueByKey(collection)('meta')

export const selectCollectionIsLoading = state => type => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  return selectValueByKey(meta)('isLoading')
}

export const selectCollectionIsLoaded = state => type => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  return selectValueByKey(meta)('isLoading')
}
<commit_msg>adding some selectors for collections<commit_after>import { selectValueByKey } from './'

// allow for setting the default root selector by type
const __DEFAULT_ROOT_SELECTOR__ = '@@redux-data/__DEFAULT__'
const rootSelectorsByType = {
  [__DEFAULT_ROOT_SELECTOR__]: state => type => state[type]
}

export const setCollectionRootSelector = (type, reducer) => {
  rootSelectorsByType[type] = reducer
}

export const selectRootOfType = state => type => {
  const selector = rootSelectorsByType[type]
  if (!selector) {
    return rootSelectorsByType[__DEFAULT_ROOT_SELECTOR__](state)(type)
  }
  return selector(state)
}

export const selectItems = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const data = selectCollectionData(collection)
  if (key) {
    let set
    if (options && options.page) {
      set = selectSetItems(state)({ type, key, options })
    } else {
      set = selectFullSetItems(state)({ type, key, options })
    }
    console.log({ type, key, options, set })
    if (!set) { return [] }
    return set.map(({ type, id }) => data.find(item => item.type === type && item.id === id))
  }
  return data
}

export const selectSet = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  const { sets } = meta
  if (!sets) { return }
  const set = sets[key]
  if (!set) { return }
  let page = '1'
  if (options && options.page) { page = `${options.page}` }
  return set[page]
}

export const selectSetItems = state => ({ type, key, options }) => {
  const { data } = selectSet(state)({ type, key, options })
  return data
}

export const selectFullSetItems = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  const { sets } = meta
  if (!sets) { return }
  const set = sets[key]
  if (!set) { return }
  const items = Object.keys(set).sort((a, b) => a - b).reduce((list, page) => {
    const setPage = set[page]
    const { data } = setPage
    if (data) { return list.concat(data) }
    return list
  }, [])
  return items
}

export const selectLastLoadedPageNum = state => ({ type, key, options }) => {
  const collection = selectRootOfType(state)(type)
  const collectionMeta = selectCollectionMeta(collection)
  const { sets } = collectionMeta
  if (!sets) { return }
  const set = sets[key]
  if (!set) { return }
  return Object.keys(set).sort((a, b) => a - b).reverse()[0]
}

export const selectIsLoaded = state => ({ type, key, options }) => {
  let meta
  if (key) {
    // NOTE: selectSet returns by page
    // TODO: should return collection.meta.sets[key].meta.isLoading <-- sets[key].meta currently doesn't exist
    // TODO: should return collection.meta.sets[key].data[page].meta.isLoading <-- sets[key].data currently doesn't exist
    const set = selectSet(state)({ type, key, options })
    meta = selectValueByKey(set)('meta')
  } else {
    const collection = selectRootOfType(state)(type)
    meta = selectCollectionMeta(collection)
  }
  return selectValueByKey(meta)('isLoaded')
}

export const selectIsLoading = state => ({ type, key, options }) => {
  let meta
  if (key) {
    const set = selectSet(state)({ type, key, options })
    meta = selectValueByKey(set)('meta')
  } else {
    const collection = selectRootOfType(state)(type)
    meta = selectCollectionMeta(collection)
  }
  return selectValueByKey(meta)('isLoading')
}

// ----

export const selectCollectionData = (collection) => selectValueByKey(collection)('data')
export const selectCollectionMeta = (collection) => selectValueByKey(collection)('meta')

export const selectCollectionIsLoading = state => type => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  return selectValueByKey(meta)('isLoading')
}

export const selectCollectionIsLoaded = state => type => {
  const collection = selectRootOfType(state)(type)
  const meta = selectCollectionMeta(collection)
  return selectValueByKey(meta)('isLoading')
}
<|endoftext|>


<commit_before>/**
 * StructuredFun javascript
 * QUnit test harness
 */
(function($, sfun, undefined) {

  // ---------
  // CONSTANTS
  // ---------

  // ---------
  // FUNCTIONS
  // ---------

  var init = function() {
    var obj = {
      'context': this,
      'callback': bindToTemplate,
      'view': {
        'title': 'Test'
      },
      'template': getTemplate()
    };
    // once script is loaded and executes, push header button async
    sfun.push('headerAddButton', obj);
  };

  var getTemplate = function() {
    var str = '
{{ title }}
';
    return str;
  }

  var bindToTemplate = function(obj) {
    $('#header-test-single').click(getClickHandler());
  }

  var getClickHandler = function() {
    return(function(event) {
      // write QUnit harness into page
      var qs = '

';
      $('body').prepend(qs);
      // pull in QUnit library (triggers scroll:x=0&y=0)
      $.getScript("/chrome/vendor/qunit/qunit-1.14.0.min.js").done(function() {
        // execute tests
        tests();
      });
      event.preventDefault();
    });
  }

  // -----
  // TESTS
  // -----

  /**
   * execute tests
   */
  var tests = function() {
    QUnit.init();
    var endTest = function() {
      window.location.hash = '#!';
    }

    test( 'rapid scroll event queuing', function() {
      window.location.hash = 'rapid-scroll';
      var direction = sfun.api_getDirection();
      QUnit.stop();
      sfun.api_triggerKeypress(sfun.KEY_HOME).done(function() {
        var initialSeq = $('ul.flow .selectablecell.selected').data('seq');
        // scroll to last element
        sfun.api_triggerKeypress(sfun.KEY_END).done(function() {
          var finalSeq = sfun.api_getTotalEntries()-1;
          var $selected = $('ul.flow .selectablecell.selected');
          equal( $selected.data('seq'), finalSeq, 'Selected last image (#'+finalSeq+')' );
          // store major axis position of final image then use to calculate scroll limit
          var position = $selected.offset();
          var limitPos = (direction == 'x' ? position.left - sfun.api_getViewportWidth() : position.top - sfun.api_getViewportHeight());
          // scroll to middle
          var middleSeq = Math.floor((finalSeq - initialSeq) / 2);
          // scroll to middle image
          sfun.api_imageAdvanceTo(middleSeq).done(function() {
            $selected = $('ul.flow .selectablecell.selected');
            equal($selected.data('seq'), middleSeq, 'Selected middle image (#'+middleSeq+')' );
            // use position of middle image as startPos
            var position = $selected.offset();
            var startPos = (direction == 'x' ? position.left : position.top);
            // check that we have 1000 pixels to scroll within
            if (limitPos - startPos < 1000) {
              ok(true, 'image set not large enough to conduct scroll test');
            } else {
              var target = { 'left': 0, 'top': 0 };
              // fire 100 x 10px scroll events in sequence
              for (var i=0 ; i<100 ; i++) {
                if (direction == 'x') {
                  target.left = startPos + (i * 10);
                } else {
                  target.top = startPos + (i * 10);
                }
                // fire, but not using api_triggerScroll, as browser drag doesn't do that!
                $(document).scrollLeft(target.left);
                $(document).scrollTop(target.top);
              }
// START HERE
            }
            QUnit.start();
            endTest();
          });
        });
      });
    });

    QUnit.start();
  }

  // call init function
  init();

})(jQuery, window.sfun, undefined);<commit_msg>working on rapid scroll test<commit_after>/**
 * StructuredFun javascript
 * QUnit test harness
 */
(function($, sfun, undefined) {

  // ---------
  // CONSTANTS
  // ---------

  // ---------
  // FUNCTIONS
  // ---------

  var init = function() {
    var obj = {
      'context': this,
      'callback': bindToTemplate,
      'view': {
        'title': 'Test'
      },
      'template': getTemplate()
    };
    // once script is loaded and executes, push header button async
    sfun.push('headerAddButton', obj);
  };

  var getTemplate = function() {
    var str = '
{{ title }}
';
    return str;
  }

  var bindToTemplate = function(obj) {
    $('#header-test-single').click(getClickHandler());
  }

  var getClickHandler = function() {
    return(function(event) {
      // write QUnit harness into page
      var qs = '

';
      $('body').prepend(qs);
      // pull in QUnit library (triggers scroll:x=0&y=0)
      $.getScript("/chrome/vendor/qunit/qunit-1.14.0.min.js").done(function() {
        // execute tests
        tests();
      });
      event.preventDefault();
    });
  }

  // -----
  // TESTS
  // -----

  /**
   * execute tests
   */
  var tests = function() {
    QUnit.init();
    var endTest = function() {
      window.location.hash = '#!';
    }

    test( 'rapid scroll event queuing', function() {
      window.location.hash = 'rapid-scroll';
      var direction = sfun.api_getDirection();
      QUnit.stop();
      sfun.api_triggerKeypress(sfun.KEY_HOME).done(function() {
        var initialSeq = $('ul.flow .selectablecell.selected').data('seq');
        // scroll to last element
        sfun.api_triggerKeypress(sfun.KEY_END).done(function() {
          var finalSeq = sfun.api_getTotalEntries()-1;
          var $selected = $('ul.flow .selectablecell.selected');
          equal( $selected.data('seq'), finalSeq, 'Selected last image (#'+finalSeq+')' );
          // store major axis position of final image then use to calculate scroll limit
          var position = $selected.offset();
          var limitPos = (direction == 'x' ? position.left - sfun.api_getViewportWidth() : position.top - sfun.api_getViewportHeight());
          // scroll to middle
          var middleSeq = Math.floor((finalSeq - initialSeq) / 2);
          // scroll to middle image
          sfun.api_imageAdvanceTo(middleSeq).done(function() {
            $selected = $('ul.flow .selectablecell.selected');
            equal($selected.data('seq'), middleSeq, 'Selected middle image (#'+middleSeq+')' );
            // use position of middle image as startPos
            var position = $selected.offset();
            var startPos = (direction == 'x' ? position.left : position.top);
            // check that we have 1000 pixels to scroll within
            if (limitPos - startPos < 1000) {
              ok(true, 'image set not large enough to conduct scroll test');
            } else {
              // work out where we should end up
              var iterCount = 100;
              var iterMux = 10;
              var target = {
                'left': (direction == 'x' ? startPos + iterCount*iterMux : 0),
                'top': (direction == 'x' ? 0 : startPos + iterCount*iterMux)
              };
              // bind to final scroll event
              var targetKey = 'scroll:x='+target.left+'&y='+target.top;
              sfun.api_bindToContext(targetKey).done(function() {
                ok(true, 'target scroll event ('+targetKey+') triggered and resolved');
                QUnit.start();
              });
              var iter = { 'left': 0, 'top': 0 };
              // fire 100 x 10px scroll events in sequence
              for (var i=0 ; i<=iterCount ; i++) {
                if (direction == 'x') {
                  iter.left = startPos + (i * iterMux);
                } else {
                  iter.top = startPos + (i * iterMux);
                }
// START HERE
// slow down firing by using callback
                // fire, but not using api_triggerScroll, as browser drag doesn't do that!
                $(document).scrollLeft(iter.left);
                $(document).scrollTop(iter.top);
              }
              // test scroll position
              var endPos = (direction == 'x' ? $(document).scrollLeft() : $(document).scrollTop());
              equal(endPos, startPos + iterCount*iterMux, 'finished in correct scroll position');
            }
            endTest();
          });
        });
      });
    });

    QUnit.start();
  }

  // call init function
  init();

})(jQuery, window.sfun, undefined);<|endoftext|>


<commit_before>var velocityShow = function (promise) {
  var n = this
  $.Velocity(n.barDom, {
    left: 450,
    scaleY: 2
  }, {
      duration: 0
    })
  $.Velocity(n.barDom, {
    left: 0,
    scaleY: 1
  }, {
      easing: [8, 8],
      complete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

var velocityClose = function (promise) {
  var n = this
  $.Velocity(n.barDom, {
    left: '+=-50'
  }, {
      easing: [8, 8, 2],
      duration: 350
    })
  $.Velocity(n.barDom, {
    left: 450,
    scaleY: .2,
    height: 0,
    margin: 0
  }, {
      easing: [8, 8],
      complete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

var mojsShow = function (promise) {
  var n = this
  var Timeline = new mojs.Timeline()
  var body = new mojs.Html({
    el: n.barDom,
    x: { 500: 0, delay: 0, duration: 500, easing: 'elastic.out' },
    isForce3d: true,
    onComplete: function () {
      promise(function (resolve) {
        resolve()
      })
    }
  })

  var parent = new mojs.Shape({
    parent: n.barDom,
    width: 200,
    height: n.barDom.getBoundingClientRect().height,
    radius: 0,
    x: { [150]: -150 },
    duration: 1.2 * 500,
    isShowStart: true
  })

  n.barDom.style['overflow'] = 'visible'
  parent.el.style['overflow'] = 'hidden'

  var burst = new mojs.Burst({
    parent: parent.el,
    count: 10,
    top: n.barDom.getBoundingClientRect().height + 75,
    degree: 90,
    radius: 75,
    angle: { [-90]: 40 },
    children: {
      fill: '#EBD761',
      delay: 'stagger(500, -50)',
      radius: 'rand(8, 25)',
      direction: -1,
      isSwirl: true
    }
  })

  var fadeBurst = new mojs.Burst({
    parent: parent.el,
    count: 2,
    degree: 0,
    angle: 75,
    radius: { 0: 100 },
    top: '90%',
    children: {
      fill: '#EBD761',
      pathScale: [.65, 1],
      radius: 'rand(12, 15)',
      direction: [-1, 1],
      delay: .8 * 500,
      isSwirl: true
    }
  })

  Timeline.add(body, burst, fadeBurst, parent)
  Timeline.play()
}

var mojsClose = function (promise) {
  var n = this
  new mojs.Html({
    el: n.barDom,
    x: { 0: 500, delay: 10, duration: 500, easing: 'cubic.out' },
    isForce3d: true,
    onComplete: function () {
      promise(function (resolve) {
        resolve()
      })
    }
  }).play()
}

var bouncejsShow = function (promise) {
  var n = this
  new Bounce()
    .translate({
      from: { x: 450, y: 0 }, to: { x: 0, y: 0 },
      easing: 'bounce',
      duration: 1000,
      bounces: 4,
      stiffness: 3
    })
    .scale({
      from: { x: 1.2, y: 1 }, to: { x: 1, y: 1 },
      easing: 'bounce',
      duration: 1000,
      delay: 100,
      bounces: 4,
      stiffness: 1
    })
    .scale({
      from: { x: 1, y: 1.2 }, to: { x: 1, y: 1 },
      easing: 'bounce',
      duration: 1000,
      delay: 100,
      bounces: 6,
      stiffness: 1
    })
    .applyTo(n.barDom, {
      onComplete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

var bouncejsClose = function (promise) {
  var n = this
  new Bounce()
    .translate({
      from: { x: 0, y: 0 }, to: { x: 450, y: 0 },
      easing: 'bounce',
      duration: 500,
      bounces: 4,
      stiffness: 1
    })
    .applyTo(n.barDom, {
      onComplete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

$('body').on('click', '#example-runner', function (e) {
  new Noty({
    text: '
I\'m an example notification. Hi!
',
    type: 'warning',
    theme: 'mint',
    layout: 'topRight',
    timeout: 4000,
    animation: {
      open: mojsShow,
      close: mojsClose
    }
  }).show()
})

$('body').on('click', '#example-animatecss', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a jquery notification library!',
    animation: {
      open: 'animated bounceInRight', // Animate.css class names
      close: 'animated bounceOutRight' // Animate.css class names
    }
  }).show();
})

$('body').on('click', '#example-bouncejs', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a jquery notification library!',
    animation: {
      open: bouncejsShow,
      close: bouncejsClose
    }
  }).show();
})

$('body').on('click', '#example-mojs', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a jquery notification library!',
    animation: {
      open: mojsShow,
      close: mojsClose
    }
  }).show();
})

$('body').on('click', '#example-velocity', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a jquery notification library!',
    animation: {
      open: velocityShow,
      close: velocityClose
    }
  }).show();
})

setTimeout(function () {
  new Noty({
    text: '
Wubba lubba dub dub! v3.1.3 released!
',
    type: 'information',
    theme: 'mint',
    layout: 'topRight',
    timeout: 4000,
    animation: {
      open: mojsShow,
      close: mojsClose
    }
  }).show()
}, 2000)

function RenderPreviews () {
  console.log("run")

  Noty.setMaxVisible(999999999);

  $themePreview = $(".theme-previews")
  $themePreviews = ["mint", "sunset", "relax", "nest", "metroui", "semanticui", "light", "bootstrap-v3", "bootstrap-v4"]
  if ($themePreview.length != 0) {

    $.each($themePreviews, function (i, theme) {

      $(".theme-preview-" + theme).append($("
" + theme + "
"))

      console.log(theme)

      generatePreview(theme, 'alert')
      generatePreview(theme, 'success')
      generatePreview(theme, 'warning')
      generatePreview(theme, 'error')
      generatePreview(theme, 'information')
      generatePreview(theme, 'confirm')

    });

    function generatePreview (theme, type) {
      var notes = [];
      notes['alert'] = 'Best check yo self, you\'re not looking too good.';
      notes['error'] = 'Change a few things up and try submitting again.';
      notes['success'] = 'You successfully read this important alert message.';
      notes['information'] = 'This alert needs your attention, but it\'s not super important.';
      notes['warning'] = 'Warning!
 Best check yo self, you\'re not looking too good.';
      notes['confirm'] = 'Do you want to continue?';
      new Noty({
        text: notes[type],
        container: ".theme-preview-" + theme,
        type: type,
        theme: theme,
        dismissQueue: true,
        force: false,
        closeWith: [],
        buttons: (type != 'confirm') ? false : [
          Noty.button('YES', 'btn btn-success', function () {
            console.log('button 1 clicked');
          }),

          Noty.button('NO', 'btn btn-error', function () {
            console.log('button 2 clicked');
          })
        ]
      }).show()
    }

  } else {
    console.log("shit")
  }
}

<commit_msg>Remove references to jQuery<commit_after>var velocityShow = function (promise) {
  var n = this
  $.Velocity(n.barDom, {
    left: 450,
    scaleY: 2
  }, {
      duration: 0
    })
  $.Velocity(n.barDom, {
    left: 0,
    scaleY: 1
  }, {
      easing: [8, 8],
      complete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

var velocityClose = function (promise) {
  var n = this
  $.Velocity(n.barDom, {
    left: '+=-50'
  }, {
      easing: [8, 8, 2],
      duration: 350
    })
  $.Velocity(n.barDom, {
    left: 450,
    scaleY: .2,
    height: 0,
    margin: 0
  }, {
      easing: [8, 8],
      complete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

var mojsShow = function (promise) {
  var n = this
  var Timeline = new mojs.Timeline()
  var body = new mojs.Html({
    el: n.barDom,
    x: { 500: 0, delay: 0, duration: 500, easing: 'elastic.out' },
    isForce3d: true,
    onComplete: function () {
      promise(function (resolve) {
        resolve()
      })
    }
  })

  var parent = new mojs.Shape({
    parent: n.barDom,
    width: 200,
    height: n.barDom.getBoundingClientRect().height,
    radius: 0,
    x: { [150]: -150 },
    duration: 1.2 * 500,
    isShowStart: true
  })

  n.barDom.style['overflow'] = 'visible'
  parent.el.style['overflow'] = 'hidden'

  var burst = new mojs.Burst({
    parent: parent.el,
    count: 10,
    top: n.barDom.getBoundingClientRect().height + 75,
    degree: 90,
    radius: 75,
    angle: { [-90]: 40 },
    children: {
      fill: '#EBD761',
      delay: 'stagger(500, -50)',
      radius: 'rand(8, 25)',
      direction: -1,
      isSwirl: true
    }
  })

  var fadeBurst = new mojs.Burst({
    parent: parent.el,
    count: 2,
    degree: 0,
    angle: 75,
    radius: { 0: 100 },
    top: '90%',
    children: {
      fill: '#EBD761',
      pathScale: [.65, 1],
      radius: 'rand(12, 15)',
      direction: [-1, 1],
      delay: .8 * 500,
      isSwirl: true
    }
  })

  Timeline.add(body, burst, fadeBurst, parent)
  Timeline.play()
}

var mojsClose = function (promise) {
  var n = this
  new mojs.Html({
    el: n.barDom,
    x: { 0: 500, delay: 10, duration: 500, easing: 'cubic.out' },
    isForce3d: true,
    onComplete: function () {
      promise(function (resolve) {
        resolve()
      })
    }
  }).play()
}

var bouncejsShow = function (promise) {
  var n = this
  new Bounce()
    .translate({
      from: { x: 450, y: 0 }, to: { x: 0, y: 0 },
      easing: 'bounce',
      duration: 1000,
      bounces: 4,
      stiffness: 3
    })
    .scale({
      from: { x: 1.2, y: 1 }, to: { x: 1, y: 1 },
      easing: 'bounce',
      duration: 1000,
      delay: 100,
      bounces: 4,
      stiffness: 1
    })
    .scale({
      from: { x: 1, y: 1.2 }, to: { x: 1, y: 1 },
      easing: 'bounce',
      duration: 1000,
      delay: 100,
      bounces: 6,
      stiffness: 1
    })
    .applyTo(n.barDom, {
      onComplete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

var bouncejsClose = function (promise) {
  var n = this
  new Bounce()
    .translate({
      from: { x: 0, y: 0 }, to: { x: 450, y: 0 },
      easing: 'bounce',
      duration: 500,
      bounces: 4,
      stiffness: 1
    })
    .applyTo(n.barDom, {
      onComplete: function () {
        promise(function (resolve) {
          resolve()
        })
      }
    })
}

$('body').on('click', '#example-runner', function (e) {
  new Noty({
    text: '
I\'m an example notification. Hi!
',
    type: 'warning',
    theme: 'mint',
    layout: 'topRight',
    timeout: 4000,
    animation: {
      open: mojsShow,
      close: mojsClose
    }
  }).show()
})

$('body').on('click', '#example-animatecss', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a Dependency-free notification library!',
    animation: {
      open: 'animated bounceInRight', // Animate.css class names
      close: 'animated bounceOutRight' // Animate.css class names
    }
  }).show();
})

$('body').on('click', '#example-bouncejs', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a Dependency-free notification library!',
    animation: {
      open: bouncejsShow,
      close: bouncejsClose
    }
  }).show();
})

$('body').on('click', '#example-mojs', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a Dependency-free notification library!',
    animation: {
      open: mojsShow,
      close: mojsClose
    }
  }).show();
})

$('body').on('click', '#example-velocity', function (e) {
  new Noty({
    type: 'warning',
    text: 'NOTY - a Dependency-free notification library!',
    animation: {
      open: velocityShow,
      close: velocityClose
    }
  }).show();
})

setTimeout(function () {
  new Noty({
    text: '
Wubba lubba dub dub! v3.1.3 released!
',
    type: 'information',
    theme: 'mint',
    layout: 'topRight',
    timeout: 4000,
    animation: {
      open: mojsShow,
      close: mojsClose
    }
  }).show()
}, 2000)

function RenderPreviews () {
  console.log("run")

  Noty.setMaxVisible(999999999);

  $themePreview = $(".theme-previews")
  $themePreviews = ["mint", "sunset", "relax", "nest", "metroui", "semanticui", "light", "bootstrap-v3", "bootstrap-v4"]
  if ($themePreview.length != 0) {

    $.each($themePreviews, function (i, theme) {

      $(".theme-preview-" + theme).append($("
" + theme + "
"))

      console.log(theme)

      generatePreview(theme, 'alert')
      generatePreview(theme, 'success')
      generatePreview(theme, 'warning')
      generatePreview(theme, 'error')
      generatePreview(theme, 'information')
      generatePreview(theme, 'confirm')

    });

    function generatePreview (theme, type) {
      var notes = [];
      notes['alert'] = 'Best check yo self, you\'re not looking too good.';
      notes['error'] = 'Change a few things up and try submitting again.';
      notes['success'] = 'You successfully read this important alert message.';
      notes['information'] = 'This alert needs your attention, but it\'s not super important.';
      notes['warning'] = 'Warning!
 Best check yo self, you\'re not looking too good.';
      notes['confirm'] = 'Do you want to continue?';
      new Noty({
        text: notes[type],
        container: ".theme-preview-" + theme,
        type: type,
        theme: theme,
        dismissQueue: true,
        force: false,
        closeWith: [],
        buttons: (type != 'confirm') ? false : [
          Noty.button('YES', 'btn btn-success', function () {
            console.log('button 1 clicked');
          }),

          Noty.button('NO', 'btn btn-error', function () {
            console.log('button 2 clicked');
          })
        ]
      }).show()
    }

  } else {
    console.log("shit")
  }
}

<|endoftext|>


<commit_before>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 * ======================================================================== */

(function($) {})(jQuery); // Fully reference jQuery after this point.

$(document).foundation();

if ( $('body').hasClass('page-template-tmpl-landing') ) {
  Pace.on('done', function() {
    $('.thecover').addClass('opening');
    $('.top-bar').removeClass('darkened');
    window.location.href = $('.homelogo').data('realhome');
  });
} else {
  Pace.on('done', function() {
    $('.top-bar').removeClass('darkened');
  });
};

$.each($('.card, .membersquare, .projectsquare, .clientlogo'), function(i, el){
  $(el).addClass('fadeInUp wow').attr('data-wow-delay', i%5*125 + 'ms');
});

function resizeProjectCarousel() {
  if (window.innerWidth>=768 && $('.projectheadrow').innerHeight()<420 ) {
    $('.projectcarousel img').css('max-height', function() {
      return (window.innerHeight>720)?(window.innerHeight - $('.projectheadrow').outerHeight()  - 90 ):400 ;
    });
    $('.projectcarousel .owl-stage-outer').css('max-height', function() {
      return (window.innerHeight>720)?(window.innerHeight - $('.projectheadrow').outerHeight()  - 90 ):400 ;
    });
  } else {
    $('.projectcarousel img').css('max-height', function() {
      return 'none';
    });
    $('.projectcarousel .owl-stage-outer').css('max-height', function() {
      return 'none' ;
    });
  }
}

$('document').ready(function() {

  //tweaking main navigation #-ed elemets on non home pages
  if ( !$('body').hasClass('page-template-tmpl-home') ) {
    $('.menu-the-work a' ).addClass('active');
    $('.menu-item').each(function() {
      if ( $(this).find('a').attr('href').substring(0, 1) === '#') {
       $(this).find('a').attr('href', $('.homelogo').data('realhome') + $(this).find('a').attr('href') );
      }
    });
    //$('.primarynav').foundation('reflow');
  }

  $('input[type=text], input[type=email]').on('change', function(){
      if ( $(this).val() !== '' ) {
        $(this).addClass('filled');
      } else {
        $(this).removeClass('filled');
      }
  });

  $('a').click(function(e) {
    if ( ($(this).attr('href').substr(0,1)!=='#') && ($(this).attr('href').substr(0,6)!=='mailto') && (!$(this).hasClass('popimg'))
        ) {
      e.preventDefault();
      // $('.thecover').removeClass('rejtve');
      // $('.thecover').removeClass('opening');
      $('.top-bar').addClass('darkened');
      $('.document').addClass('docfade');
      window.location.href = $(this).attr('href');
    }
  });

  $('.document').removeClass('docfade');

  resizeProjectCarousel();

  //Home intra accordion control

  $('.homeintromore, .whatwedoclose').on('click', function(e) {
    e.preventDefault();
    $('#intro').foundation('toggle', $('#introblock'));
    $('#intro').foundation('toggle', $('#whatwedo'));
    //$('.keyboard').toggleClass('is-hidden');
  });

  //popimg Gallery popup
  $('.whatwedogrid').magnificPopup({
    delegate: 'a.popimg',
    type: 'image',
    tLoading: 'Loading image #%curr%...',
    mainClass: 'mfp-img-mobile nottootall mfp-with-zoom',
    closeBtnInside: false,
    gallery: {
      enabled: true,
      navigateByImgClick: true,
      preload: [0,1] // Will preload 0 - before current, and 1 after the current image
    },
    image: {
      tError: 'The image #%curr% could not be loaded.',
      titleSrc: function(item) {
        return item.el.attr('title');
      }
    }
  });

  //project Gallery popup
  $('.projectcarousel').magnificPopup({
    delegate: 'a.popimg',
    type: 'image',
    tLoading: 'Loading image #%curr%...',
    mainClass: 'mfp-img-mobile nottootall mfp-with-zoom',
    closeBtnInside: false,
    gallery: {
      enabled: true,
      navigateByImgClick: true,
      preload: [0,1] // Will preload 0 - before current, and 1 after the current image
    },
    image: {
      tError: 'The image #%curr% could not be loaded.',
      titleSrc: function(item) {
        return item.el.attr('title');
      }
    }
  });

});

$( window ).on('resize', function() {
  resizeProjectCarousel();
});

$('.menu-item a').on('click', function(){
  if (window.innerWidth<768) {
    $('.menu-icon').click();
  }
});

$('.top-bar-right').on('update.zf.magellan', function() {
  var section = $( $('.primarynav a.active').attr('href') );
  var prevsection = section.prev('main > section').attr('id');
  var nextsection = section.next('main > section').attr('id');
  prevsection = !prevsection?'work':prevsection;
  setTimeout(function() {
    $('.realkeyboard .btn.up').attr('href','#' + prevsection);
    $('.realkeyboard .btn.down').attr('href','#' + nextsection);
    $('.keyboard').removeClass('active');
    if (section.attr('id')==='approach') {
      $('.keyboard').addClass('active');
    }
  },500);
});

$(document.documentElement).keydown(function(event) {
    switch (event.keyCode) {
      case 38:
        $('.realkeyboard .btn.up').addClass('pressed');
      break;
      case 40:
        $('.realkeyboard .btn.down').addClass('pressed');
      break;
      case 37:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.left').addClass('pressed');
        }
        if ($('.single-project .primarynav .menu-the-work a').hasClass('active')) {
          $('.realkeyboard .btn.left').addClass('pressed');
        }
        $('.keyboard .button.left').addClass('pressed');
      break;
      case 39:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.right').addClass('pressed');
        }
        if ($('.single-project .primarynav .menu-the-work a').hasClass('active')) {
          $('.realkeyboard .btn.right').addClass('pressed');
        }
        $('.keyboard .button.right').addClass('pressed');
      break;

    }
});

$(document.documentElement).keyup(function(event) {
    $('.realkeyboard .btn').removeClass('pressed');
    $('.keyboard .button').removeClass('pressed');
    switch (event.keyCode) {
      case 38:
      if ( $('body').hasClass('page-template-tmpl-home') ) {
        $('.primarynav').foundation('scrollToLoc', $('.realkeyboard .btn.up').attr('href'));
      }
      break;
      case 40:
      if ( $('body').hasClass('page-template-tmpl-home') ) {
        $('.primarynav').foundation('scrollToLoc', $('.realkeyboard .btn.down').attr('href'));
      }
      break;
      case 37:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.left').click();
        }
        if ($('body').hasClass('single-project')) {
          $('.realkeyboard .btn.left').click();
        }
      break;
      case 39:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.right').click();
        }
        if ($('body').hasClass('single-project')) {
          $('.realkeyboard .btn.right').click();
        }
      break;

    }
});

var wow = new WOW();
wow.init();

$(function() {
  var wow = new WOW({
    boxClass: 'wow',
    offset: 120,
  }).init();
});

var whatwedocarousel = $('.whatwedocarousel').owlCarousel({
    //margin:32,
    smartSpeed:500,
    //autoWidth:true,
    // mouseDrag:false,
    // touchDrag:false,
    // pullDrag:false,
    autoHeight:true,
    loop:true,
    items:1,
    nav:true,
    navText: ['', ''],
    responsiveClass:true,
    responsive:{
        0:{
            items:1,
            margin:0
        },
        540:{
            items:2,
            margin:24
        },
        1024:{
            items:3,
            margin:32
        }
    }
});

var approachcarousel = $('.approachcarousel').owlCarousel({
    //margin:32,
    smartSpeed:500,
    //autoWidth:true,
    // mouseDrag:false,
    // touchDrag:false,
    // pullDrag:false,
    autoHeight:true,
    loop:true,
    items:1,
    nav:false,
    navText: ['', ''],
    responsiveClass:true,
    responsive:{
        0:{
            items:1,
            margin:24
        },
        768:{
            items:1,
            margin:24
        },
        1024:{
            items:1,
            margin:32
        }
    }

});

var aboutcarousel = $('.aboutcarousel').owlCarousel({
    smartSpeed:500,
    margin:30,
    autoHeight:true,
    loop:true,
    mouseDrag:false,
    touchDrag:false,
    pullDrag:false,
    items:1,
    nav:false,
    navText: ['', ''],
    itemElement: 'section'
});

var projectcarousel = $('.projectcarousel').owlCarousel({
    //margin:32,
    smartSpeed:500,
    loop:true,
    autoWidth:true,
    autoHeight:true,
    items:1,
    nav:false,
    navText: ['', ''],
    responsiveClass:true,
    responsive:{
        0:{
            items:1,
            margin:0
        },
        768:{
            items:2,
            margin:24
        },
        1200:{
            items:3,
            margin:32
        }
    }
});

$('.btn.up, .btn.down').on('click', function(e){
  e.preventDefault();
  $('.primarynav').foundation('scrollToLoc', $(this).attr('href'));
});

$('.button.left').on('click', function(e){
  e.preventDefault();
  $('.btn.left').click();
});

$('.button.right').on('click', function(e){
  e.preventDefault();
  $('.btn.right').click();
});

$('.btn.left').on('click', function(e){
  e.preventDefault();
  var owltarget = $(this).attr('data-owltarget');
  switch (owltarget) {
    case 'approach':
     approachcarousel.trigger('prev.owl.carousel');
    break;
    case 'project':
      projectcarousel.trigger('prev.owl.carousel');
    break;
  }
});

$('.btn.right').click(function(e){
  e.preventDefault();
  var owltarget = $(this).attr('data-owltarget');
  switch (owltarget) {
    case 'approach':
      approachcarousel.trigger('next.owl.carousel');
    break;
    case 'project':
      projectcarousel.trigger('next.owl.carousel');
    break;
  }
});

<commit_msg>jolesz<commit_after>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 * ======================================================================== */

(function($) {})(jQuery); // Fully reference jQuery after this point.

$(document).foundation();

if ( $('body').hasClass('page-template-tmpl-landing') ) {
  Pace.on('done', function() {
    $('.thecover').addClass('opening');
    $('.top-bar').removeClass('darkened');
    window.location.href = $('.homelogo').data('realhome');
  });
} else {
  Pace.on('done', function() {
    $('.top-bar').removeClass('darkened');
  });
}

$.each($('.card, .membersquare, .projectsquare, .clientlogo'), function(i, el){
  $(el).addClass('fadeInUp wow').attr('data-wow-delay', i%5*125 + 'ms');
});

function resizeProjectCarousel() {
  if (window.innerWidth>=768 && $('.projectheadrow').innerHeight()<420 ) {
    $('.projectcarousel img').css('max-height', function() {
      return (window.innerHeight>720)?(window.innerHeight - $('.projectheadrow').outerHeight()  - 90 ):400 ;
    });
    $('.projectcarousel .owl-stage-outer').css('max-height', function() {
      return (window.innerHeight>720)?(window.innerHeight - $('.projectheadrow').outerHeight()  - 90 ):400 ;
    });
  } else {
    $('.projectcarousel img').css('max-height', function() {
      return 'none';
    });
    $('.projectcarousel .owl-stage-outer').css('max-height', function() {
      return 'none' ;
    });
  }
}

$('document').ready(function() {

  //tweaking main navigation #-ed elemets on non home pages
  if ( !$('body').hasClass('page-template-tmpl-home') ) {
    $('.menu-the-work a' ).addClass('active');
    $('.menu-item').each(function() {
      if ( $(this).find('a').attr('href').substring(0, 1) === '#') {
       $(this).find('a').attr('href', $('.homelogo').data('realhome') + $(this).find('a').attr('href') );
      }
    });
    //$('.primarynav').foundation('reflow');
  }

  $('input[type=text], input[type=email]').on('change', function(){
      if ( $(this).val() !== '' ) {
        $(this).addClass('filled');
      } else {
        $(this).removeClass('filled');
      }
  });

  $('a').click(function(e) {
    if ( ($(this).attr('href').substr(0,1)!=='#') && ($(this).attr('href').substr(0,6)!=='mailto') && (!$(this).hasClass('popimg'))
        ) {
      e.preventDefault();
      // $('.thecover').removeClass('rejtve');
      // $('.thecover').removeClass('opening');
      $('.top-bar').addClass('darkened');
      $('.document').addClass('docfade');
      window.location.href = $(this).attr('href');
    }
  });

  $('.document').removeClass('docfade');

  resizeProjectCarousel();

  //Home intra accordion control

  $('.homeintromore, .whatwedoclose').on('click', function(e) {
    e.preventDefault();
    $('#intro').foundation('toggle', $('#introblock'));
    $('#intro').foundation('toggle', $('#whatwedo'));
    //$('.keyboard').toggleClass('is-hidden');
  });

  //popimg Gallery popup
  $('.whatwedogrid').magnificPopup({
    delegate: 'a.popimg',
    type: 'image',
    tLoading: 'Loading image #%curr%...',
    mainClass: 'mfp-img-mobile nottootall mfp-with-zoom',
    closeBtnInside: false,
    gallery: {
      enabled: true,
      navigateByImgClick: true,
      preload: [0,1] // Will preload 0 - before current, and 1 after the current image
    },
    image: {
      tError: 'The image #%curr% could not be loaded.',
      titleSrc: function(item) {
        return item.el.attr('title');
      }
    }
  });

  //project Gallery popup
  $('.projectcarousel').magnificPopup({
    delegate: 'a.popimg',
    type: 'image',
    tLoading: 'Loading image #%curr%...',
    mainClass: 'mfp-img-mobile nottootall mfp-with-zoom',
    closeBtnInside: false,
    gallery: {
      enabled: true,
      navigateByImgClick: true,
      preload: [0,1] // Will preload 0 - before current, and 1 after the current image
    },
    image: {
      tError: 'The image #%curr% could not be loaded.',
      titleSrc: function(item) {
        return item.el.attr('title');
      }
    }
  });

});

$( window ).on('resize', function() {
  resizeProjectCarousel();
});

$('.menu-item a').on('click', function(){
  if (window.innerWidth<768) {
    $('.menu-icon').click();
  }
});

$('.top-bar-right').on('update.zf.magellan', function() {
  var section = $( $('.primarynav a.active').attr('href') );
  var prevsection = section.prev('main > section').attr('id');
  var nextsection = section.next('main > section').attr('id');
  prevsection = !prevsection?'work':prevsection;
  setTimeout(function() {
    $('.realkeyboard .btn.up').attr('href','#' + prevsection);
    $('.realkeyboard .btn.down').attr('href','#' + nextsection);
    $('.keyboard').removeClass('active');
    if (section.attr('id')==='approach') {
      $('.keyboard').addClass('active');
    }
  },500);
});

$(document.documentElement).keydown(function(event) {
    switch (event.keyCode) {
      case 38:
        $('.realkeyboard .btn.up').addClass('pressed');
      break;
      case 40:
        $('.realkeyboard .btn.down').addClass('pressed');
      break;
      case 37:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.left').addClass('pressed');
        }
        if ($('.single-project .primarynav .menu-the-work a').hasClass('active')) {
          $('.realkeyboard .btn.left').addClass('pressed');
        }
        $('.keyboard .button.left').addClass('pressed');
      break;
      case 39:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.right').addClass('pressed');
        }
        if ($('.single-project .primarynav .menu-the-work a').hasClass('active')) {
          $('.realkeyboard .btn.right').addClass('pressed');
        }
        $('.keyboard .button.right').addClass('pressed');
      break;

    }
});

$(document.documentElement).keyup(function(event) {
    $('.realkeyboard .btn').removeClass('pressed');
    $('.keyboard .button').removeClass('pressed');
    switch (event.keyCode) {
      case 38:
      if ( $('body').hasClass('page-template-tmpl-home') ) {
        $('.primarynav').foundation('scrollToLoc', $('.realkeyboard .btn.up').attr('href'));
      }
      break;
      case 40:
      if ( $('body').hasClass('page-template-tmpl-home') ) {
        $('.primarynav').foundation('scrollToLoc', $('.realkeyboard .btn.down').attr('href'));
      }
      break;
      case 37:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.left').click();
        }
        if ($('body').hasClass('single-project')) {
          $('.realkeyboard .btn.left').click();
        }
      break;
      case 39:
        if ($('.primarynav .menu-approach a').hasClass('active')) {
          $('.realkeyboard .btn.right').click();
        }
        if ($('body').hasClass('single-project')) {
          $('.realkeyboard .btn.right').click();
        }
      break;

    }
});

var wow = new WOW();
wow.init();

$(function() {
  var wow = new WOW({
    boxClass: 'wow',
    offset: 120,
  }).init();
});

var whatwedocarousel = $('.whatwedocarousel').owlCarousel({
    //margin:32,
    smartSpeed:500,
    //autoWidth:true,
    // mouseDrag:false,
    // touchDrag:false,
    // pullDrag:false,
    autoHeight:true,
    loop:true,
    items:1,
    nav:true,
    navText: ['', ''],
    responsiveClass:true,
    responsive:{
        0:{
            items:1,
            margin:0
        },
        540:{
            items:2,
            margin:24
        },
        1024:{
            items:3,
            margin:32
        }
    }
});

var approachcarousel = $('.approachcarousel').owlCarousel({
    //margin:32,
    smartSpeed:500,
    //autoWidth:true,
    // mouseDrag:false,
    // touchDrag:false,
    // pullDrag:false,
    autoHeight:true,
    loop:true,
    items:1,
    nav:false,
    navText: ['', ''],
    responsiveClass:true,
    responsive:{
        0:{
            items:1,
            margin:24
        },
        768:{
            items:1,
            margin:24
        },
        1024:{
            items:1,
            margin:32
        }
    }

});

var aboutcarousel = $('.aboutcarousel').owlCarousel({
    smartSpeed:500,
    margin:30,
    autoHeight:true,
    loop:true,
    mouseDrag:false,
    touchDrag:false,
    pullDrag:false,
    items:1,
    nav:false,
    navText: ['', ''],
    itemElement: 'section'
});

var projectcarousel = $('.projectcarousel').owlCarousel({
    //margin:32,
    smartSpeed:500,
    loop:true,
    autoWidth:true,
    autoHeight:true,
    items:1,
    nav:false,
    navText: ['', ''],
    responsiveClass:true,
    responsive:{
        0:{
            items:1,
            margin:0
        },
        768:{
            items:2,
            margin:24
        },
        1200:{
            items:3,
            margin:32
        }
    }
});

$('.btn.up, .btn.down').on('click', function(e){
  e.preventDefault();
  $('.primarynav').foundation('scrollToLoc', $(this).attr('href'));
});

$('.button.left').on('click', function(e){
  e.preventDefault();
  $('.btn.left').click();
});

$('.button.right').on('click', function(e){
  e.preventDefault();
  $('.btn.right').click();
});

$('.btn.left').on('click', function(e){
  e.preventDefault();
  var owltarget = $(this).attr('data-owltarget');
  switch (owltarget) {
    case 'approach':
     approachcarousel.trigger('prev.owl.carousel');
    break;
    case 'project':
      projectcarousel.trigger('prev.owl.carousel');
    break;
  }
});

$('.btn.right').click(function(e){
  e.preventDefault();
  var owltarget = $(this).attr('data-owltarget');
  switch (owltarget) {
    case 'approach':
      approachcarousel.trigger('next.owl.carousel');
    break;
    case 'project':
      projectcarousel.trigger('next.owl.carousel');
    break;
  }
});

<|endoftext|>


<commit_before>if (simpleStorage.get('token')) {
  $('#account-btn').show();
} else {
  $('#load-login-btn').show();
}

function showLoginForm() {
  $('#register-box').fadeOut('fast',function() {
      $('#login-box').fadeIn('fast');
      $('#modal-register-footer').fadeOut('fast',function() {
        $('#model-label-header').text('Login');
        $('#modal-login-footer').fadeIn('fast');
      });
  });
};

function showRegisterForm() {
  $('#login-box').fadeOut('fast',function() {
      $('#register-box').fadeIn('fast');
      $('#modal-login-footer').fadeOut('fast',function() {
        $('#model-label-header').text('Register');
        $('#modal-register-footer').fadeIn('fast');
      });
  });
};

var renderIndexPage = function() {
  var templatingFunction = Handlebars.compile($('#index-page-template').html());
  $.ajax({
    url: "http://localhost:3000/books",
    method: 'GET'
  }).done(function(books, textStatus, jqxhr){
    console.log(books);
    var html = templatingFunction(books);
    $("#page").html(html);
  }).fail(function(jqxhr, textStatus, errorThrown){
    console.log(books);
    console.log(textStatus);
    console.log(jqxhr.responseText);
  });
};

// ---------------------- Books --------------------------
var setCreateResultMessage = function(success) {
  if (success) {
    $('#create-book-result-message').addClass('bg-success message');
    $('#create-book-result-message').text('Your book was created successfully!');
    $("#create-book-result-message").css();
  } else {
    $("#create-book-result-message").addClass('bg-danger message');
    $("#create-book-result-message").text('Something went wrong!');
  }
}

var booksPageTemplate = Handlebars.compile($("#books-page-template").html());

var renderCreateBookPage = function(book) {
  var templatingFunction = Handlebars.compile($('#create-book-template').html());
  var html = templatingFunction(book);
  $("#page").html(html);
};

var renderDisplayBookPage = function(book) {
  var templatingFunction = Handlebars.compile($('#display-book-template').html());
  var html = templatingFunction(book);
  $("#page").html(html);
};

// ---------------------- Loans --------------------------

var renderCreateLoanPage = function(users, books) {
  var templatingFunction = Handlebars.compile($('#create-loan-template').html());
  var html = templatingFunction(users, books);
  $("#page").html(html);
};

$(document).ready(function() {
  Authenticator.init();

  renderIndexPage("Books List");

  $("#page").on("click", "#thumbnail-preview-btn", function() {
    var clicked_id = $(this).data('id');
    console.log("Clicked button number " + clicked_id);
    $.ajax({
      url: "http://localhost:3000/books/" + clicked_id,
      method: 'GET'
    }).done(function(book, textStatus, jqxhr){
      console.log(book);
      $("#page").html(renderDisplayBookPage(book));

    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(jqxhr.responseText);
    });
  });

  $("#page").on("click", "#thumbnail-update-btn", function() {
    var clicked_id = $(this).data('id');
    console.log("Clicked button number " + clicked_id);
    $.ajax({
      url: "http://localhost:3000/books/" + clicked_id,
      method: 'GET'
    }).done(function(book, textStatus, jqxhr){
      console.log(book);
      $("#page").html(renderDisplayBookPage(book));

    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(jqxhr.responseText);
    });
  });

  $("#create-a-book-dd-btn").on("click", function(){
    console.log("#create-a-book-dd-btn clicked");
    renderCreateBookPage();
  });

  //create book with Ajax
  $("#page").on("click", "#book-create", function() {
    var reader = new FileReader();

    reader.onload = function(event){
      $.ajax({
        url: 'http://localhost:3000/books',
        method: 'POST',
        headers: { Authorization: 'Token token=' + simpleStorage.get('token') },
        data: {
          book: {
            title: $("#book-title").val(),
            author: $("#book-author").val(),
            year: $("#book-year").val(),
            price: $("#book-price").val(),
            image: event.target.result,
            url: $("#book-url").val()
          }
        }
      }).done(function(book, textStatus, jqxhr){
        console.log("Book created successfully");
        $("#book-title").text(book.title);
        $("#book-title").attr('readonly', 'readonly');
        $("#book-author").text(book.author);
        $("#book-author").attr('readonly', 'readonly');
        $("#book-year").text(book.year);
        $("#book-year").attr('readonly', 'readonly');
        $("#book-price").text(book.price);
        $("#book-price").attr('readonly', 'readonly');
        $("#book-url").text(book.url);
        $("#book-url").attr('readonly', 'readonly');
        setCreateResultMessage(true);
      }).fail(function(jqxhr, textStatus, errorThrown){
        console.log(textStatus);
        console.log(jqxhr.responseText);
        setCreateResultMessage(false);
      });
    };

    reader.readAsDataURL($('#book-image-upload')[0].files[0]);

  });

  //show user books
  $("#my-books").on("click", function() {
    console.log("my books clicked");

    $.ajax({
      url: "http://localhost:3000/books?limit=me",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      $("#page").html(booksPageTemplate({heading: "My Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("There was an error while LISTING CURRENT USER'S books, error: " + jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // show my loaned books
  $("#my-loaned-books").on("click", function() {
    console.log("my loaned books clicked");

    $.ajax({
      url: "http://localhost:3000/books/loaned",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      console.log(data);
      $("#page").html(booksPageTemplate({heading: "My Loaned Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("There was an error while LISTING CURRENT USER'S books, error: " + jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // show my borrowed books
  $("#my-borrowed-books").on("click", function() {
    console.log("my borrowed books clicked");

    $.ajax({
      url: "http://localhost:3000/books/borrowed",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      console.log(data);
      $("#page").html(booksPageTemplate({heading: "My Borrowed Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // show all boks
  $("#books-show").on("click", function() {
    $("#book-label").html();

    $.ajax({
      url: "http://localhost:3000/books",
      method: 'GET' //,
      // headers: { Authorization: 'Token token=' + $('#token').val()}
    }).done(function(data, textStatus, jqxhr){
      $("#page").html(booksPageTemplate({heading: "All Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("There was an error while LISTING ALL the books, error: " + jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // update Book with Ajax
  $("#book-update").on("click", function() {
    $.ajax({
      url: 'http://localhost:3000/books/' + $("#book-id").val(),
      method: 'PATCH',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') },
      data: {
        book: {
          title: $("#book-title").val(),
          author: $("#book-author").val(),
          year: $("#book-year").val(),
          price: $("#book-price").val(),
          url: $("#book-url").val(),
          status: $("#book-status").val()
        }
      }
    }).done(function(book, textStatus, jqxhr) {
      $("#book-label").html(bookTemplate(book));
    }).fail(function(jqxhr, textStatus, errorThrown) {
      console.log("textStatus: " + textStatus);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  //destroy Book with Ajax
  $("#book-destroy").on('click', function() {
   $.ajax({
     url: 'http://localhost:3000/books/' + $("#book-id").val(),
     method: 'DELETE'
   }).done(function(book, textStatus, jqxhr){
     console.log("Your book has been deleted, here is some data about it: " + data);
   }).fail(function(jqxhr, textStatus, errorThrown) {
    $("#book-label").html(jqxhr.responseText);
   });
  });

  // ------------------ Loan ---------------

  // show create loan page
  $("#create-a-loan-dd-btn").on("click", function() {
    console.log("#create-a-loan-dd-btn clicked");

    var users = {};
    var books = {};
    $('#page').load('partials/create-loan-form.html');
    $.ajax({
      url: "http://localhost:3000/users",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      var templatingFunction = Handlebars.compile($('#create-user-select-template').html());
      var html = templatingFunction({users: data.users});
      $('#loan-borrower-combo').html(html);
      users = data;
      console.log(users);
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("Error in getting users");
      console.log(jqxhr.responseText);
    });

    $.ajax({
      url: "http://localhost:3000/books?limit=me",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      var templatingFunction = Handlebars.compile($('#create-book-select-template').html());
      var html = templatingFunction({books: data.books});
      $('#loan-book-combo').html(html);
      books = data;
      console.log(books);
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("Error in getting books");
      console.log(jqxhr.responseText);
    });
    $("#loan-date").datepicker({format: 'YYYY-MM-DD'});

  });

  //create Loan with Ajax
  $("#page").on('click', "#loan-create", function() {
    console.log("Loan create clicked");
    var borrowe_id = $('loan-borrower-combo').selected_value;
    var book_id =
    $.ajax({
      url: 'http://localhost:3000/loans',
      method: 'POST',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') },
      data: {
        loan: {
          borrower_id: $("#loan-borrower-combo").val(),
          book_id: $("#loan-book-combo").val(),
          date_loaned: $("#loan-date").val(),
          loan_duration: $("#loan_duration").val()
        }
      }
    }).done(function(book, textStatus, jqxhr){
      console.log("Book created successfully");
      $("#book-title").text(book.title);
      $("#book-title").attr('readonly', 'readonly');
      $("#book-author").text(book.author);
      $("#book-author").attr('readonly', 'readonly');
      $("#book-year").text(book.year);
      $("#book-year").attr('readonly', 'readonly');
      $("#book-price").text(book.price);
      $("#book-price").attr('readonly', 'readonly');
      $("#book-url").text(book.url);
      $("#book-url").attr('readonly', 'readonly');
      setCreateResultMessage(true);
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(textStatus);
      console.log(jqxhr.responseText);
      setCreateResultMessage(false);
    });
  });

  //update Loan with Ajax
  $("#loan-update").on('click', function(){
    $.ajax({
      url: 'http://localhost:3000/loans/' + $("#user-id").val(),
      method: 'PATCH',
      data: {
        loan: {
          name: $("#name").val(),
          born: $("#born").val(),
          died: $("#died").val()
        }
      }
    }).done(function(book, textStatus, jqxhr){
      console.log("I'm a robot that UPDATED a person.");
    }).fail(function(jqxhr, textStatus, errorThrown) {
      $("#loan-label").html(jqxhr.responseText);
    });
  });

  //destroy Loan with Ajax
  $("#loan-destroy").on('click', function(){
    $.ajax({
      url: 'http://localhost:3000/loans/' + $("#user-id").val(),
      method: 'DELETE'
    }).done(function(book, textStatus, jqxhr){
      console.log("This loan has been added to your list of deleted loans.");
    }).fail(function(jqxhr, textStatus, errorThrown) {
      $("#loan-label").html(jqxhr.responseText);
    });
  });
});
<commit_msg>Add renderUpdate template function to display the update page<commit_after>if (simpleStorage.get('token')) {
  $('#account-btn').show();
} else {
  $('#load-login-btn').show();
}

function showLoginForm() {
  $('#register-box').fadeOut('fast',function() {
      $('#login-box').fadeIn('fast');
      $('#modal-register-footer').fadeOut('fast',function() {
        $('#model-label-header').text('Login');
        $('#modal-login-footer').fadeIn('fast');
      });
  });
};

function showRegisterForm() {
  $('#login-box').fadeOut('fast',function() {
      $('#register-box').fadeIn('fast');
      $('#modal-login-footer').fadeOut('fast',function() {
        $('#model-label-header').text('Register');
        $('#modal-register-footer').fadeIn('fast');
      });
  });
};

var renderIndexPage = function() {
  var templatingFunction = Handlebars.compile($('#index-page-template').html());
  $.ajax({
    url: "http://localhost:3000/books",
    method: 'GET'
  }).done(function(books, textStatus, jqxhr){
    console.log(books);
    var html = templatingFunction(books);
    $("#page").html(html);
  }).fail(function(jqxhr, textStatus, errorThrown){
    console.log(books);
    console.log(textStatus);
    console.log(jqxhr.responseText);
  });
};

// ---------------------- Books --------------------------
var setCreateResultMessage = function(success) {
  if (success) {
    $('#create-book-result-message').addClass('bg-success message');
    $('#create-book-result-message').text('Your book was created successfully!');
    $("#create-book-result-message").css();
  } else {
    $("#create-book-result-message").addClass('bg-danger message');
    $("#create-book-result-message").text('Something went wrong!');
  }
}

var booksPageTemplate = Handlebars.compile($("#books-page-template").html());

var renderCreateBookPage = function(book) {
  var templatingFunction = Handlebars.compile($('#create-book-template').html());
  var html = templatingFunction(book);
  $("#page").html(html);
};

var renderDisplayBookPage = function(book) {
  var templatingFunction = Handlebars.compile($('#display-book-template').html());
  var html = templatingFunction(book);
  $("#page").html(html);
};

var renderUpdateBookPage = function(book) {
  var templatingFunction = Handlebars.compile($('#update-book-template').html());
  var html = templatingFunction(book);
  $("#page").html(html);
};

// ---------------------- Loans --------------------------

var renderCreateLoanPage = function(users, books) {
  var templatingFunction = Handlebars.compile($('#create-loan-template').html());
  var html = templatingFunction(users, books);
  $("#page").html(html);
};

$(document).ready(function() {
  Authenticator.init();

  renderIndexPage("Books List");

  // thumbnail button preview book
  $("#page").on("click", "#thumbnail-preview-btn", function() {
    var clicked_id = $(this).data('id');
    console.log("Clicked button number " + clicked_id);
    $.ajax({
      url: "http://localhost:3000/books/" + clicked_id,
      method: 'GET'
    }).done(function(book, textStatus, jqxhr){
      console.log(book);
      $("#page").html(renderDisplayBookPage(book));

    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(jqxhr.responseText);
    });
  });

  // thumbnail button update book
  $("#page").on("click", "#thumbnail-update-btn", function() {
    var clicked_id = $(this).data('id');
    console.log("Clicked button number " + clicked_id);
    $.ajax({
      url: "http://localhost:3000/books/" + clicked_id,
      method: 'GET'
    }).done(function(book, textStatus, jqxhr){
      console.log(book);
      $("#page").html(renderUpdateBookPage(book));

    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(jqxhr.responseText);
    });
  });

  $("#create-a-book-dd-btn").on("click", function(){
    console.log("#create-a-book-dd-btn clicked");
    renderCreateBookPage();
  });

  //create book with Ajax
  $("#page").on("click", "#book-create", function() {
    var reader = new FileReader();

    reader.onload = function(event){
      $.ajax({
        url: 'http://localhost:3000/books',
        method: 'POST',
        headers: { Authorization: 'Token token=' + simpleStorage.get('token') },
        data: {
          book: {
            title: $("#book-title").val(),
            author: $("#book-author").val(),
            year: $("#book-year").val(),
            price: $("#book-price").val(),
            image: event.target.result,
            url: $("#book-url").val()
          }
        }
      }).done(function(book, textStatus, jqxhr){
        console.log("Book created successfully");
        $("#book-title").text(book.title);
        $("#book-title").attr('readonly', 'readonly');
        $("#book-author").text(book.author);
        $("#book-author").attr('readonly', 'readonly');
        $("#book-year").text(book.year);
        $("#book-year").attr('readonly', 'readonly');
        $("#book-price").text(book.price);
        $("#book-price").attr('readonly', 'readonly');
        $("#book-url").text(book.url);
        $("#book-url").attr('readonly', 'readonly');
        setCreateResultMessage(true);
      }).fail(function(jqxhr, textStatus, errorThrown){
        console.log(textStatus);
        console.log(jqxhr.responseText);
        setCreateResultMessage(false);
      });
    };

    reader.readAsDataURL($('#book-image-upload')[0].files[0]);

  });

  //show user books
  $("#my-books").on("click", function() {
    console.log("my books clicked");

    $.ajax({
      url: "http://localhost:3000/books?limit=me",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      $("#page").html(booksPageTemplate({heading: "My Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("There was an error while LISTING CURRENT USER'S books, error: " + jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // show my loaned books
  $("#my-loaned-books").on("click", function() {
    console.log("my loaned books clicked");

    $.ajax({
      url: "http://localhost:3000/books/loaned",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      console.log(data);
      $("#page").html(booksPageTemplate({heading: "My Loaned Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("There was an error while LISTING CURRENT USER'S books, error: " + jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // show my borrowed books
  $("#my-borrowed-books").on("click", function() {
    console.log("my borrowed books clicked");

    $.ajax({
      url: "http://localhost:3000/books/borrowed",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      console.log(data);
      $("#page").html(booksPageTemplate({heading: "My Borrowed Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // show all books
  $("#books-show").on("click", function() {
    $("#book-label").html();

    $.ajax({
      url: "http://localhost:3000/books",
      method: 'GET' //,
      // headers: { Authorization: 'Token token=' + $('#token').val()}
    }).done(function(data, textStatus, jqxhr){
      $("#page").html(booksPageTemplate({heading: "All Books", books: data.books}));
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("There was an error while LISTING ALL the books, error: " + jqxhr);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // update Book with Ajax
  $("#page").on("click", "#book-update", function() {
    var id = $(this).data('id');

    $.ajax({
      url: 'http://localhost:3000/books/' + id,
      method: 'PATCH',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') },
      data: {
        book: {
          title: $("#book-title").val(),
          author: $("#book-author").val(),
          year: $("#book-year").val(),
          price: $("#book-price").val(),
          url: $("#book-url").val(),
          status: $("#book-status").val()
        }
      }
    }).done(function(book, textStatus, jqxhr) {
      $("#book-label").html(bookTemplate(book));
    }).fail(function(jqxhr, textStatus, errorThrown) {
      console.log("textStatus: " + textStatus);
      $("#book-label").html(jqxhr.responseText);
    });
  });

  //destroy Book with Ajax
  $("#book-destroy").on('click', function() {
    $.ajax({
      url: 'http://localhost:3000/books/' + $("#book-id").val(),
      method: 'DELETE'
    }).done(function(book, textStatus, jqxhr){
      console.log("Your book has been deleted, here is some data about it: " + data);
    }).fail(function(jqxhr, textStatus, errorThrown) {
      $("#book-label").html(jqxhr.responseText);
    });
  });

  // ------------------ Loan ---------------

  // show create loan page
  $("#create-a-loan-dd-btn").on("click", function() {
    console.log("#create-a-loan-dd-btn clicked");

    var users = {};
    var books = {};
    $('#page').load('partials/create-loan-form.html');
    $.ajax({
      url: "http://localhost:3000/users",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      var templatingFunction = Handlebars.compile($('#create-user-select-template').html());
      var html = templatingFunction({users: data.users});
      $('#loan-borrower-combo').html(html);
      users = data;
      console.log(users);
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("Error in getting users");
      console.log(jqxhr.responseText);
    });

    $.ajax({
      url: "http://localhost:3000/books?limit=me",
      method: 'GET',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') }
    }).done(function(data, textStatus, jqxhr){
      var templatingFunction = Handlebars.compile($('#create-book-select-template').html());
      var html = templatingFunction({books: data.books});
      $('#loan-book-combo').html(html);
      books = data;
      console.log(books);
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log("Error in getting books");
      console.log(jqxhr.responseText);
    });
    $("#loan-date").datepicker({format: 'YYYY-MM-DD'});
  });

  //create Loan with Ajax
  $("#page").on('click', "#loan-create", function() {
    console.log("Loan create clicked");
    var borrowe_id = $('loan-borrower-combo').selected_value;
    var book_id =
    $.ajax({
      url: 'http://localhost:3000/loans',
      method: 'POST',
      headers: { Authorization: 'Token token=' + simpleStorage.get('token') },
      data: {
        loan: {
          borrower_id: $("#loan-borrower-combo").val(),
          book_id: $("#loan-book-combo").val(),
          date_loaned: $("#loan-date").val(),
          loan_duration: $("#loan_duration").val()
        }
      }
    }).done(function(book, textStatus, jqxhr){
      console.log("Book created successfully");
      $("#book-title").text(book.title);
      $("#book-title").attr('readonly', 'readonly');
      $("#book-author").text(book.author);
      $("#book-author").attr('readonly', 'readonly');
      $("#book-year").text(book.year);
      $("#book-year").attr('readonly', 'readonly');
      $("#book-price").text(book.price);
      $("#book-price").attr('readonly', 'readonly');
      $("#book-url").text(book.url);
      $("#book-url").attr('readonly', 'readonly');
      setCreateResultMessage(true);
    }).fail(function(jqxhr, textStatus, errorThrown){
      console.log(textStatus);
      console.log(jqxhr.responseText);
      setCreateResultMessage(false);
    });
  });

  //update Loan with Ajax
  $("#loan-update").on('click', function(){
    $.ajax({
      url: 'http://localhost:3000/loans/' + $("#user-id").val(),
      method: 'PATCH',
      data: {
        loan: {
          name: $("#name").val(),
          born: $("#born").val(),
          died: $("#died").val()
        }
      }
    }).done(function(book, textStatus, jqxhr){
      console.log("I'm a robot that UPDATED a person.");
    }).fail(function(jqxhr, textStatus, errorThrown) {
      $("#loan-label").html(jqxhr.responseText);
    });
  });

  //destroy Loan with Ajax
  $("#loan-destroy").on('click', function(){
    $.ajax({
      url: 'http://localhost:3000/loans/' + $("#user-id").val(),
      method: 'DELETE'
    }).done(function(book, textStatus, jqxhr){
      console.log("This loan has been added to your list of deleted loans.");
    }).fail(function(jqxhr, textStatus, errorThrown) {
      $("#loan-label").html(jqxhr.responseText);
    });
  });
});
<|endoftext|>