diff --git a/.env b/.env new file mode 100644 index 00000000..4e0fd1a0 --- /dev/null +++ b/.env @@ -0,0 +1,36 @@ +## these environment variables are passed to containers via docker-compose +## copy this to your plugin root directory and rename as .env +## changing the environment variables will require a rebuild of docker containers + +## project name used by docker & plugin folder name +PROJECT_NAME=woocommerce-pos + +## default development settings +PHP_VERSION=5.6 +# MYSQL_VERSION=8.0 +# WP_VERSION=latest +# WC_VERSION=https://github.com/woocommerce/woocommerce/releases/download/3.5.0-rc.2/woocommerce.zip +# WP_MULTISITE=0 + +## wordpress settings +# WP_USER=admin +# WP_PASSWORD=password +# WP_EMAIL=example@example.com +# WP_TITLE=Localhost +# WP_URL=localhost + +## external ports +# LOCALHOST_HTTP_PORT=80 +# LOCALHOST_HTTPS_PORT=443 +# LOCALHOST_MYSQL_PORT=3306 +# LOCALHOST_PHP_PORT=9001 +# XDEBUG_REMOTE_PORT=9000 + +## mysql +# MYSQL_ROOT_PASSWORD=wordpress +# DB_NAME=wordpress +# DB_HOST=db-mysql57:3306 +# DB_PASSWORD=wordpress + +# directory for wp cli packages +# WP_CLI_PACKAGES_DIR=/var/www/html diff --git a/.gitignore b/.gitignore index fc8f7d37..17319c50 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ assets/js/vendor.bundle.js assets/js/products.min.js coverage assets/js/templates.js +.data +.html +.DS_Store \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 4aeb8349..e0d264bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,21 +1,3 @@ -[submodule "assets/js/src/lib/config/obscura/filtered"] - path = assets/js/src/lib/config/obscura/filtered - url = https://github.com/kilbot/backbone-filtered-collection.git -[submodule "assets/js/src/lib/config/obscura/sorted"] - path = assets/js/src/lib/config/obscura/sorted - url = https://github.com/kilbot/backbone-sorted-collection.git -[submodule "assets/js/src/lib/config/obscura/paginated"] - path = assets/js/src/lib/config/obscura/paginated - url = https://github.com/kilbot/backbone-paginated-collection.git -[submodule "assets/js/src/lib/config/obscura/query"] - path = assets/js/src/lib/config/obscura/query - url = https://github.com/kilbot/backbone-query.git -[submodule "assets/js/src/lib/config/deep-model"] - path = assets/js/src/lib/config/deep-model - url = https://github.com/kilbot/backbone-deep-model.git -[submodule "assets/js/src/lib/config/idb"] - path = assets/js/src/lib/config/idb - url = https://github.com/kilbot/backbone-idb.git [submodule "styleguide"] path = styleguide url = https://github.com/kilbot/WooCommerce-POS-StyleGuide.git diff --git a/.travis.yml b/.travis.yml index 0521ca71..0a41362c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,75 +1,54 @@ -language: php +sudo: required -php: - - 5.4 +language: node_js -addons: - hosts: - - woopos.dev +node_js: + - "node" + +services: + - docker env: - - WP_VERSION=latest WP_MULTISITE=0 - # - WP_VERSION=latest WP_MULTISITE=1 - # - WP_VERSION=3.8 WP_MULTISITE=0 - # - WP_VERSION=3.8 WP_MULTISITE=1 + matrix: + - PHP_VERSION=php54 WC_VERSION=latest WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php55 WC_VERSION=latest WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php56 WC_VERSION=latest WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php70 WC_VERSION=latest WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php54 WC_VERSION=2.6.14 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php55 WC_VERSION=2.6.14 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php56 WC_VERSION=2.6.14 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php70 WC_VERSION=2.6.14 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php54 WC_VERSION=2.5.5 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php55 WC_VERSION=2.5.5 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php56 WC_VERSION=2.5.5 WP_VERSION=latest WP_MULTISITE=0 + - PHP_VERSION=php70 WC_VERSION=2.5.5 WP_VERSION=latest WP_MULTISITE=0 before_install: - - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install stable - - git submodule update --init --recursive + - sudo apt-get update -qq + - sudo apt-get install docker-ce --no-install-recommends -y -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" + - sudo rm /usr/local/bin/docker-compose + - curl -L https://github.com/docker/compose/releases/download/1.11.2/docker-compose-`uname -s`-`uname -m` > docker-compose + - chmod +x docker-compose + - sudo mv docker-compose /usr/local/bin/ + - docker-compose -v + - docker -v install: - # php libraries - - composer require satooshi/php-coveralls:~0.6.1@stable - - composer require guzzlehttp/guzzle:~5 - - composer require 10up/wp_mock:dev-master - # install wordpress & woocommerce & test theme - - bash tests/unit/php/bin/install-travis-wp-tests.sh woopos_tests root '' localhost $WP_VERSION - - mkdir /tmp/wordpress/wp-content/plugins/woocommerce-pos/ - - mv * .[^.]* /tmp/wordpress/wp-content/plugins/woocommerce-pos/ - - mv /tmp/wordpress/* ./ - - git clone https://github.com/kilbot/WooCommerce-POS-Test-Theme.git wp-content/themes/WooCommerce-POS-Test-Theme - - git clone https://github.com/kilbot/WooCommerce-POS-Test-Plugin.git wp-content/plugins/woocommerce-pos-test - # apache - - sudo apt-get update - - sudo apt-get install apache2 libapache2-mod-fastcgi - # enable php-fpm - - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf - - sudo a2enmod rewrite actions fastcgi alias - - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm - # configure apache virtual hosts - - sudo cp -f ./wp-content/plugins/woocommerce-pos/tests/integration/php/bin/travis-ci-apache /etc/apache2/sites-available/default - - sudo sed -e "s?%TRAVIS_BUILD_DIR%?$(pwd)?g" --in-place /etc/apache2/sites-available/default - - sudo service apache2 restart + - npm install && node_modules/.bin/grunt build --force + - npm run start:${PHP_VERSION} before_script: - # wp-cli - - curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar - - chmod +x wp-cli.phar - - sudo mv wp-cli.phar /usr/local/bin/wp - - wp --info - - wp core config --dbname=woopos_tests --dbuser=root - - wp core install --url=woopos.dev --title=WooCommercePOS --admin_user=admin --admin_password=password --admin_email=support@woopos.com.au - - wp rewrite structure '/%year%/%monthnum%/%postname%' - - wp plugin activate woocommerce-pos - - wp plugin activate woocommerce-pos-test - - wp plugin install woocommerce --activate - - wp plugin install wordpress-importer --activate - - wp import wp-content/plugins/woocommerce/dummy-data/dummy-data.xml --authors=create - - wp option update woocommerce_api_enabled yes - - cp wp-content/plugins/woocommerce-pos/tests/integration/php/bin/wp-cli.yml ./ - - wp rewrite flush --hard - # grunt-cli - - cd wp-content/plugins/woocommerce-pos/ - - npm install -g grunt-cli - - npm install + - sleep 60 + - docker exec woocommerce-pos-app-${PHP_VERSION} wp core version --allow-root + - docker exec woocommerce-pos-app-${PHP_VERSION} wp plugin list --allow-root --status=active -script: - - grunt test - - phpunit -c phpunit.xml.dist - - phpunit -c phpunit.int.xml - # - ./node_modules/.bin/pioneer + ## download test theme and activate + - docker exec woocommerce-pos-app-${PHP_VERSION} wp theme install https://github.com/kilbot/WooCommerce-POS-Test-Theme/archive/master.zip --allow-root --activate -after_script: - - php vendor/bin/coveralls -v - - grunt coverage \ No newline at end of file + ## turn off WP_DEBUG to prevent depreciation notices +# - docker exec woocommerce-pos-app-${PHP_VERSION} sed -i "s/'WP_DEBUG', true/'WP_DEBUG', false/g" wp-config.php + +script: + - npm run unit-test:js + - npm run unit-test:${PHP_VERSION} + - npm run integration-test:${PHP_VERSION} \ No newline at end of file diff --git a/.wp-env.json b/.wp-env.json new file mode 100644 index 00000000..16546deb --- /dev/null +++ b/.wp-env.json @@ -0,0 +1,20 @@ +{ + "core": null, + "phpVersion": null, + "plugins": [ + ".", + "https://downloads.wordpress.org/plugin/woocommerce.zip" + ], + "config": { + "WP_DEBUG": true, + "SCRIPT_DEBUG": true, + "WP_PHP_BINARY": "php", + "WP_TESTS_EMAIL": "admin@example.org", + "WP_TESTS_TITLE": "Test Blog", + "WP_TESTS_DOMAIN": "http://localhost", + "WP_SITEURL": "http://localhost", + "WP_HOME": "http://localhost" + }, + "mappings": { + } +} \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js index cfe4abd0..a191fb47 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -6,6 +6,8 @@ module.exports = function(grunt) { var pkg = grunt.file.readJSON('package.json'); + var path = require('path'); + grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), @@ -32,7 +34,7 @@ module.exports = function(grunt) { '!locales.json', '!phpunit.xml', '!phpunit.xml.dist', - '!phpunit.int.xml', + '!phpunit.xml', '!pioneer.json', '!<%= app.css.src %>/**', '!<%= app.js.src %>/**', @@ -155,7 +157,7 @@ module.exports = function(grunt) { radio: 'backbone.radio', underscore: 'lodash' }, - modulesDirectories: ['node_modules', './<%= app.js.src %>'] + modules: ['node_modules', './<%= app.js.src %>'] }, externals: { jquery: 'jQuery', @@ -172,22 +174,20 @@ module.exports = function(grunt) { select2: 'select2', 'idb-wrapper': 'IDBStore' }, - cache: true, - watch: true + cache: true }, dev: { output: { - path: './<%= app.js.build %>/', + path: path.resolve(__dirname, '<%= app.js.build %>/'), filename: '[name].build.js', pathinfo: true, library: 'POS' }, - devtool: 'eval-source-map', - debug: true + devtool: 'eval-source-map' }, deploy: { output: { - path: './<%= app.js.build %>/', + path: path.resolve(__dirname, '<%= app.js.build %>'), filename: '[name].build.js', library: 'POS' } @@ -241,12 +241,16 @@ module.exports = function(grunt) { options: { potFilename: 'woocommerce-pos.pot', exclude: [ + '.html', 'styleguide', 'includes/admin/.*', 'includes/products/.*', 'includes/class-wc-pos-activator.php', 'includes/class-wc-pos-deactivator.php' ], + // include: [ + // './*' + // ], processPot: function( pot ) { var translation, excluded_meta = [ @@ -276,6 +280,7 @@ module.exports = function(grunt) { options: { potFilename: 'woocommerce-pos-admin.pot', exclude: [ + '.html', 'styleguide' ], include: [ @@ -436,8 +441,11 @@ module.exports = function(grunt) { // test grunt.registerTask('test', 'Run unit tests', ['symlink', 'simplemocha']); + // build + grunt.registerTask('build', 'Build projects', ['compass', 'cssmin', 'jshint', 'test', 'webpack:dev', 'uglify']); + // dev - grunt.registerTask('dev', 'Development build', ['compass', 'cssmin', 'jshint', 'test', 'webpack:dev', 'uglify', 'watch']); + grunt.registerTask('dev', 'Development build', ['build', 'watch']); // deploy grunt.registerTask('deploy', 'Production build', ['test', 'makepot', 'webpack:deploy', 'js_locales', 'uglify', 'copy', 'compress', 'clean']); diff --git a/LICENSE.txt b/LICENSE.txt old mode 100644 new mode 100755 diff --git a/assets/css/src/scss/partials/_icons.scss b/assets/css/src/scss/partials/_icons.scss index c447908b..2e1258f0 100644 --- a/assets/css/src/scss/partials/_icons.scss +++ b/assets/css/src/scss/partials/_icons.scss @@ -199,7 +199,7 @@ icon { .#{current-module()}-#{nth($icon, 1)} { &:before { content: unquote($withslash); - color: "#{nth($icon, 3)}"; + color: #{nth($icon, 3)}; } } diff --git a/assets/css/src/scss/partials/_list.scss b/assets/css/src/scss/partials/_list.scss index 6bb79190..17c66630 100644 --- a/assets/css/src/scss/partials/_list.scss +++ b/assets/css/src/scss/partials/_list.scss @@ -46,13 +46,13 @@ list { .#{current-module()} { - ul { + > div > ul, > ul { width: 100%; margin: 0; padding: 0; list-style: none; - li { + > li { border-bottom: 1px solid $list-border-color; &:last-of-type { @@ -81,9 +81,15 @@ list { // Default zebra-stripe styles (alternating gray and transparent backgrounds) .#{current-module()}-striped { - li:nth-of-type(odd) { - background-color: $list-alternate-bg-color; + + > div > ul, > ul { + + > li:nth-of-type(odd) { + background-color: $list-alternate-bg-color; + } + } + } diff --git a/assets/css/src/scss/partials/_products.scss b/assets/css/src/scss/partials/_products.scss index d9c664da..2f195735 100644 --- a/assets/css/src/scss/partials/_products.scss +++ b/assets/css/src/scss/partials/_products.scss @@ -71,6 +71,21 @@ products { small { display: block; } + + ul.variations, ul.variant { + list-style: none; + padding: 0; + margin: 0; + font-size: $font-size-sm; + strong { + font-weight: 600; + } + a.active { + color: $text-color; + text-decoration: none; + cursor: default; + } + } } .price { diff --git a/assets/css/src/scss/partials/admin/_settings.scss b/assets/css/src/scss/partials/admin/_settings.scss index f6abd6b3..dab0a7f7 100644 --- a/assets/css/src/scss/partials/admin/_settings.scss +++ b/assets/css/src/scss/partials/admin/_settings.scss @@ -28,6 +28,8 @@ settings { font-size: 15px; line-height: 24px; border-bottom: 1px solid #ccc; + margin-bottom: -1px; + &.active { color: #000; background: #f1f1f1; diff --git a/assets/js/src/apps/pos/cart/route.js b/assets/js/src/apps/pos/cart/route.js index 95776766..0ff7c8c8 100644 --- a/assets/js/src/apps/pos/cart/route.js +++ b/assets/js/src/apps/pos/cart/route.js @@ -10,6 +10,7 @@ var _ = require('lodash'); var App = require('lib/config/application'); var Utils = require('lib/utilities/utils'); var polyglot = require('lib/utilities/polyglot'); +var Radio = require('backbone.radio'); var CartRoute = Route.extend({ @@ -147,14 +148,19 @@ var CartRoute = Route.extend({ 'action:fee': function(){ this.order.cart.addToCart({ type : 'fee', - title : polyglot.t('titles.fee') + name : polyglot.t('titles.fee') }); }, 'action:shipping': function(){ + var shipping = Radio.request('entities', 'get', { + type: 'option', + name: 'shipping' + }); + var method_ids = _.keys(shipping); this.order.cart.addToCart({ type : 'shipping', method_title: polyglot.t('titles.shipping'), - method_id : '' // todo: settings + method_id : _.first(method_ids) || '' }); }, 'action:checkout': function(){ diff --git a/assets/js/src/apps/pos/cart/views/line/views/item.js b/assets/js/src/apps/pos/cart/views/line/views/item.js index a12855a9..70cc3b21 100644 --- a/assets/js/src/apps/pos/cart/views/line/views/item.js +++ b/assets/js/src/apps/pos/cart/views/line/views/item.js @@ -50,7 +50,7 @@ module.exports = FormView.extend({ }, modelEvents: { - 'change:title' : 'save', + 'change:name' : 'save', 'change:method_title' : 'save' }, @@ -63,7 +63,7 @@ module.exports = FormView.extend({ onSet: Utils.unformat }, '*[data-name="title"]' : { - observe: 'title', + observe: 'name', events: ['blur'] }, 'dl.meta': { @@ -105,7 +105,6 @@ module.exports = FormView.extend({ }, save: function(){ - console.log(arguments); this.model.save(); }, diff --git a/assets/js/src/apps/pos/products/views/item/views/drawer/variation.js b/assets/js/src/apps/pos/products/views/item/views/drawer/variation.js index 446479bc..fb91db48 100644 --- a/assets/js/src/apps/pos/products/views/item/views/drawer/variation.js +++ b/assets/js/src/apps/pos/products/views/item/views/drawer/variation.js @@ -28,7 +28,8 @@ var Item = ItemView.extend({ templateHelpers: function(){ return { variation: true, - title: this.options.model.parent.get('title') + title: this.options.model.parent.get('title'), + attributes: this.model.getVariationAttributes() }; } diff --git a/assets/js/src/apps/pos/products/views/item/views/drawer/variations.js b/assets/js/src/apps/pos/products/views/item/views/drawer/variations.js index 20c5eae6..901675e7 100644 --- a/assets/js/src/apps/pos/products/views/item/views/drawer/variations.js +++ b/assets/js/src/apps/pos/products/views/item/views/drawer/variations.js @@ -30,12 +30,11 @@ module.exports = CollectionView.extend({ if(filter){ filter = filter || {}; var matchMaker = function(model){ - var attributes = model.get('attributes'); + var attributes = model.getVariationAttributes(); return _.any(attributes, function(attribute){ return attribute.name === filter.name && - attribute.option === filter.option; + ( attribute.option === undefined && _.includes(attribute.options, filter.option) ) || attribute.option === filter.option || attribute.option === ''; }); - }; this.collection.filterBy('variation', matchMaker); } diff --git a/assets/js/src/apps/pos/products/views/item/views/popover/variations.js b/assets/js/src/apps/pos/products/views/item/views/popover/variations.js index 3ae00570..6fa1972b 100644 --- a/assets/js/src/apps/pos/products/views/item/views/popover/variations.js +++ b/assets/js/src/apps/pos/products/views/item/views/popover/variations.js @@ -29,7 +29,7 @@ var Variations = ItemView.extend({ templateHelpers: function(){ var data = {}; - data.variations = _.chain( this.model.getVariationOptions() ) + data.variations = _.chain( this.model.productVariations() ) .each(function(variation){ if(hasManyOptions(variation)){ variation.select = true; @@ -70,8 +70,11 @@ var Variations = ItemView.extend({ var name = target.data('name'); var option = target.val(); this.collection.filterBy(name, function(model){ - return _.some(model.get('attributes'), function(obj){ - return obj.name === name && obj.option === option; + return _.some(model.getVariationAttributes(), function(obj){ + if(obj.name !== name) { + return false; + } + return obj.option === undefined && _.includes(obj.options, option) || obj.option === option || obj.option === ''; }); }); this.ui.add.prop('disabled', this.collection.length !== 1); diff --git a/assets/js/src/apps/pos/products/views/item/views/product.js b/assets/js/src/apps/pos/products/views/item/views/product.js index 02a9179b..68262813 100644 --- a/assets/js/src/apps/pos/products/views/item/views/product.js +++ b/assets/js/src/apps/pos/products/views/item/views/product.js @@ -13,14 +13,21 @@ var Item = ItemView.extend({ ui: { add : 'a[data-action="add"]', - vpopover : 'a[data-action="variations"]', - vdrawer : '.title dl.variations dd a' + popover : 'a[data-action="variations"]', + filter : '.title ul.variations li a', + open : 'a[data-action="expand"]', + close : 'a[data-action="close"]' }, events: { - 'click @ui.add' : 'addToCart', - 'click @ui.vpopover' : 'variationsPopover', - 'click @ui.vdrawer' : 'variationsDrawer' + 'click @ui.add' : 'addToCart', + 'click @ui.popover' : 'variationsPopover', + 'click @ui.filter' : 'variationsDrawer' + }, + + triggers: { + 'click @ui.open' : 'open:drawer', + 'click @ui.close' : 'close:drawer toggle:reset' }, modelEvents: { @@ -82,7 +89,7 @@ var Item = ItemView.extend({ price: variations.superset().range('price'), sale_price: variations.superset().range('sale_price'), regular_price: variations.superset().range('regular_price'), - product_variations: this.model.getVariationOptions() + product_variations: this.model.productVariations() } : {} ; data.product_attributes = this.model.productAttributes(); return data; diff --git a/assets/js/src/entities/cart/collection.js b/assets/js/src/entities/cart/collection.js index 34fff8aa..d03fe2ef 100644 --- a/assets/js/src/entities/cart/collection.js +++ b/assets/js/src/entities/cart/collection.js @@ -17,7 +17,7 @@ module.exports = IndexedDBCollection.extend({ */ productAttributes: [ 'order', - 'title', + 'name', 'local_id', 'product_id', 'type', diff --git a/assets/js/src/entities/cart/model.js b/assets/js/src/entities/cart/model.js index 86553d74..b0e45fd4 100644 --- a/assets/js/src/entities/cart/model.js +++ b/assets/js/src/entities/cart/model.js @@ -263,6 +263,22 @@ module.exports = Model.extend({ sum += this.get(array[i]); } return Utils.round(sum, 4); + }, + + // hack to copy meta to meta_data + toJSON: function(args){ + var data = Model.prototype.toJSON.apply(this, args); + if(data.meta) { + var array = []; + _.each(data.meta, function(meta){ + array.push({ + key : meta.label, + value : meta.value + }); + }); + data.meta_data = array; + } + return data; } }); \ No newline at end of file diff --git a/assets/js/src/entities/orders/model.js b/assets/js/src/entities/orders/model.js index bbf29432..937bb134 100644 --- a/assets/js/src/entities/orders/model.js +++ b/assets/js/src/entities/orders/model.js @@ -42,7 +42,7 @@ var Model = DualModel.extend({ initialize: function(attributes){ attributes = attributes || {}; - if(!attributes.customer){ + if(!attributes.customer && !attributes.billing){ var customers = this.getEntities('customers'); var customer = customers['default'] || customers.guest || {}; this.set({ diff --git a/assets/js/src/entities/products/model.js b/assets/js/src/entities/products/model.js index faf803a9..ddded6bf 100644 --- a/assets/js/src/entities/products/model.js +++ b/assets/js/src/entities/products/model.js @@ -7,7 +7,7 @@ module.exports = DualModel.extend({ name: 'product', // this is an array of fields used by FilterCollection.matchmaker() - fields: ['title'], + fields: ['name'], // data types schema: { @@ -169,7 +169,10 @@ module.exports = DualModel.extend({ getVariations: function(){ if( this.get('type') !== 'variable' ){ return false; } if( ! this._variations ){ - var variations = new Variations(this.get('variations'), { parent: this }); + var variations = new Variations(this.get('variations'), { + parent: this, + parentAttrs: this.attributes + }); this._variations = new FilteredCollection(variations); } return this._variations; diff --git a/assets/js/src/entities/variations/model.js b/assets/js/src/entities/variations/model.js index 5277447d..d40f5318 100644 --- a/assets/js/src/entities/variations/model.js +++ b/assets/js/src/entities/variations/model.js @@ -1,5 +1,7 @@ //var Model = require('lib/config/model'); var Model = require('lib/config/deep-model'); +var _ = require('lodash'); +var Radio = require('backbone.radio'); module.exports = Model.extend({ name: 'product', @@ -15,10 +17,30 @@ module.exports = Model.extend({ stock_quantity: 'number' }, + url: function(){ + var wc_api = Radio.request('entities', 'get', { + type: 'option', + name: 'wc_api' + }); + if(wc_api.indexOf('wp-json') !== -1) { + var id = this.get('id'); + var parent_id = this.parent.get('id'); + if(id && parent_id) { + return wc_api + 'products/' + parent_id + '/variations/' + id; + } + } + return wc_api + 'products/' + this.id; + }, + + constructor: function(attributes, options){ + options = _.extend({parse: true}, options); // parse by default + Model.call(this, attributes, options); + }, + initialize: function(attributes, options){ options = options || {}; this.parent = options.parent; - this.set({ title: options.parent.get('title') }); + this.set({ name: options.parent.get('name') }); }, // copy variation to parent @@ -29,6 +51,33 @@ module.exports = Model.extend({ self.parent.set({ variations: self.collection.toJSON() }); self.parent.merge(); }); + }, + + /** + * + */ + getVariationAttributes: function(){ + var result = []; + var attributes = this.get('attributes'); + + _.each(this.parent.productVariations(), function(attribute){ + // pluck attribute on id and merge + var attr = _.findWhere(attributes, { id: attribute.id }); + + // piped attributes have id = 0 ffs + if(!attr || attr.id === 0){ + attr = _.findWhere(attributes, { name: attribute.name }); + } + + if( attr ) { + result.push( _.merge(attr, attribute) ); + } else { + result.push( attribute ); + } + }); + + // sort + return _.sortBy( result, 'position' ); } }); \ No newline at end of file diff --git a/assets/js/src/lib/behaviors/dropdown.js b/assets/js/src/lib/behaviors/dropdown.js index 91f36f61..06001d64 100644 --- a/assets/js/src/lib/behaviors/dropdown.js +++ b/assets/js/src/lib/behaviors/dropdown.js @@ -6,7 +6,7 @@ var Drop = require('tether-drop'); var App = require('lib/config/application'); var namespace = App.prototype.namespace('dropdown'); -var _Drop = Drop.createContext({ +var Drop_ = Drop.createContext({ classPrefix: namespace }); @@ -65,7 +65,7 @@ var Dropdown = Behavior.extend({ target : target, content : content }); - this.drop = new _Drop(options); + this.drop = new Drop_(options); // drop events this.drop.on('open', this.onOpen); diff --git a/assets/js/src/lib/behaviors/tooltip.js b/assets/js/src/lib/behaviors/tooltip.js index b395c2c9..9819be9f 100644 --- a/assets/js/src/lib/behaviors/tooltip.js +++ b/assets/js/src/lib/behaviors/tooltip.js @@ -6,7 +6,7 @@ var Drop = require('tether-drop'); var App = require('lib/config/application'); var namespace = App.prototype.namespace('tooltip'); -var _Drop = Drop.createContext({ +var Drop_ = Drop.createContext({ classPrefix: namespace }); @@ -46,7 +46,7 @@ var TooltipBehavior = Behavior.extend({ target : e.target, content : $(e.target).attr('title') }); - var drop = new _Drop(options); + var drop = new Drop_(options); this._initialized.push(e.target); // remove the title attribute to prevent browser hover diff --git a/assets/js/src/lib/components/modal/service.js b/assets/js/src/lib/components/modal/service.js index 71176663..7e7d7cb3 100644 --- a/assets/js/src/lib/components/modal/service.js +++ b/assets/js/src/lib/components/modal/service.js @@ -128,7 +128,12 @@ module.exports = Service.extend({ options.message = options.thrownError.message; } else { options.status = options.jqXHR.statusText; - if( options.jqXHR.responseJSON && options.jqXHR.responseJSON.errors[0] ){ + if(options.jqXHR.responseJSON && options.jqXHR.responseJSON.message) { + options.message = options.jqXHR.responseJSON.message; + } + else if( options.jqXHR.responseJSON && + options.jqXHR.responseJSON.errors && + options.jqXHR.responseJSON.errors[0] ){ options.message = options.jqXHR.responseJSON.errors[0].message; } } diff --git a/assets/js/src/lib/components/modal/views/layout.js b/assets/js/src/lib/components/modal/views/layout.js index ee98c07f..bf01a6bd 100644 --- a/assets/js/src/lib/components/modal/views/layout.js +++ b/assets/js/src/lib/components/modal/views/layout.js @@ -7,7 +7,7 @@ var Tmpl = require('./modal.hbs'); var Radio = require('backbone.radio'); var debug = require('debug')('modalLayout'); var App = require('lib/config/application'); -require('bootstrap/dist/js/umd/modal'); +require('./modal'); module.exports = LayoutView.extend({ template: hbs.compile(Tmpl), diff --git a/assets/js/src/lib/components/modal/views/modal.js b/assets/js/src/lib/components/modal/views/modal.js new file mode 100755 index 00000000..f82ec5b7 --- /dev/null +++ b/assets/js/src/lib/components/modal/views/modal.js @@ -0,0 +1,554 @@ +/* jshint ignore:start */ +(function (global, factory) { + if (typeof define === 'function' && define.amd) { + define(['exports', 'module', './util'], factory); + } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') { + factory(exports, module, require('./util')); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, mod, global.Util); + global.modal = mod.exports; + } +})(this, function (exports, module, _util) { + 'use strict'; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + var _Util = _interopRequireDefault(_util); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.0.0-alpha.2): modal.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Modal = (function ($) { + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + var NAME = 'modal'; + var VERSION = '4.0.0-alpha.2'; + var DATA_KEY = 'bs.modal'; + var EVENT_KEY = '.' + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $.fn[NAME]; + var TRANSITION_DURATION = 300; + var BACKDROP_TRANSITION_DURATION = 150; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var Default = { + backdrop: true, + keyboard: true, + focus: true, + show: true + }; + + var DefaultType = { + backdrop: '(boolean|string)', + keyboard: 'boolean', + focus: 'boolean', + show: 'boolean' + }; + + var Event = { + HIDE: 'hide' + EVENT_KEY, + HIDDEN: 'hidden' + EVENT_KEY, + SHOW: 'show' + EVENT_KEY, + SHOWN: 'shown' + EVENT_KEY, + FOCUSIN: 'focusin' + EVENT_KEY, + RESIZE: 'resize' + EVENT_KEY, + CLICK_DISMISS: 'click.dismiss' + EVENT_KEY, + KEYDOWN_DISMISS: 'keydown.dismiss' + EVENT_KEY, + MOUSEUP_DISMISS: 'mouseup.dismiss' + EVENT_KEY, + MOUSEDOWN_DISMISS: 'mousedown.dismiss' + EVENT_KEY, + CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY + }; + + var ClassName = { + SCROLLBAR_MEASURER: 'modal-scrollbar-measure', + BACKDROP: 'modal-backdrop', + OPEN: 'modal-open', + FADE: 'fade', + IN: 'in' + }; + + var Selector = { + DIALOG: '.modal-dialog', + DATA_TOGGLE: '[data-toggle="modal"]', + DATA_DISMISS: '[data-dismiss="modal"]', + FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed' + }; + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + var Modal = (function () { + function Modal(element, config) { + _classCallCheck(this, Modal); + + this._config = this._getConfig(config); + this._element = element; + this._dialog = $(element).find(Selector.DIALOG)[0]; + this._backdrop = null; + this._isShown = false; + this._isBodyOverflowing = false; + this._ignoreBackdropClick = false; + this._originalBodyPadding = 0; + this._scrollbarWidth = 0; + } + + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + // getters + + _createClass(Modal, [{ + key: 'toggle', + + // public + + value: function toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + } + }, { + key: 'show', + value: function show(relatedTarget) { + var _this = this; + + var showEvent = $.Event(Event.SHOW, { + relatedTarget: relatedTarget + }); + + $(this._element).trigger(showEvent); + + if (this._isShown || showEvent.isDefaultPrevented()) { + return; + } + + this._isShown = true; + + this._checkScrollbar(); + this._setScrollbar(); + + $(document.body).addClass(ClassName.OPEN); + + this._setEscapeEvent(); + this._setResizeEvent(); + + $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, $.proxy(this.hide, this)); + + $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { + $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { + if ($(event.target).is(_this._element)) { + _this._ignoreBackdropClick = true; + } + }); + }); + + this._showBackdrop($.proxy(this._showElement, this, relatedTarget)); + } + }, { + key: 'hide', + value: function hide(event) { + if (event) { + event.preventDefault(); + } + + var hideEvent = $.Event(Event.HIDE); + + $(this._element).trigger(hideEvent); + + if (!this._isShown || hideEvent.isDefaultPrevented()) { + return; + } + + this._isShown = false; + + this._setEscapeEvent(); + this._setResizeEvent(); + + $(document).off(Event.FOCUSIN); + + $(this._element).removeClass(ClassName.IN); + + $(this._element).off(Event.CLICK_DISMISS); + $(this._dialog).off(Event.MOUSEDOWN_DISMISS); + + if (_Util['default'].supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) { + + $(this._element).one(_Util['default'].TRANSITION_END, $.proxy(this._hideModal, this)).emulateTransitionEnd(TRANSITION_DURATION); + } else { + this._hideModal(); + } + } + }, { + key: 'dispose', + value: function dispose() { + $.removeData(this._element, DATA_KEY); + + $(window).off(EVENT_KEY); + $(document).off(EVENT_KEY); + $(this._element).off(EVENT_KEY); + $(this._backdrop).off(EVENT_KEY); + + this._config = null; + this._element = null; + this._dialog = null; + this._backdrop = null; + this._isShown = null; + this._isBodyOverflowing = null; + this._ignoreBackdropClick = null; + this._originalBodyPadding = null; + this._scrollbarWidth = null; + } + + // private + + }, { + key: '_getConfig', + value: function _getConfig(config) { + config = $.extend({}, Default, config); + _Util['default'].typeCheckConfig(NAME, config, DefaultType); + return config; + } + }, { + key: '_showElement', + value: function _showElement(relatedTarget) { + var _this2 = this; + + var transition = _Util['default'].supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE); + + if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { + // don't move modals dom position + document.body.appendChild(this._element); + } + + this._element.style.display = 'block'; + this._element.removeAttribute('aria-hidden'); + this._element.scrollTop = 0; + + if (transition) { + _Util['default'].reflow(this._element); + } + + $(this._element).addClass(ClassName.IN); + + if (this._config.focus) { + this._enforceFocus(); + } + + var shownEvent = $.Event(Event.SHOWN, { + relatedTarget: relatedTarget + }); + + var transitionComplete = function transitionComplete() { + if (_this2._config.focus) { + _this2._element.focus(); + } + $(_this2._element).trigger(shownEvent); + }; + + if (transition) { + $(this._dialog).one(_Util['default'].TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION); + } else { + transitionComplete(); + } + } + }, { + key: '_enforceFocus', + value: function _enforceFocus() { + var _this3 = this; + + $(document).off(Event.FOCUSIN) // guard against infinite focus loop + .on(Event.FOCUSIN, function (event) { + if (document !== event.target && _this3._element !== event.target && !$(_this3._element).has(event.target).length) { + _this3._element.focus(); + } + }); + } + }, { + key: '_setEscapeEvent', + value: function _setEscapeEvent() { + var _this4 = this; + + if (this._isShown && this._config.keyboard) { + $(this._element).on(Event.KEYDOWN_DISMISS, function (event) { + if (event.which === ESCAPE_KEYCODE) { + _this4.hide(); + } + }); + } else if (!this._isShown) { + $(this._element).off(Event.KEYDOWN_DISMISS); + } + } + }, { + key: '_setResizeEvent', + value: function _setResizeEvent() { + if (this._isShown) { + $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this)); + } else { + $(window).off(Event.RESIZE); + } + } + }, { + key: '_hideModal', + value: function _hideModal() { + var _this5 = this; + + this._element.style.display = 'none'; + this._element.setAttribute('aria-hidden', 'true'); + this._showBackdrop(function () { + $(document.body).removeClass(ClassName.OPEN); + _this5._resetAdjustments(); + _this5._resetScrollbar(); + $(_this5._element).trigger(Event.HIDDEN); + }); + } + }, { + key: '_removeBackdrop', + value: function _removeBackdrop() { + if (this._backdrop) { + $(this._backdrop).remove(); + this._backdrop = null; + } + } + }, { + key: '_showBackdrop', + value: function _showBackdrop(callback) { + var _this6 = this; + + var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; + + if (this._isShown && this._config.backdrop) { + var doAnimate = _Util['default'].supportsTransitionEnd() && animate; + + this._backdrop = document.createElement('div'); + this._backdrop.className = ClassName.BACKDROP; + + if (animate) { + $(this._backdrop).addClass(animate); + } + + $(this._backdrop).appendTo(document.body); + + $(this._element).on(Event.CLICK_DISMISS, function (event) { + if (_this6._ignoreBackdropClick) { + _this6._ignoreBackdropClick = false; + return; + } + if (event.target !== event.currentTarget) { + return; + } + if (_this6._config.backdrop === 'static') { + _this6._element.focus(); + } else { + _this6.hide(); + } + }); + + if (doAnimate) { + _Util['default'].reflow(this._backdrop); + } + + $(this._backdrop).addClass(ClassName.IN); + + if (!callback) { + return; + } + + if (!doAnimate) { + callback(); + return; + } + + $(this._backdrop).one(_Util['default'].TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION); + } else if (!this._isShown && this._backdrop) { + $(this._backdrop).removeClass(ClassName.IN); + + var callbackRemove = function callbackRemove() { + _this6._removeBackdrop(); + if (callback) { + callback(); + } + }; + + if (_Util['default'].supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) { + $(this._backdrop).one(_Util['default'].TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION); + } else { + callbackRemove(); + } + } else if (callback) { + callback(); + } + } + + // ---------------------------------------------------------------------- + // the following methods are used to handle overflowing modals + // todo (fat): these should probably be refactored out of modal.js + // ---------------------------------------------------------------------- + + }, { + key: '_handleUpdate', + value: function _handleUpdate() { + this._adjustDialog(); + } + }, { + key: '_adjustDialog', + value: function _adjustDialog() { + var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; + + if (!this._isBodyOverflowing && isModalOverflowing) { + this._element.style.paddingLeft = this._scrollbarWidth + 'px'; + } + + if (this._isBodyOverflowing && !isModalOverflowing) { + this._element.style.paddingRight = this._scrollbarWidth + 'px'; + } + } + }, { + key: '_resetAdjustments', + value: function _resetAdjustments() { + this._element.style.paddingLeft = ''; + this._element.style.paddingRight = ''; + } + }, { + key: '_checkScrollbar', + value: function _checkScrollbar() { + this._isBodyOverflowing = document.body.clientWidth < window.innerWidth; + this._scrollbarWidth = this._getScrollbarWidth(); + } + }, { + key: '_setScrollbar', + value: function _setScrollbar() { + var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10); + + this._originalBodyPadding = document.body.style.paddingRight || ''; + + if (this._isBodyOverflowing) { + document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px'; + } + } + }, { + key: '_resetScrollbar', + value: function _resetScrollbar() { + document.body.style.paddingRight = this._originalBodyPadding; + } + }, { + key: '_getScrollbarWidth', + value: function _getScrollbarWidth() { + // thx d.walsh + var scrollDiv = document.createElement('div'); + scrollDiv.className = ClassName.SCROLLBAR_MEASURER; + document.body.appendChild(scrollDiv); + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return scrollbarWidth; + } + + // static + + }], [{ + key: '_jQueryInterface', + value: function _jQueryInterface(config, relatedTarget) { + return this.each(function () { + var data = $(this).data(DATA_KEY); + var _config = $.extend({}, Modal.Default, $(this).data(), typeof config === 'object' && config); + + if (!data) { + data = new Modal(this, _config); + $(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (data[config] === undefined) { + throw new Error('No method named "' + config + '"'); + } + data[config](relatedTarget); + } else if (_config.show) { + data.show(relatedTarget); + } + }); + } + }, { + key: 'VERSION', + get: function get() { + return VERSION; + } + }, { + key: 'Default', + get: function get() { + return Default; + } + }]); + + return Modal; + })(); + + $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + var _this7 = this; + + var target = undefined; + var selector = _Util['default'].getSelectorFromElement(this); + + if (selector) { + target = $(selector)[0]; + } + + var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data()); + + if (this.tagName === 'A') { + event.preventDefault(); + } + + var $target = $(target).one(Event.SHOW, function (showEvent) { + if (showEvent.isDefaultPrevented()) { + // only register focus restorer if modal will actually get shown + return; + } + + $target.one(Event.HIDDEN, function () { + if ($(_this7).is(':visible')) { + _this7.focus(); + } + }); + }); + + Modal._jQueryInterface.call($(target), config, this); + }); + + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $.fn[NAME] = Modal._jQueryInterface; + $.fn[NAME].Constructor = Modal; + $.fn[NAME].noConflict = function () { + $.fn[NAME] = JQUERY_NO_CONFLICT; + return Modal._jQueryInterface; + }; + + return Modal; + })(jQuery); + + module.exports = Modal; +}); +/* jshint ignore:end */ \ No newline at end of file diff --git a/assets/js/src/lib/components/modal/views/util.js b/assets/js/src/lib/components/modal/views/util.js new file mode 100644 index 00000000..6a9912d1 --- /dev/null +++ b/assets/js/src/lib/components/modal/views/util.js @@ -0,0 +1,179 @@ +/* jshint ignore:start */ +(function (global, factory) { + if (typeof define === 'function' && define.amd) { + define(['exports', 'module'], factory); + } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') { + factory(exports, module); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, mod); + global.util = mod.exports; + } +})(this, function (exports, module) { + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.0.0-alpha.2): util.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + 'use strict'; + + var Util = (function ($) { + + /** + * ------------------------------------------------------------------------ + * Private TransitionEnd Helpers + * ------------------------------------------------------------------------ + */ + + var transition = false; + + var MAX_UID = 1000000; + + var TransitionEndEvent = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + }; + + // shoutout AngusCroll (https://goo.gl/pxwQGp) + function toType(obj) { + return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); + } + + function isElement(obj) { + return (obj[0] || obj).nodeType; + } + + function getSpecialTransitionEndEvent() { + return { + bindType: transition.end, + delegateType: transition.end, + handle: function handle(event) { + if ($(event.target).is(this)) { + return event.handleObj.handler.apply(this, arguments); + } + return undefined; + } + }; + } + + function transitionEndTest() { + if (window.QUnit) { + return false; + } + + var el = document.createElement('bootstrap'); + + for (var _name in TransitionEndEvent) { + if (el.style[_name] !== undefined) { + return { end: TransitionEndEvent[_name] }; + } + } + + return false; + } + + function transitionEndEmulator(duration) { + var _this = this; + + var called = false; + + $(this).one(Util.TRANSITION_END, function () { + called = true; + }); + + setTimeout(function () { + if (!called) { + Util.triggerTransitionEnd(_this); + } + }, duration); + + return this; + } + + function setTransitionEndSupport() { + transition = transitionEndTest(); + + $.fn.emulateTransitionEnd = transitionEndEmulator; + + if (Util.supportsTransitionEnd()) { + $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); + } + } + + /** + * -------------------------------------------------------------------------- + * Public Util Api + * -------------------------------------------------------------------------- + */ + + var Util = { + + TRANSITION_END: 'bsTransitionEnd', + + getUID: function getUID(prefix) { + do { + /* eslint-disable no-bitwise */ + prefix += ~ ~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here + /* eslint-enable no-bitwise */ + } while (document.getElementById(prefix)); + return prefix; + }, + + getSelectorFromElement: function getSelectorFromElement(element) { + var selector = element.getAttribute('data-target'); + + if (!selector) { + selector = element.getAttribute('href') || ''; + selector = /^#[a-z]/i.test(selector) ? selector : null; + } + + return selector; + }, + + reflow: function reflow(element) { + new Function('bs', 'return bs')(element.offsetHeight); + }, + + triggerTransitionEnd: function triggerTransitionEnd(element) { + $(element).trigger(transition.end); + }, + + supportsTransitionEnd: function supportsTransitionEnd() { + return Boolean(transition); + }, + + typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { + for (var property in configTypes) { + if (configTypes.hasOwnProperty(property)) { + var expectedTypes = configTypes[property]; + var value = config[property]; + var valueType = undefined; + + if (value && isElement(value)) { + valueType = 'element'; + } else { + valueType = toType(value); + } + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".')); + } + } + } + } + }; + + setTransitionEndSupport(); + + return Util; + })(jQuery); + + module.exports = Util; +}); +/* jshint ignore:end */ \ No newline at end of file diff --git a/assets/js/src/lib/components/numpad/model.js b/assets/js/src/lib/components/numpad/model.js index d5a591f7..34fb9207 100644 --- a/assets/js/src/lib/components/numpad/model.js +++ b/assets/js/src/lib/components/numpad/model.js @@ -15,7 +15,9 @@ module.exports = bb.Model.extend({ options = options || {}; this.numpad = options.numpad; - this.set({ value: options.value.toString() }); + if(options.value){ + this.set({ value: options.value.toString() }); + } if(options.precision){ this.precision = options.precision; diff --git a/assets/js/src/lib/components/popover/service.js b/assets/js/src/lib/components/popover/service.js index 53566840..8f95ee91 100644 --- a/assets/js/src/lib/components/popover/service.js +++ b/assets/js/src/lib/components/popover/service.js @@ -6,7 +6,7 @@ var Mn = require('backbone.marionette'); var App = require('lib/config/application'); var namespace = App.prototype.namespace('popover'); -var _Drop = Drop.createContext({ +var Drop_ = Drop.createContext({ classPrefix: namespace }); @@ -39,7 +39,7 @@ module.exports = Service.extend({ this.close(); // new Drop instance - this.drop = new _Drop(options); + this.drop = new Drop_(options); // attach region this.drop.region = new Mn.Region({ diff --git a/assets/js/src/lib/components/print/service.js b/assets/js/src/lib/components/print/service.js index 85c96bc8..deaa1bda 100644 --- a/assets/js/src/lib/components/print/service.js +++ b/assets/js/src/lib/components/print/service.js @@ -32,7 +32,9 @@ module.exports = Service.extend({ this.deferred = $.Deferred(); // insert template + iframe.document.open(); iframe.document.write(template); + iframe.document.close(); // print once loaded var loaded = function(){ @@ -58,14 +60,6 @@ module.exports = Service.extend({ * returns a reference to the iframe window */ init: function(){ - if(this.iframe){ - this.iframe.remove(); - } - - this.iframe = $('
- +- support@woopos.com.au'); ?> + support@wcpos.com'); ?>
\ No newline at end of file diff --git a/includes/views/modals/tmpl-hotkeys.php b/includes/views/modals/tmpl-hotkeys.php old mode 100644 new mode 100755 diff --git a/includes/views/pos/cart/tmpl-customer.php b/includes/views/pos/cart/tmpl-customer.php old mode 100644 new mode 100755 diff --git a/includes/views/pos/cart/tmpl-item-drawer.php b/includes/views/pos/cart/tmpl-item-drawer.php old mode 100644 new mode 100755 diff --git a/includes/views/pos/cart/tmpl-item.php b/includes/views/pos/cart/tmpl-item.php old mode 100644 new mode 100755 index 444cb2b4..3092d88d --- a/includes/views/pos/cart/tmpl-item.php +++ b/includes/views/pos/cart/tmpl-item.php @@ -1,7 +1,7 @@ {{#if product}} diff --git a/includes/views/pos/cart/tmpl-panel.php b/includes/views/pos/cart/tmpl-panel.php old mode 100644 new mode 100755 diff --git a/includes/views/pos/cart/tmpl-totals.php b/includes/views/pos/cart/tmpl-totals.php old mode 100644 new mode 100755 index 8a64b6dd..d6430e30 --- a/includes/views/pos/cart/tmpl-totals.php +++ b/includes/views/pos/cart/tmpl-totals.php @@ -1,11 +1,11 @@+ | {{order_number}} | |||
---|---|---|---|---|
: | +: | {{{money subtotal}}} | ||
: | +: | {{{money cart_discount negative=true}}} | ||
{{title}}: | +{{name}}: | {{{money total}}} | ||
: | +: | {{{money order_discount negative=true}}} | ||
: | +: | {{{money total}}} |