<commit_before>import Webiny from 'Webiny';

let translations = {};

/**
 * This is responsible for replacing given text with given values
 * It will automatically detect if it needs to return a string or JSX based on given variables
 * (if all variables are strings, then final output will also be returned as string)
 * @param text
 * @param values
 * @returns {*}
 */
function replaceVariables(text, values) {
    if (_.isEmpty(values)) {
        return text;
    }

    // Let's first check if we need to return pure string or JSX
    let stringOutput = true;
    _.each(values, (value) => {
        if (!_.isString(value)) {
            stringOutput = false;
        }
    });

    const parts = text.split(/(\{.*?\})/);

    if (stringOutput) {
        let output = '';
        parts.forEach(part => {
            output += _.startsWith(part, '{') ? values[_.trim(part, '{}')] : part;
        });
        return output;
    }

    // Let's create a JSX output
    return parts.map((part, index) => {
        if (_.startsWith(part, '{')) {
            return <webiny-i18n-part key={index}>{values[_.trim(part, '{}')]}</webiny-i18n-part>;
        }
        return <webiny-i18n-part key={index}>{part}</webiny-i18n-part>;
    });
}

const i18n = function i18n(key, text, variables) {
    const output = i18n.getTranslation(key) || text;
    return replaceVariables(output, variables);
};

i18n.language = '';
i18n.api = null;

/**
 * Used for rendering text in DOM
 * @param key
 * @param label
 * @param variables
 * @param options
 * @returns {XML}
 */
i18n.render = function render(key, label, variables, options) {
    return <Webiny.Ui.Components.I18N placeholder={label} translationKey={key} variables={variables} options={options}/>;
};

// Following methods are plain-simple for now - let's make them smarter in the near future
i18n.price = function price(value, currency = '£') {
    const currencySymbols = {gbp: '£', usd: '$', eur: '€'}; // Plain simple for now
    return accounting.formatMoney(value, _.get(currencySymbols, currency, currency));
};

i18n.number = function price(value) {
    return accounting.formatNumber(value);
};

i18n.date = function date(value, format = 'DD/MMM/YY') {
    return moment(value).format(format);
};

i18n.time = function time(value, format = 'HH:mm') {
    return moment(value).format(format);
};

i18n.datetime = function datetime(value, format = 'DD/MMM/YY HH:mm') {
    return moment(value).format(format);
};

i18n.getTranslation = function getTranslation(key) {
    return translations[key] || '';
};

i18n.setTranslation = function setTranslation(key, translation) {
    translations[key] = translation;
    return this;
};

i18n.getTranslations = function getTranslations() {
    return translations;
};

i18n.hasTranslation = function hasTranslation(key) {
    return _.get(translations, key);
};

i18n.setApiEndpoint = function setApiEndpoint(api) {
    this.api = api;
    return this;
};

i18n.getLanguage = function getLanguage() {
    return this.language;
};

i18n.setLanguage = function setLanguage(language) {
    this.language = language;
    // TODO: Set moment / accounting language settings here

    // First let's get contents from cache
    if (localStorage[`Webiny.i18n.translations`]) {
        translations = JSON.parse(localStorage[`Webiny.i18n.translations`]);
    }

    // First we fetch all translations from server - we send a cache key
    return this.api.get('', {
        language: this.language,
        cacheKey: localStorage[`Webiny.i18n.cacheKey`]
    }).then(apiResponse => {
        if (_.isEmpty(apiResponse.getData('translations'))) {
            return apiResponse;
        }
        localStorage[`Webiny.i18n.language`] = this.language;
        localStorage[`Webiny.i18n.cacheKey`] = apiResponse.getData('cacheKey', null);
        localStorage[`Webiny.i18n.translations`] = JSON.stringify(apiResponse.getData('translations'));
        translations = _.assign(translations, apiResponse.getData('translations'));
        return apiResponse;
    });
};

export default i18n;<commit_msg>- setting cache key outside of i18n (still for discussion..)<commit_after>import Webiny from 'Webiny';

let translations = {};

/**
 * This is responsible for replacing given text with given values
 * It will automatically detect if it needs to return a string or JSX based on given variables
 * (if all variables are strings, then final output will also be returned as string)
 * @param text
 * @param values
 * @returns {*}
 */
function replaceVariables(text, values) {
    if (_.isEmpty(values)) {
        return text;
    }

    // Let's first check if we need to return pure string or JSX
    let stringOutput = true;
    _.each(values, (value) => {
        if (!_.isString(value)) {
            stringOutput = false;
        }
    });

    const parts = text.split(/(\{.*?\})/);

    if (stringOutput) {
        let output = '';
        parts.forEach(part => {
            output += _.startsWith(part, '{') ? values[_.trim(part, '{}')] : part;
        });
        return output;
    }

    // Let's create a JSX output
    return parts.map((part, index) => {
        if (_.startsWith(part, '{')) {
            return <webiny-i18n-part key={index}>{values[_.trim(part, '{}')]}</webiny-i18n-part>;
        }
        return <webiny-i18n-part key={index}>{part}</webiny-i18n-part>;
    });
}

const i18n = function i18n(key, text, variables) {
    const output = i18n.getTranslation(key) || text;
    return replaceVariables(output, variables);
};

i18n.language = '';
i18n.api = null;
i18n.cacheKey = null;

/**
 * Used for rendering text in DOM
 * @param key
 * @param label
 * @param variables
 * @param options
 * @returns {XML}
 */
i18n.render = function render(key, label, variables, options) {
    return <Webiny.Ui.Components.I18N placeholder={label} translationKey={key} variables={variables} options={options}/>;
};

// Following methods are plain-simple for now - let's make them smarter in the near future
i18n.price = function price(value, currency = '£') {
    const currencySymbols = {gbp: '£', usd: '$', eur: '€'}; // Plain simple for now
    return accounting.formatMoney(value, _.get(currencySymbols, currency, currency));
};

i18n.number = function price(value) {
    return accounting.formatNumber(value);
};

i18n.date = function date(value, format = 'DD/MMM/YY') {
    return moment(value).format(format);
};

i18n.time = function time(value, format = 'HH:mm') {
    return moment(value).format(format);
};

i18n.datetime = function datetime(value, format = 'DD/MMM/YY HH:mm') {
    return moment(value).format(format);
};

i18n.getTranslation = function getTranslation(key) {
    return translations[key] || '';
};

i18n.setTranslation = function setTranslation(key, translation) {
    translations[key] = translation;
    return this;
};

i18n.getTranslations = function getTranslations() {
    return translations;
};

i18n.hasTranslation = function hasTranslation(key) {
    return _.get(translations, key);
};

i18n.setApiEndpoint = function setApiEndpoint(api) {
    this.api = api;
    return this;
};

i18n.getLanguage = function getLanguage() {
    return this.language;
};

i18n.setCacheKey = function setCacheKey(cacheKey) {
    this.cacheKey = cacheKey;
    return this;
};

i18n.initialize = function setLanguage(language) {
    this.language = language;
    // TODO: Set moment / accounting language settings here

    // If we have the same cache key, that means we have latest translations - we can safely read from local storage.
    if (this.cacheKey === parseInt(localStorage[`Webiny.i18n.cacheKey`])) {
        translations = JSON.parse(localStorage[`Webiny.i18n.translations`]);
        return Promise.resolve();
    }

    // If we have a different cache key (or no cache key at all), we must fetch translations from server
    return this.api.get(null, {language: this.language}).then(apiResponse => {
        localStorage[`Webiny.i18n.language`] = this.language;
        localStorage[`Webiny.i18n.cacheKey`] = apiResponse.getData('cacheKey', null);
        localStorage[`Webiny.i18n.translations`] = JSON.stringify(apiResponse.getData('translations'));
        translations = _.assign(translations, apiResponse.getData('translations'));
        return apiResponse;
    });
};

export default i18n;<|endoftext|>


<commit_before>angular.module('conFusion.controllers', [])

.controller('AppCtrl', function ($scope, $ionicModal, $timeout, $localStorage, $ionicPlatform, $cordovaCamera) {

  // With the new view caching in Ionic, Controllers are only called
  // when they are recreated or on app start, instead of every page change.
  // To listen for when this page is active (for example, to refresh data),
  // listen for the $ionicView.enter event:
  //$scope.$on('$ionicView.enter', function(e) {
  //});

  // Form data for the login modal
  $scope.loginData = $localStorage.getObject('userinfo','{}');
  $scope.registration = {};

  // Create the registration modal that we will use later
    $ionicModal.fromTemplateUrl('templates/register.html', {
        scope: $scope
    }).then(function (modal) {
        $scope.registerform = modal;
    });

    // Triggered in the registration modal to close it
    $scope.closeRegister = function () {
        $scope.registerform.hide();
    };

    // Open the registration modal
    $scope.register = function () {
        $scope.registerform.show();
    };

    // Perform the registration action when the user submits the registration form
    $scope.doRegister = function () {
        console.log('Doing reservation', $scope.reservation);

        // Simulate a registration delay. Remove this and replace with your registration
        // code if using a registration system
        $timeout(function () {
            $scope.closeRegister();
        }, 1000);
    };

    $ionicPlatform.ready(function() {
        var options = {
            quality: 50,
            destinationType: Camera.DestinationType.DATA_URL,
            sourceType: Camera.PictureSourceType.CAMERA,
            allowEdit: true,
            encodingType: Camera.EncodingType.JPEG,
            targetWidth: 100,
            targetHeight: 100,
            popoverOptions: CameraPopoverOptions,
            saveToPhotoAlbum: false
        };
         $scope.takePicture = function() {
            $cordovaCamera.getPicture(options).then(function(imageData) {
                $scope.registration.imgSrc = "data:image/jpeg;base64," + imageData;
            }, function(err) {
                console.log(err);
            });

            $scope.registerform.show();

        };

        var optionsSelect = {
          quality: 50,
          destinationType: Camera.DestinationType.DATA_URL,
          sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
          allowEdit: true,
          encodingType: Camera.EncodingType.JPEG,
          targetWidth: 100,
          targetHeight: 100,
          popoverOptions: CameraPopoverOptions,
          saveToPhotoAlbum: false
        };
         $scope.selectPicture = function() {
            $cordovaCamera.getPicture(optionsSelect).then(function(imageData) {
                $scope.registration.imgSrc = "data:image/jpeg;base64," + imageData;
            }, function(err) {
                console.log(err);
            });

            $scope.registerform.show();

        };
    });

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  };

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    console.log('Doing login', $scope.loginData);
    $localStorage.storeObject('userinfo',$scope.loginData);

    // Simulate a login delay. Remove this and replace with your login
    // code if using a login system
    $timeout(function() {
      $scope.closeLogin();
    }, 1000);
  };

  // Create the reserve modal that we will use later
  $ionicModal.fromTemplateUrl('templates/reserve.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.reserveform = modal;
  });

  // Triggered in the reserve modal to close it
  $scope.closeReserve = function() {
    $scope.reserveform.hide();
  };

  // Open the reserve modal
  $scope.reserve = function() {
    $scope.reserveform.show();
  };

  // Perform the reserve action when the user submits the reserve form
  $scope.doReserve = function() {
    console.log('Doing reservation', $scope.reservation);

    // Simulate a reservation delay. Remove this and replace with your reservation
    // code if using a server system
    $timeout(function() {
      $scope.closeReserve();
    }, 1000);
  };
})

.controller('MenuController', ['$scope', 'menuFactory', 'favoriteFactory',
'dishes', 'baseURL', '$ionicListDelegate', '$ionicPlatform', '$cordovaLocalNotification', '$cordovaToast',
 function ($scope, menuFactory,
  favoriteFactory, dishes, baseURL, $ionicListDelegate, $ionicPlatform, $cordovaLocalNotification, $cordovaToast) {
    $scope.baseURL = baseURL;

    $scope.tab = 1;
    $scope.filtText = '';
    $scope.showDetails = false;
    $scope.showMenu = false;
    $scope.message = "Loading ...";

    /*menuFactory.query(
        function(response) {
            $scope.dishes = response;
            $scope.showMenu = true;
        },
        function(response) {
            $scope.message = "Error: "+response.status + " " + response.statusText;
        });
    */
    $scope.dishes = dishes

    $scope.select = function(setTab) {
        $scope.tab = setTab;

        if (setTab === 2) {
            $scope.filtText = "appetizer";
        }
        else if (setTab === 3) {
            $scope.filtText = "mains";
        }
        else if (setTab === 4) {
            $scope.filtText = "dessert";
        }
        else {
            $scope.filtText = "";
        }
    };

    $scope.isSelected = function (checkTab) {
        return ($scope.tab === checkTab);
    };

    $scope.toggleDetails = function() {
        $scope.showDetails = !$scope.showDetails;
    };

    $scope.addFavorite = function (index) {
        console.log("index is " + index);
        favoriteFactory.addToFavorites(index);
        $ionicListDelegate.closeOptionButtons();

        $ionicPlatform.ready(function () {
                $cordovaLocalNotification.schedule({
                    id: 1,
                    title: "Added Favorite",
                    text: $scope.dishes[index].name
                }).then(function () {
                    console.log('Added Favorite '+$scope.dishes[index].name);
                },
                function () {
                    console.log('Failed to add Notification ');
                });

                $cordovaToast
                  .show('Added Favorite '+$scope.dishes[index].name, 'long', 'center')
                  .then(function (success) {
                      // success
                  }, function (error) {
                      // error
                  });
        });
    }
}])

.controller('ContactController', ['$scope', function($scope) {

    $scope.feedback = {mychannel:"", firstName:"", lastName:"", agree:false, email:"" };

    var channels = [{value:"tel", label:"Tel."}, {value:"Email",label:"Email"}];

    $scope.channels = channels;
    $scope.invalidChannelSelection = false;

}])

.controller('FeedbackController', ['$scope', 'feedbackFactory', function($scope,feedbackFactory) {

    $scope.sendFeedback = function() {

        console.log($scope.feedback);

        if ($scope.feedback.agree && ($scope.feedback.mychannel == "")) {
            $scope.invalidChannelSelection = true;
            console.log('incorrect');
        }
        else {
            $scope.invalidChannelSelection = false;
            feedbackFactory.save($scope.feedback);
            $scope.feedback = {mychannel:"", firstName:"", lastName:"", agree:false, email:"" };
            $scope.feedback.mychannel="";
            $scope.feedbackForm.$setPristine();
            console.log($scope.feedback);
        }
    };
}])

.controller('DishDetailController', ['$scope', '$stateParams', 'dish',
'menuFactory', 'favoriteFactory', 'baseURL', '$ionicPopover', '$ionicModal', '$ionicPlatform', '$cordovaLocalNotification', '$cordovaToast',
function ($scope, $stateParams, dish, menuFactory, favoriteFactory, baseURL,
  $ionicPopover, $ionicModal, $ionicPlatform, $cordovaLocalNotification, $cordovaToast) {

    $scope.baseURL = baseURL;
    $scope.dish = dish;
    $scope.showDish = false;
    $scope.message="Loading ...";

    $scope.dish = menuFactory.get({id:parseInt($stateParams.id,10)})
    .$promise.then(
                    function(response){
                        $scope.dish = response;
                        $scope.showDish = true;
                    },
                    function(response) {
                        $scope.message = "Error: "+response.status + " " + response.statusText;
                    }
    );

    $scope.addFavorite = function (index) {
        favoriteFactory.addToFavorites($scope.dish.id);
        $scope.popover.hide();
        $ionicPlatform.ready(function () {
                $cordovaLocalNotification.schedule({
                    id: 1,
                    title: "Added Favorite",
                    text: $scope.dish.name
                }).then(function () {
                    console.log('Added Favorite '+$scope.dish.name);
                },
                function () {
                    console.log('Failed to add Notification ');
                });

                $cordovaToast
                  .show('Added Favorite '+$scope.dish.name, 'long', 'bottom')
                  .then(function (success) {
                      // success
                  }, function (error) {
                      // error
                  });
        });
    }

    $scope.commentData = {};
    $scope.mycomment = {rating:5, comment:"", author:"", date:""};

    $scope.doComment = function() {
      $scope.mycomment = $scope.commentData;
      $scope.mycomment.date = new Date().toISOString();

      $scope.dish.comments.push($scope.commentData);
      $scope.modal.hide();
    }

    $ionicPopover.fromTemplateUrl('templates/dish-detail-popover.html', {
      scope: $scope
    }).then(function(popover) {
      $scope.popover = popover;
    });

    $scope.openPopover = function($event) {
      $scope.popover.show($event);
    };
    $scope.closePopover = function() {
      $scope.popover.hide();
    };
    //Cleanup the popover when we're done with it!
    $scope.$on('$destroy', function() {
      $scope.popover.remove();
    });
    // Execute action on hide popover
    $scope.$on('popover.hidden', function() {
      // Execute action
    });
    // Execute action on remove popover
    $scope.$on('popover.removed', function() {
      // Execute action
    });

    $ionicModal.fromTemplateUrl('templates/dish-comment.html', {
      scope: $scope,
      animation: 'slide-in-up'
    }).then(function(modal) {
      $scope.modal = modal;
    });
    $scope.openModal = function() {
      $scope.modal.show();
      $scope.popover.hide();
    };
    $scope.closeModal = function() {
      $scope.modal.hide();
    };
    //Cleanup the modal when we're done with it!
    $scope.$on('$destroy', function() {
      $scope.modal.remove();
    });
    // Execute action on hide modal
    $scope.$on('modal.hidden', function() {
      // Execute action
    });
    // Execute action on remove modal
    $scope.$on('modal.removed', function() {
      // Execute action
    });

}])

.controller('DishCommentController', ['$scope', 'menuFactory', function($scope,menuFactory) {

    $scope.mycomment = {rating:5, comment:"", author:"", date:""};

    $scope.submitComment = function () {

        $scope.mycomment.date = new Date().toISOString();
        console.log($scope.mycomment);

        $scope.dish.comments.push($scope.mycomment);
        menuFactory.update({id:$scope.dish.id},$scope.dish);

        $scope.commentForm.$setPristine();

        $scope.mycomment = {rating:5, comment:"", author:"", date:""};
    }
}])

// implement the IndexController and About Controller here

.controller('IndexController', ['$scope', 'menuFactory', 'promotionFactory',
'corporateFactory', 'promotion', 'leader', 'dish', 'baseURL', function ($scope,
  menuFactory, promotionFactory, corporateFactory, promotion, leader,
  dish, baseURL) {

    $scope.baseURL = baseURL;
    //$scope.leader = corporateFactory.get({id: 3});
    $scope.leader = leader

    $scope.showDish = false;
    $scope.message = "Loading ...";

    /*$scope.dish = menuFactory.get({id: 0})
        .$promise.then(
            function (response) {
                $scope.dish = response;
                $scope.showDish = true;
            },
            function (response) {
                $scope.message = "Error: " + response.status + " " + response.statusText;
            }
        );
    */
    $scope.dish = dish;
    //$scope.promotion = promotionFactory.get({id: 0});
    $scope.promotion = promotion

}])

.controller('AboutController', ['$scope', 'corporateFactory', 'leaders', 'baseURL', function($scope, corporateFactory, leaders, baseURL) {

    $scope.baseURL = baseURL;
    $scope.leaders = leaders
    //$scope.leaders = corporateFactory.query();
    console.log($scope.leaders);

}])

.controller('FavoritesController', ['$scope', 'dishes', 'favorites', "menuFactory",
'favoriteFactory', 'baseURL', '$ionicListDelegate', '$ionicPopup',
'$ionicLoading', '$timeout', function ($scope, dishes, favorites, menuFactory,
  favoriteFactory, baseURL, $ionicListDelegate, $ionicPopup, $ionicLoading,
  $timeout) {
  $scope.baseURL = baseURL;
  $scope.shouldShowDelete = false;

  $scope.favorites = favorites;

  $scope.dishes = dishes;

    $ionicLoading.show({
        template: '<ion-spinner></ion-spinner> Loading...'
    });

    $scope.favorites = favoriteFactory.getFavorites();

    $scope.dishes = menuFactory.query(
      function (response) {
          $scope.dishes = response;
          $timeout(function () {
              $ionicLoading.hide();
          }, 1000);
      },
      function (response) {
          $scope.message = "Error: " + response.status + " " + response.statusText;
          $timeout(function () {
              $ionicLoading.hide();
          }, 1000);
    });

    console.log($scope.dishes, $scope.favorites);

    $scope.toggleDelete = function () {
        $scope.shouldShowDelete = !$scope.shouldShowDelete;
        console.log($scope.shouldShowDelete);
    }

    $scope.deleteFavorite = function (index) {
        var confirmPopup = $ionicPopup.confirm({
            title: 'Confirm Delete',
            template: 'Are you sure you want to delete this item?'
        });

        confirmPopup.then(function (res) {
            if (res) {
                console.log('Ok to delete');
                favoriteFactory.deleteFromFavorites(index);
            } else {
                console.log('Canceled delete');
            }
        });

        $scope.shouldShowDelete = false;

    }
}])

.filter('favoriteFilter', function () {
  return function (dishes, favorites) {
    var out = [];
    for (var i = 0; i < favorites.length; i++) {
      for (var j = 0; j < dishes.length; j++) {
        if (dishes[j].id === favorites[i].id)
            out.push(dishes[j]);
      }
    }
    return out;
}});

;
<commit_msg>adding vibrate when delete a fav<commit_after>angular.module('conFusion.controllers', [])

.controller('AppCtrl', function ($scope, $ionicModal, $timeout, $localStorage, $ionicPlatform, $cordovaCamera) {

  // With the new view caching in Ionic, Controllers are only called
  // when they are recreated or on app start, instead of every page change.
  // To listen for when this page is active (for example, to refresh data),
  // listen for the $ionicView.enter event:
  //$scope.$on('$ionicView.enter', function(e) {
  //});

  // Form data for the login modal
  $scope.loginData = $localStorage.getObject('userinfo','{}');
  $scope.registration = {};

  // Create the registration modal that we will use later
    $ionicModal.fromTemplateUrl('templates/register.html', {
        scope: $scope
    }).then(function (modal) {
        $scope.registerform = modal;
    });

    // Triggered in the registration modal to close it
    $scope.closeRegister = function () {
        $scope.registerform.hide();
    };

    // Open the registration modal
    $scope.register = function () {
        $scope.registerform.show();
    };

    // Perform the registration action when the user submits the registration form
    $scope.doRegister = function () {
        console.log('Doing reservation', $scope.reservation);

        // Simulate a registration delay. Remove this and replace with your registration
        // code if using a registration system
        $timeout(function () {
            $scope.closeRegister();
        }, 1000);
    };

    $ionicPlatform.ready(function() {
        var options = {
            quality: 50,
            destinationType: Camera.DestinationType.DATA_URL,
            sourceType: Camera.PictureSourceType.CAMERA,
            allowEdit: true,
            encodingType: Camera.EncodingType.JPEG,
            targetWidth: 100,
            targetHeight: 100,
            popoverOptions: CameraPopoverOptions,
            saveToPhotoAlbum: false
        };
         $scope.takePicture = function() {
            $cordovaCamera.getPicture(options).then(function(imageData) {
                $scope.registration.imgSrc = "data:image/jpeg;base64," + imageData;
            }, function(err) {
                console.log(err);
            });

            $scope.registerform.show();

        };

        var optionsSelect = {
          quality: 50,
          destinationType: Camera.DestinationType.DATA_URL,
          sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
          allowEdit: true,
          encodingType: Camera.EncodingType.JPEG,
          targetWidth: 100,
          targetHeight: 100,
          popoverOptions: CameraPopoverOptions,
          saveToPhotoAlbum: false
        };
         $scope.selectPicture = function() {
            $cordovaCamera.getPicture(optionsSelect).then(function(imageData) {
                $scope.registration.imgSrc = "data:image/jpeg;base64," + imageData;
            }, function(err) {
                console.log(err);
            });

            $scope.registerform.show();

        };
    });

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  };

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    console.log('Doing login', $scope.loginData);
    $localStorage.storeObject('userinfo',$scope.loginData);

    // Simulate a login delay. Remove this and replace with your login
    // code if using a login system
    $timeout(function() {
      $scope.closeLogin();
    }, 1000);
  };

  // Create the reserve modal that we will use later
  $ionicModal.fromTemplateUrl('templates/reserve.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.reserveform = modal;
  });

  // Triggered in the reserve modal to close it
  $scope.closeReserve = function() {
    $scope.reserveform.hide();
  };

  // Open the reserve modal
  $scope.reserve = function() {
    $scope.reserveform.show();
  };

  // Perform the reserve action when the user submits the reserve form
  $scope.doReserve = function() {
    console.log('Doing reservation', $scope.reservation);

    // Simulate a reservation delay. Remove this and replace with your reservation
    // code if using a server system
    $timeout(function() {
      $scope.closeReserve();
    }, 1000);
  };
})

.controller('MenuController', ['$scope', 'menuFactory', 'favoriteFactory',
'dishes', 'baseURL', '$ionicListDelegate', '$ionicPlatform', '$cordovaLocalNotification', '$cordovaToast',
 function ($scope, menuFactory,
  favoriteFactory, dishes, baseURL, $ionicListDelegate, $ionicPlatform, $cordovaLocalNotification, $cordovaToast) {
    $scope.baseURL = baseURL;

    $scope.tab = 1;
    $scope.filtText = '';
    $scope.showDetails = false;
    $scope.showMenu = false;
    $scope.message = "Loading ...";

    /*menuFactory.query(
        function(response) {
            $scope.dishes = response;
            $scope.showMenu = true;
        },
        function(response) {
            $scope.message = "Error: "+response.status + " " + response.statusText;
        });
    */
    $scope.dishes = dishes

    $scope.select = function(setTab) {
        $scope.tab = setTab;

        if (setTab === 2) {
            $scope.filtText = "appetizer";
        }
        else if (setTab === 3) {
            $scope.filtText = "mains";
        }
        else if (setTab === 4) {
            $scope.filtText = "dessert";
        }
        else {
            $scope.filtText = "";
        }
    };

    $scope.isSelected = function (checkTab) {
        return ($scope.tab === checkTab);
    };

    $scope.toggleDetails = function() {
        $scope.showDetails = !$scope.showDetails;
    };

    $scope.addFavorite = function (index) {
        console.log("index is " + index);
        favoriteFactory.addToFavorites(index);
        $ionicListDelegate.closeOptionButtons();

        $ionicPlatform.ready(function () {
                $cordovaLocalNotification.schedule({
                    id: 1,
                    title: "Added Favorite",
                    text: $scope.dishes[index].name
                }).then(function () {
                    console.log('Added Favorite '+$scope.dishes[index].name);
                },
                function () {
                    console.log('Failed to add Notification ');
                });

                $cordovaToast
                  .show('Added Favorite '+$scope.dishes[index].name, 'long', 'center')
                  .then(function (success) {
                      // success
                  }, function (error) {
                      // error
                  });
        });
    }
}])

.controller('ContactController', ['$scope', function($scope) {

    $scope.feedback = {mychannel:"", firstName:"", lastName:"", agree:false, email:"" };

    var channels = [{value:"tel", label:"Tel."}, {value:"Email",label:"Email"}];

    $scope.channels = channels;
    $scope.invalidChannelSelection = false;

}])

.controller('FeedbackController', ['$scope', 'feedbackFactory', function($scope,feedbackFactory) {

    $scope.sendFeedback = function() {

        console.log($scope.feedback);

        if ($scope.feedback.agree && ($scope.feedback.mychannel == "")) {
            $scope.invalidChannelSelection = true;
            console.log('incorrect');
        }
        else {
            $scope.invalidChannelSelection = false;
            feedbackFactory.save($scope.feedback);
            $scope.feedback = {mychannel:"", firstName:"", lastName:"", agree:false, email:"" };
            $scope.feedback.mychannel="";
            $scope.feedbackForm.$setPristine();
            console.log($scope.feedback);
        }
    };
}])

.controller('DishDetailController', ['$scope', '$stateParams', 'dish',
'menuFactory', 'favoriteFactory', 'baseURL', '$ionicPopover', '$ionicModal', '$ionicPlatform', '$cordovaLocalNotification', '$cordovaToast',
function ($scope, $stateParams, dish, menuFactory, favoriteFactory, baseURL,
  $ionicPopover, $ionicModal, $ionicPlatform, $cordovaLocalNotification, $cordovaToast) {

    $scope.baseURL = baseURL;
    $scope.dish = dish;
    $scope.showDish = false;
    $scope.message="Loading ...";

    $scope.dish = menuFactory.get({id:parseInt($stateParams.id,10)})
    .$promise.then(
                    function(response){
                        $scope.dish = response;
                        $scope.showDish = true;
                    },
                    function(response) {
                        $scope.message = "Error: "+response.status + " " + response.statusText;
                    }
    );

    $scope.addFavorite = function (index) {
        favoriteFactory.addToFavorites($scope.dish.id);
        $scope.popover.hide();
        $ionicPlatform.ready(function () {
                $cordovaLocalNotification.schedule({
                    id: 1,
                    title: "Added Favorite",
                    text: $scope.dish.name
                }).then(function () {
                    console.log('Added Favorite '+$scope.dish.name);
                },
                function () {
                    console.log('Failed to add Notification ');
                });

                $cordovaToast
                  .show('Added Favorite '+$scope.dish.name, 'long', 'bottom')
                  .then(function (success) {
                      // success
                  }, function (error) {
                      // error
                  });
        });
    }

    $scope.commentData = {};
    $scope.mycomment = {rating:5, comment:"", author:"", date:""};

    $scope.doComment = function() {
      $scope.mycomment = $scope.commentData;
      $scope.mycomment.date = new Date().toISOString();

      $scope.dish.comments.push($scope.commentData);
      $scope.modal.hide();
    }

    $ionicPopover.fromTemplateUrl('templates/dish-detail-popover.html', {
      scope: $scope
    }).then(function(popover) {
      $scope.popover = popover;
    });

    $scope.openPopover = function($event) {
      $scope.popover.show($event);
    };
    $scope.closePopover = function() {
      $scope.popover.hide();
    };
    //Cleanup the popover when we're done with it!
    $scope.$on('$destroy', function() {
      $scope.popover.remove();
    });
    // Execute action on hide popover
    $scope.$on('popover.hidden', function() {
      // Execute action
    });
    // Execute action on remove popover
    $scope.$on('popover.removed', function() {
      // Execute action
    });

    $ionicModal.fromTemplateUrl('templates/dish-comment.html', {
      scope: $scope,
      animation: 'slide-in-up'
    }).then(function(modal) {
      $scope.modal = modal;
    });
    $scope.openModal = function() {
      $scope.modal.show();
      $scope.popover.hide();
    };
    $scope.closeModal = function() {
      $scope.modal.hide();
    };
    //Cleanup the modal when we're done with it!
    $scope.$on('$destroy', function() {
      $scope.modal.remove();
    });
    // Execute action on hide modal
    $scope.$on('modal.hidden', function() {
      // Execute action
    });
    // Execute action on remove modal
    $scope.$on('modal.removed', function() {
      // Execute action
    });

}])

.controller('DishCommentController', ['$scope', 'menuFactory', function($scope,menuFactory) {

    $scope.mycomment = {rating:5, comment:"", author:"", date:""};

    $scope.submitComment = function () {

        $scope.mycomment.date = new Date().toISOString();
        console.log($scope.mycomment);

        $scope.dish.comments.push($scope.mycomment);
        menuFactory.update({id:$scope.dish.id},$scope.dish);

        $scope.commentForm.$setPristine();

        $scope.mycomment = {rating:5, comment:"", author:"", date:""};
    }
}])

// implement the IndexController and About Controller here

.controller('IndexController', ['$scope', 'menuFactory', 'promotionFactory',
'corporateFactory', 'promotion', 'leader', 'dish', 'baseURL', function ($scope,
  menuFactory, promotionFactory, corporateFactory, promotion, leader,
  dish, baseURL) {

    $scope.baseURL = baseURL;
    //$scope.leader = corporateFactory.get({id: 3});
    $scope.leader = leader

    $scope.showDish = false;
    $scope.message = "Loading ...";

    /*$scope.dish = menuFactory.get({id: 0})
        .$promise.then(
            function (response) {
                $scope.dish = response;
                $scope.showDish = true;
            },
            function (response) {
                $scope.message = "Error: " + response.status + " " + response.statusText;
            }
        );
    */
    $scope.dish = dish;
    //$scope.promotion = promotionFactory.get({id: 0});
    $scope.promotion = promotion

}])

.controller('AboutController', ['$scope', 'corporateFactory', 'leaders', 'baseURL', function($scope, corporateFactory, leaders, baseURL) {

    $scope.baseURL = baseURL;
    $scope.leaders = leaders
    //$scope.leaders = corporateFactory.query();
    console.log($scope.leaders);

}])

.controller('FavoritesController', ['$scope', 'dishes', 'favorites', "menuFactory",
'favoriteFactory', 'baseURL', '$ionicListDelegate', '$ionicPopup',
'$ionicLoading', '$timeout', '$cordovaVibration', function ($scope, dishes, favorites, menuFactory,
  favoriteFactory, baseURL, $ionicListDelegate, $ionicPopup, $ionicLoading,
  $timeout, $cordovaVibration) {
  $scope.baseURL = baseURL;
  $scope.shouldShowDelete = false;

  $scope.favorites = favorites;

  $scope.dishes = dishes;

    $ionicLoading.show({
        template: '<ion-spinner></ion-spinner> Loading...'
    });

    $scope.favorites = favoriteFactory.getFavorites();

    $scope.dishes = menuFactory.query(
      function (response) {
          $scope.dishes = response;
          $timeout(function () {
              $ionicLoading.hide();
          }, 1000);
      },
      function (response) {
          $scope.message = "Error: " + response.status + " " + response.statusText;
          $timeout(function () {
              $ionicLoading.hide();
          }, 1000);
    });

    console.log($scope.dishes, $scope.favorites);

    $scope.toggleDelete = function () {
        $scope.shouldShowDelete = !$scope.shouldShowDelete;
        console.log($scope.shouldShowDelete);
    }

    $scope.deleteFavorite = function (index) {
        var confirmPopup = $ionicPopup.confirm({
            title: 'Confirm Delete',
            template: 'Are you sure you want to delete this item?'
        });

        confirmPopup.then(function (res) {
            if (res) {
                console.log('Ok to delete');
                favoriteFactory.deleteFromFavorites(index);
                $cordovaVibration.vibrate(100);
            } else {
                console.log('Canceled delete');
            }
        });

        $scope.shouldShowDelete = false;

    }
}])

.filter('favoriteFilter', function () {
  return function (dishes, favorites) {
    var out = [];
    for (var i = 0; i < favorites.length; i++) {
      for (var j = 0; j < dishes.length; j++) {
        if (dishes[j].id === favorites[i].id)
            out.push(dishes[j]);
      }
    }
    return out;
}});

;
<|endoftext|>


<commit_before>#!/usr/bin/env node
var app=require("express")(),
    http=require("http").Server(app),
    io=require("socket.io")(http),
    child_process=require("child_process"),
    shlex=require("shell-quote").parse;

var HTTPPORT=8012;

var conn=null,proc=null,aicmd=null,aibuf=null,ailines=[],ailineslisteners=[];

function resetai(){
	console.log("AI_STOP\n");
	if(proc)proc.kill("SIGTERM");
	proc=null;
	aicmd=null;
	aibuf=null;
	ailines=[];
	ailineslisteners=[];
}

app.get('/style.css', function(req, res) {
	res.sendFile(__dirname + "/style.css");
});
app.get('/client.js', function(req, res) {
	res.sendFile(__dirname + "/client.js");
});

app.get("/",function(req,res){
	res.sendFile(__dirname+"/index.html");
});

io.on("connection",function(_conn){
	if(conn!=null){
		_conn.emit("alert","Another connection already active!");
		_conn.emit("jseval","window.close();");
		_conn.disconnect(true);
		return;
	}
	console.log("(connect)");
	conn=_conn;
	conn.on("disconnect",function(){
		console.log("(disconnect)");
		conn.disconnect(); //just to be sure
		conn=null;
		resetai();
	});
	conn.on("aistart",function(cmd){
		resetai();
		aicmd=cmd;
		var lexed=shlex(cmd);
		proc=child_process.spawn(lexed[0],lexed.slice(1),{stdio:["pipe","pipe","inherit"]});
		console.log("AI_START");
		proc.on("error",function(err){
			if(err){
				if(conn)conn.emit("alert",err.message);
				console.log(err);
				resetai();
			}
		});
		proc.stdout.on("data",function(data){
			console.log("AI_OUT: "+String(data).replace(/\n$/,""));
			var idx;
			aibuf+=data;
			idx=aibuf.indexOf("\n");
			while(idx!=-1){
				ailines.push(aibuf.slice(0,idx));
				aibuf=aibuf.slice(idx+1);
				idx=aibuf.indexOf("\n");
			}
			while(ailines.length&&ailineslisteners.length){
				ailineslisteners.shift()(ailines.shift());
			}
		});
		aibuf="";
	});
	conn.on("aistop",function(){
		resetai();
	});
	conn.on("aiwriteln",function(text){
		console.log("AI_IN: "+text);
		proc.stdin.write(text+"\n");
	});
	conn.on("aigetline",function(){
		var line;
		if(ailines.length){
			line=ailines.shift();
			conn.emit("ailine",line);
			console.log(" sent: "+line);
		} else ailineslisteners.push(function(line){
			conn.emit("ailine",line);
			console.log(" sent: "+line);
		});
	});
	conn.on("aistatus",function(){
		if(proc==null)conn.emit("aistatus","Not running");
		else conn.emit("aistatus","Running: "+aicmd);
	});
});

http.listen(HTTPPORT,function(){
	console.log("Listening on http://localhost:"+HTTPPORT);
});
<commit_msg>Update index.js<commit_after>#!/usr/bin/env node
var app=require("express")(),
    http=require("http").Server(app),
    io=require("socket.io")(http),
    child_process=require("child_process"),
    shlex=require("shell-quote").parse;

var HTTPPORT=8012;

var conn=null,ai=new AI(),ai2=new AI();

function AI(){
	var proc=null;
	var cmd=null;
	var buf=null;
	var lines=[];
	var lineslisteners=[];

	this.reset=function(){
		console.log("AI_STOP\n");
		if(proc)proc.kill("SIGTERM");
		proc=null;
		cmd=null;
		buf=null;
		lines=[];
		lineslisteners=[];
	}

	this.start=function(command){
		this.reset();
		cmd=command;
		var lexed=shlex(cmd);
		console.log( process.env.PATH );
		console.log("starting");
		proc=child_process.spawn(lexed[0],lexed.slice(1),{stdio:["pipe","pipe","inherit"]});
		console.log("AI_START");
		var self=this;
		proc.on("error",function(err){
			if(err){
				if(conn)conn.emit("alert",err.message);
				console.log(err);
				self.reset();
				return;
			}
		});
		proc.stdout.on("data",function(data){
			console.log("AI_OUT: "+String(data).replace(/\n$/,""));
			var idx;
			buf+=data;
			idx=buf.indexOf("\n");
			while(idx!=-1){
				lines.push(buf.slice(0,idx));
				buf=buf.slice(idx+1);
				idx=buf.indexOf("\n");
			}
			while(lines.length&&lineslisteners.length){
				lineslisteners.shift()(lines.shift());
			}
		});
		buf="";
	}

	this.writeln=function(text){
		console.log("AI_IN: "+text);
		proc.stdin.write(text+"\n");
	}

	this.getline=function(){
		var line;
		if(lines.length){
			line=lines.shift();
			conn.emit("ailine",line);
			console.log(" sent: "+line);
		} else lineslisteners.push(function(line){
			conn.emit("ailine",line);
			console.log(" sent: "+line);
		});
	}

	this.status=function(){
		if(proc==null)conn.emit("aistatus","Not running");
		else conn.emit("aistatus","Running: "+cmd);
	}
}

app.get('/style.css', function(req, res) {
	res.sendFile(__dirname + "/style.css");
});
app.get('/client.js', function(req, res) {
	res.sendFile(__dirname + "/client.js");
});

app.get("/",function(req,res){
	res.sendFile(__dirname+"/index.html");
});
var aiVsAi=false;
var turn=0;
io.on("connection",function(_conn){
	if(conn!=null){
		_conn.emit("alert","Another connection already active!");
		_conn.emit("jseval","window.close();");
		_conn.disconnect(true);
		return;
	}
	console.log("(connect)");
	conn=_conn;
	conn.on("disconnect",function(){
		console.log("(disconnect)");
		conn.disconnect(); //just to be sure
		conn=null;
		ai.reset();
		if(aiVsAi)ai2.reset();
	});
	conn.on("aistart2",function(cmd,cmd2){
		ai.start(cmd);
		ai2.start(cmd2);
		aiVsAi=true;
		turn=0;
	});
	conn.on("aistart",function(cmd){
		if(aiVsAi)ai.reset();
		ai.start(cmd);
		aiVsAi=false;
	});
	conn.on("aistop",function(){
		ai.reset();
		if(aiVsAi)ai2.reset();
	});
	conn.on("aiwriteln",function(text){
		if(!aiVsAi)ai.writeln(text);
		else{
			if(turn==0)ai.writeln(text);
			else ai2.writeln(text);
		}
	});
	conn.on("aigetline",function(){
		if(aiVsAi){
			if(turn==0)ai.getline();
			else ai2.getline();
			turn=!turn;
		}else{
			ai.getline();
		}
	});
	conn.on("aistatus",function(){
		ai.status();
	});
});

http.listen(HTTPPORT,function(){
	console.log("Listening on http://localhost:"+HTTPPORT);
});
<|endoftext|>


<commit_before>import React from 'react'
import BABYLON from 'babylonjs'

var BabylonScene = React.createClass({
  propTypes: {
    setCanvasCallbacks: React.PropTypes.func.isRequired,
    pointerEventHandler: React.PropTypes.func.isRequired,
    useVrCamera: React.PropTypes.bool.isRequired
  },

  canvas3d: null,
  canvas2d: null,
  dynamicTexture: null,
  engine: null,
  scene: null,
  guiMesh: null,
  camera: null,
  pointerX: 0,
  pointerY: 0,
  isShiftPressed: false,
  pointerMovedWithShiftPressed: false,

  componentDidMount: function () {
    var self = this
    this.props.setCanvasCallbacks(
      (canvas2d) => {
        self.setup(canvas2d)
      },
      () => {
        self.updateDynamicTexture()
      }
    )
  },

  setup: function (canvas2d) {
    var canvas3d = this.canvas3d
    var engine = new BABYLON.Engine(canvas3d, true)
    this.engine = engine

    this.canvas2d = canvas2d

    // create a basic BJS Scene object
    var scene = new BABYLON.Scene(engine)
    this.scene = scene

    // create a FreeCamera, and set its position to (x:0, y:5, z:-10)
    var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene)
    this.camera = camera
    // target the camera to scene origin
    camera.setTarget(BABYLON.Vector3.Zero())
    // attach the camera to the canvas
    camera.attachControl(canvas3d, true)

    // create a basic light, aiming 0,1,0 - meaning, to the sky
    var light1 = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene)
    light1.diffuse = new BABYLON.Color3(1, 1, 1)
    light1.specular = new BABYLON.Color3(1, 1, 1)
    light1.groundColor = new BABYLON.Color3(0, 0, 0)

    // create skybox
    var skybox = BABYLON.Mesh.CreateBox('skyBox', 100.0, scene)
    skybox.renderingGroupId = 0
    var skyboxMaterial = new BABYLON.StandardMaterial('skyBox', scene)
    skyboxMaterial.backFaceCulling = false
    skyboxMaterial.disableLighting = true
    skybox.material = skyboxMaterial
    skybox.infiniteDistance = true
    skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0)
    skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0)
    skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture('static/textures/skybox', scene)
    skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE

    // create a built-in "sphere" shape; its constructor takes 5 params: name, width, depth, subdivisions, scene
    var sphere = BABYLON.Mesh.CreateSphere('sphere1', 16, 2, scene)
    var sphereMat = new BABYLON.StandardMaterial('sphereMat', scene)
    sphereMat.alpha = 1
    sphereMat.diffuseTexture = new BABYLON.Texture('static/textures/moonmap1k.jpg', scene)
    sphereMat.specularColor = new BABYLON.Color3(0, 0, 0)
    sphere.material = sphereMat
    sphere.renderingGroupId = 1

    // create a built-in "ground" shape; its constructor takes the same 5 params as the sphere's one
    var ground = BABYLON.Mesh.CreateGround('ground1', 6, 6, 2, scene)
    this.guiMesh = ground
    ground.renderingGroupId = 1
    var mat = new BABYLON.StandardMaterial('mat1', scene)
    mat.alpha = 1.0
    mat.emissiveColor = new BABYLON.Color3(0.4, 0.4, 0.4)

    var texture = new BABYLON.DynamicTexture('texture1', canvas2d, scene)
    this.dynamicTexture = texture
    mat.diffuseTexture = texture
    mat.diffuseTexture.hasAlpha = true
    ground.material = mat

    scene.onPointerObservable.add((e) => {
      if (e.type === BABYLON.PointerEventTypes.POINTERMOVE) {
        let px = e.event.layerX
        let py = e.event.layerY
        let picked = this.scene.pick(px, py, (m) => { return m === this.guiMesh }, false, this.camera)
        if (picked.hit && picked.pickedMesh === this.guiMesh) {
          let point2d = picked.getTextureCoordinates()
          let x2d = point2d.x * canvas2d.width
          let y2d = (1 - point2d.y) * canvas2d.height
          this.pointerX = x2d
          this.pointerY = y2d
          this.props.pointerEventHandler({
            type: 'pointermove3d',
            x: x2d,
            y: y2d,
            buttons: this.isShiftPressed ? 1 : 0
          })
          e.event.preventDefault()
          // camera.inputs.attached.mouse.detachControl()
        } else {
          // camera.inputs.attached.mouse.attachControl()
        }
      }
    })

    function animatePositions () {
      var t = Date.now()
      var p5 = 2 * Math.PI * (t % 5000) / 5000
      var p20 = 2 * Math.PI * (t % 20000) / 20000
      ground.rotation.x = -((Math.PI / 2) * 0.9)
      ground.rotation.x += Math.sin(p5) * 0.1
      ground.rotation.z = Math.sin(p20) * 0.05

      sphere.rotation.x = Math.PI / 2
      sphere.rotation.y = p5
      sphere.position.x = 4 * Math.sin(p20)
      sphere.position.y = 1 + -2 * Math.cos(p20)
      sphere.position.z = -4 * Math.cos(p20)
    }

    engine.runRenderLoop(function () {
      animatePositions()
      scene.render()
    })
    window.addEventListener('resize', function () {
      engine.resize()
    })
  },

  updateDynamicTexture: function () {
    if (this.dynamicTexture !== null) {
      this.dynamicTexture.update()
    }
  },

  onCanvas3d: function (c) {
    c.addEventListener('mouseover', (e) => {
      this.focus()
    })
    c.addEventListener('mouseout', (e) => {
      this.blur()
    })
    this.canvas3d = c
  },

  keyPressHandler: function (e) {
    let {dispatch} = this.props
    this.isShiftPressed = e.shiftKey
    if (e.keyCode === 13) {
      dispatch('addCurrent')
    } else if (e.keyCode === 8) {
      dispatch('removeLastTextCharacter')
      e.preventDefault()
      e.stopPropagation()
      return false
    } else if (e.key === 'Shift') {
      this.props.pointerEventHandler({
        type: 'pointerpick3d',
        x: this.pointerX,
        y: this.pointerY,
        buttons: 1
      })
    } else if (e.key.length === 1) {
      dispatch('appendText', e.key)
    }
  },
  focus: function () {
    document.body.addEventListener('keydown', this.keyPressHandler)
  },
  blur: function () {
    document.body.removeEventListener('keydown', this.keyPressHandler)
  },

  render: function () {
    return (
      <canvas width={1400} height={450} ref={this.onCanvas3d} />
    )
  }
})

module.exports = BabylonScene
<commit_msg>Try different cameras.<commit_after>import React from 'react'
import BABYLON from 'babylonjs'

var BabylonScene = React.createClass({
  propTypes: {
    setCanvasCallbacks: React.PropTypes.func.isRequired,
    pointerEventHandler: React.PropTypes.func.isRequired,
    useVrCamera: React.PropTypes.bool.isRequired
  },

  canvas3d: null,
  canvas2d: null,
  dynamicTexture: null,
  engine: null,
  scene: null,
  guiMesh: null,
  camera: null,
  pointerX: 0,
  pointerY: 0,
  isShiftPressed: false,
  pointerMovedWithShiftPressed: false,

  componentDidMount: function () {
    var self = this
    this.props.setCanvasCallbacks(
      (canvas2d) => {
        self.setup(canvas2d)
      },
      () => {
        self.updateDynamicTexture()
      }
    )
  },

  setup: function (canvas2d) {
    var canvas3d = this.canvas3d
    var engine = new BABYLON.Engine(canvas3d, true)
    this.engine = engine

    this.canvas2d = canvas2d

    // create a basic BJS Scene object
    var scene = new BABYLON.Scene(engine)
    this.scene = scene

    // create a camera (use a FreeCamera, ArcRotateCamera or WebVRFreeCamera)
    // var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene)
    var camera = new BABYLON.ArcRotateCamera('camera1', 0, 0, 0, new BABYLON.Vector3(0, 0, 0), scene)
    camera.setPosition(new BABYLON.Vector3(0, -1, -10))
    // var camera = new BABYLON.WebVRFreeCamera('camera1', new BABYLON.Vector3(0, -1, -10), scene)
    this.camera = camera
    // target the camera to scene origin
    camera.setTarget(BABYLON.Vector3.Zero())
    // attach the camera to the canvas
    camera.attachControl(canvas3d, true)

    // create a basic light, aiming 0,1,0 - meaning, to the sky
    var light1 = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene)
    light1.diffuse = new BABYLON.Color3(1, 1, 1)
    light1.specular = new BABYLON.Color3(1, 1, 1)
    light1.groundColor = new BABYLON.Color3(0, 0, 0)

    // create skybox
    var skybox = BABYLON.Mesh.CreateBox('skyBox', 100.0, scene)
    skybox.renderingGroupId = 0
    var skyboxMaterial = new BABYLON.StandardMaterial('skyBox', scene)
    skyboxMaterial.backFaceCulling = false
    skyboxMaterial.disableLighting = true
    skybox.material = skyboxMaterial
    skybox.infiniteDistance = true
    skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0)
    skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0)
    skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture('static/textures/skybox', scene)
    skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE

    // create a built-in "sphere" shape; its constructor takes 5 params: name, width, depth, subdivisions, scene
    var sphere = BABYLON.Mesh.CreateSphere('sphere1', 16, 2, scene)
    var sphereMat = new BABYLON.StandardMaterial('sphereMat', scene)
    sphereMat.alpha = 1
    sphereMat.diffuseTexture = new BABYLON.Texture('static/textures/moonmap1k.jpg', scene)
    sphereMat.specularColor = new BABYLON.Color3(0, 0, 0)
    sphere.material = sphereMat
    sphere.renderingGroupId = 1

    // create a built-in "ground" shape; its constructor takes the same 5 params as the sphere's one
    var ground = BABYLON.Mesh.CreateGround('ground1', 6, 6, 2, scene)
    this.guiMesh = ground
    ground.renderingGroupId = 1
    var mat = new BABYLON.StandardMaterial('mat1', scene)
    mat.alpha = 1.0
    mat.emissiveColor = new BABYLON.Color3(0.4, 0.4, 0.4)

    var texture = new BABYLON.DynamicTexture('texture1', canvas2d, scene)
    this.dynamicTexture = texture
    mat.diffuseTexture = texture
    mat.diffuseTexture.hasAlpha = true
    ground.material = mat

    scene.onPointerObservable.add((e) => {
      if (e.type === BABYLON.PointerEventTypes.POINTERMOVE) {
        let px = e.event.layerX
        let py = e.event.layerY
        let picked = this.scene.pick(px, py, (m) => { return m === this.guiMesh }, false, this.camera)
        if (picked.hit && picked.pickedMesh === this.guiMesh) {
          let point2d = picked.getTextureCoordinates()
          let x2d = point2d.x * canvas2d.width
          let y2d = (1 - point2d.y) * canvas2d.height
          this.pointerX = x2d
          this.pointerY = y2d
          this.props.pointerEventHandler({
            type: 'pointermove3d',
            x: x2d,
            y: y2d,
            buttons: this.isShiftPressed ? 1 : 0
          })
          e.event.preventDefault()
          // camera.inputs.attached.mouse.detachControl()
        } else {
          // camera.inputs.attached.mouse.attachControl()
        }
      }
    })

    function animatePositions () {
      var t = Date.now()
      var p5 = 2 * Math.PI * (t % 5000) / 5000
      var p20 = 2 * Math.PI * (t % 20000) / 20000
      ground.rotation.x = -((Math.PI / 2) * 0.9)
      ground.rotation.x += Math.sin(p5) * 0.1
      ground.rotation.z = Math.sin(p20) * 0.05

      sphere.rotation.x = Math.PI / 2
      sphere.rotation.y = p5
      sphere.position.x = 4 * Math.sin(p20)
      sphere.position.y = 1 + -2 * Math.cos(p20)
      sphere.position.z = -4 * Math.cos(p20)
    }

    engine.runRenderLoop(function () {
      animatePositions()
      scene.render()
    })
    window.addEventListener('resize', function () {
      engine.resize()
    })
  },

  updateDynamicTexture: function () {
    if (this.dynamicTexture !== null) {
      this.dynamicTexture.update()
    }
  },

  onCanvas3d: function (c) {
    c.addEventListener('mouseover', (e) => {
      this.focus()
    })
    c.addEventListener('mouseout', (e) => {
      this.blur()
    })
    this.canvas3d = c
  },

  keyPressHandler: function (e) {
    let {dispatch} = this.props
    this.isShiftPressed = e.shiftKey
    if (e.keyCode === 13) {
      dispatch('addCurrent')
    } else if (e.keyCode === 8) {
      dispatch('removeLastTextCharacter')
      e.preventDefault()
      e.stopPropagation()
      return false
    } else if (e.key === 'Shift') {
      this.props.pointerEventHandler({
        type: 'pointerpick3d',
        x: this.pointerX,
        y: this.pointerY,
        buttons: 1
      })
    } else if (e.key.length === 1) {
      dispatch('appendText', e.key)
    }
  },
  focus: function () {
    document.body.addEventListener('keydown', this.keyPressHandler)
  },
  blur: function () {
    document.body.removeEventListener('keydown', this.keyPressHandler)
  },

  render: function () {
    return (
      <canvas width={1400} height={450} ref={this.onCanvas3d} />
    )
  }
})

module.exports = BabylonScene
<|endoftext|>


<commit_before>"use strict";

var ManifestValidator = (function() {

  var _json_input = {};
  var _manifest = {};
  var _logs = [];

  var ALLOWED_DISPLAY_VALUES = [ 'fullscreen',
                                 'standalone',
                                 'minimal-ui',
                                 'browser' ];

  var ALLOWED_ORIENTATION_VALUES = [ 'any',
                                     'natural',
                                     'landscape',
                                     'portrait',
                                     'portrait-primary',
                                     'portrait-secondary',
                                     'landscape-primary',
                                     'landscape-secondary' ];

  function _parseString(args) {
    var property = args.property;
    if (!(property in _json_input))
      return undefined;

    if (typeof _json_input[property] != 'string') {
      _logs.push('ERROR: "' + property + '" expected to be a string but is not.');
      return undefined;
    }

    if (args.trim)
      return _json_input[property].trim();
    return _json_input[property];
  }

  function _parseBoolean(args) {
    var property = args.property;
    var defaultValue = args.defaultValue;
    if (!(property in _json_input))
      return defaultValue;

    if (typeof _json_input[property] != 'boolean') {
      _logs.push('ERROR: "' + property + '" expected to be a boolean but is not.');
      return defaultValue;
    }

    return _json_input[property];
  }

  function _parseColor(property) {
    if (!(property in _json_input))
      return undefined;

    if (typeof _json_input[property] != 'string') {
      _logs.push('ERROR: "' + property + '" expected to be a string but is not.');
      return undefined;
    }

    // If style.color changes when set to the given color, it is valid. Testing
    // against 'white' and 'black' in case of the given color is one of them.
    var dummy = document.createElement('div');
    dummy.style.color = 'white';
    dummy.style.color = _json_input[property];
    if (dummy.style.color != 'white')
      return _json_input[property];
    dummy.style.color = 'black';
    dummy.style.color = _json_input[property];
    if (dummy.style.color != 'black')
      return _json_input[property];
    return undefined;
  }

  function _parseName() {
    return _parseString({ property: 'name', trim: true });
  }

  function _parseShortName() {
    return _parseString({ property: 'short_name', trim: true });
  }

  function _parseStartUrl() {
    // TODO: parse url using manifest_url as a base (missing).
    return _parseString({ property: 'start_url', trim: false });
  }

  function _parseDisplay() {
    var display = _parseString({ property: 'display', trim: true });
    if (display === undefined)
      return display;

    if (ALLOWED_DISPLAY_VALUES.indexOf(display.toLowerCase()) == -1) {
      _logs.push('ERROR: "display" has an invalid value, will be ignored.');
      return undefined;
    }

    return display;
  }

  function _parseOrientation() {
    var orientation = _parseString({ property: 'orientation', trim: true });
    if (orientation === undefined)
      return orientation;

    if (ALLOWED_ORIENTATION_VALUES.indexOf(orientation.toLowerCase()) == -1) {
      _logs.push('ERROR: "orientation" has an invalid value, will be ignored.');
      return undefined;
    }

    return orientation;
  }

  function _parseRelatedApplications() {
    var property = 'related_applications';
    if (!(property in _json_input))
      return [];

    if (!Array.isArray(_json_input.property)) {
      _logs.push('ERROR: "' + property + '" expected to be an array but is not.');
      return [];
    }

    // TODO: finish

    return [];
  }

  function _parsePreferRelatedApplications() {
    return _parseBoolean({ property: 'prefer_related_applications', defaultValue: false });
  }

  function _parseThemeColor() {
    return _parseColor('theme_color');
  }

  function _parseBackgroundColor() {
    return _parseColor('background_color');
  }

  function _check(string) {
    try {
      _json_input = JSON.parse(string);
    } catch (e) {
      _logs.push("File isn't valid JSON: " + e);
      return [ false, _logs ];
    }

    _logs.push("JSON parsed successfuly.");

    _manifest.name = _parseName();
    _manifest.short_name = _parseShortName();
    _manifest.start_url= _parseStartUrl();
    _manifest.display = _parseDisplay();
    _manifest.orientation = _parseOrientation();

    // TODO: parse icons

    // TODO: finish related_applications
    _manifest.related_applications = _parseRelatedApplications();
    _manifest.prefer_related_applications = _parsePreferRelatedApplications();
    _manifest.theme_color = _parseThemeColor();
    _manifest.background_color = _parseBackgroundColor();

    _logs.push('Parsed `name` property is: ' + _manifest.name);
    _logs.push('Parsed `short_name` property is: ' + _manifest.short_name);
    _logs.push('Parsed `start_url` property is: ' + _manifest.start_url);
    _logs.push('Parsed `display` property is: ' + _manifest.display);
    _logs.push('Parsed `orientation` property is: ' + _manifest.orientation);
    _logs.push('Parsed `related_applications` property is: ' + _manifest.related_applications);
    _logs.push('Parsed `prefer_related_applications` property is: ' + _manifest.prefer_related_applications);
    _logs.push('Parsed `theme_color` property is: ' + _manifest.theme_color);
    _logs.push('Parsed `background_color` property is: ' + _manifest.background_color);

    return [ true, _logs ];
  }

  return {
    check: _check,
  };
})();
<commit_msg>Finish related_applications implementation.<commit_after>"use strict";

var ManifestValidator = (function() {

  var _json_input = {};
  var _manifest = {};
  var _logs = [];

  var ALLOWED_DISPLAY_VALUES = [ 'fullscreen',
                                 'standalone',
                                 'minimal-ui',
                                 'browser' ];

  var ALLOWED_ORIENTATION_VALUES = [ 'any',
                                     'natural',
                                     'landscape',
                                     'portrait',
                                     'portrait-primary',
                                     'portrait-secondary',
                                     'landscape-primary',
                                     'landscape-secondary' ];

  function _parseString(args) {
    var object = args.object;
    var property = args.property;
    if (!(property in object))
      return undefined;

    if (typeof object[property] != 'string') {
      _logs.push('ERROR: "' + property + '" expected to be a string but is not.');
      return undefined;
    }

    if (args.trim)
      return object[property].trim();
    return object[property];
  }

  function _parseBoolean(args) {
    var object = args.object;
    var property = args.property;
    var defaultValue = args.defaultValue;
    if (!(property in object))
      return defaultValue;

    if (typeof object[property] != 'boolean') {
      _logs.push('ERROR: "' + property + '" expected to be a boolean but is not.');
      return defaultValue;
    }

    return object[property];
  }

  function _parseURL(args) {
    var object = args.object;
    var property = args.property;
    var baseURL = args.baseURL;

    var str = _parseString({ object: object, property: property, trim: false });
    if (str === undefined)
      return undefined;

    // TODO: resolve url using baseURL
    // new URL(object[property], baseURL);
    return object[property];
  }

  function _parseColor(args) {
    var object = args.object;
    var property = args.property;
    if (!(property in object))
      return undefined;

    if (typeof object[property] != 'string') {
      _logs.push('ERROR: "' + property + '" expected to be a string but is not.');
      return undefined;
    }

    // If style.color changes when set to the given color, it is valid. Testing
    // against 'white' and 'black' in case of the given color is one of them.
    var dummy = document.createElement('div');
    dummy.style.color = 'white';
    dummy.style.color = object[property];
    if (dummy.style.color != 'white')
      return object[property];
    dummy.style.color = 'black';
    dummy.style.color = object[property];
    if (dummy.style.color != 'black')
      return object[property];
    return undefined;
  }

  function _parseName() {
    return _parseString({ object: _json_input, property: 'name', trim: true });
  }

  function _parseShortName() {
    return _parseString({ object: _json_input,
                          property: 'short_name',
                          trim: true });
  }

  function _parseStartUrl() {
    // TODO: parse url using manifest_url as a base (missing).
    return _parseURL({ object: _json_input, property: 'start_url' });
  }

  function _parseDisplay() {
    var display = _parseString({ object: _json_input,
                                 property: 'display',
                                 trim: true });
    if (display === undefined)
      return display;

    if (ALLOWED_DISPLAY_VALUES.indexOf(display.toLowerCase()) == -1) {
      _logs.push('ERROR: "display" has an invalid value, will be ignored.');
      return undefined;
    }

    return display;
  }

  function _parseOrientation() {
    var orientation = _parseString({ object: _json_input,
                                     property: 'orientation',
                                     trim: true });
    if (orientation === undefined)
      return orientation;

    if (ALLOWED_ORIENTATION_VALUES.indexOf(orientation.toLowerCase()) == -1) {
      _logs.push('ERROR: "orientation" has an invalid value, will be ignored.');
      return undefined;
    }

    return orientation;
  }

  function _parseRelatedApplications() {
    var property = 'related_applications';
    var applications = [];

    if (!(property in _json_input))
      return applications;

    if (!Array.isArray(_json_input[property])) {
      _logs.push('ERROR: "' + property + '" expected to be an array but is not.');
      return applications;
    }

    _json_input[property].forEach(function(application) {
      application.platform = _parseString({ object: application,
                                            property: 'platform',
                                            trim: true });
      application.id = _parseString({ object: application,
                                      property: 'id',
                                      trim: true });
      application.url = _parseURL({ object: application, property: 'url' });
      applications.push(application);
      console.log(application);
    });

    return applications;
  }

  function _parsePreferRelatedApplications() {
    return _parseBoolean({ object: _json_input,
                           property: 'prefer_related_applications',
                           defaultValue: false });
  }

  function _parseThemeColor() {
    return _parseColor({ object: _json_input, property: 'theme_color' });
  }

  function _parseBackgroundColor() {
    return _parseColor({ object: _json_input, property: 'background_color' });
  }

  function _check(string) {
    try {
      _json_input = JSON.parse(string);
    } catch (e) {
      _logs.push("File isn't valid JSON: " + e);
      return [ false, _logs ];
    }

    _logs.push("JSON parsed successfuly.");

    _manifest.name = _parseName();
    _manifest.short_name = _parseShortName();
    _manifest.start_url= _parseStartUrl();
    _manifest.display = _parseDisplay();
    _manifest.orientation = _parseOrientation();

    // TODO: parse icons

    _manifest.related_applications = _parseRelatedApplications();
    _manifest.prefer_related_applications = _parsePreferRelatedApplications();
    _manifest.theme_color = _parseThemeColor();
    _manifest.background_color = _parseBackgroundColor();

    _logs.push('Parsed `name` property is: ' + _manifest.name);
    _logs.push('Parsed `short_name` property is: ' + _manifest.short_name);
    _logs.push('Parsed `start_url` property is: ' + _manifest.start_url);
    _logs.push('Parsed `display` property is: ' + _manifest.display);
    _logs.push('Parsed `orientation` property is: ' + _manifest.orientation);
    _logs.push('Parsed `related_applications` property is: ' + _manifest.related_applications);
    _logs.push('Parsed `prefer_related_applications` property is: ' + _manifest.prefer_related_applications);
    _logs.push('Parsed `theme_color` property is: ' + _manifest.theme_color);
    _logs.push('Parsed `background_color` property is: ' + _manifest.background_color);

    return [ true, _logs ];
  }

  return {
    check: _check,
  };
})();
<|endoftext|>


<commit_before>/*!
 * ImageUploader (for jQuery)
 * Version 0.3.4 (26/01/2015)
 * Copyright 2012-* Julien Deniau <julien.deniau@gmail.com>
 * Licensed under MIT (https://github.com/jdeniau/jquery-image-uploader/LICENSE.md)
 */
void 0!==typeof jQuery&&!function(t){var n=function(t){this.init(t),this.main()};n.defaults={fileField:null,urlField:null,urlFieldSubmit:null,hideFileField:!0,hideUrlField:!0,url:null,thumbnails:{div:null,width:null,height:null},maxFileSize:0,allowDuplicate:!1,thumbnailReady:t.noop,onFileAdded:function(){return!1},onFilesSelected:function(){return!1},onUrlSelected:function(){return!1},onDragStart:function(){return!1},onDragEnd:function(){return!1},onDragEnter:function(){return!1},onDragLeave:function(){return!1},onDragOver:function(){return!1},onDrop:function(){return!1},onUploadProgress:function(){return!1},beforeUpload:function(){return!0},afterUpload:function(){return!1},error:function(t){alert(t)}},n.prototype={init:function(i){instance=this,this.options=t.extend({},n.defaults,i),this.canUpload=!0,this.uploadFileList=[],this.allUploadedFileList=[],this.currentThumbnail=null},fileApiSupported:function(){return window.File&&window.FileReader&&window.FileList&&window.FormData},onDragLeave:function(i){return t(i.target)[0]===instance.options.dropZone[0]?instance.options.onDragLeave(i):void 0},onDragEnter:function(i){return t(i.target)[0]===instance.options.dropZone[0]?instance.options.onDragEnter(i):void 0},onDragStart:function(t){return t.preventDefault(),t.stopPropagation(),instance.options.onDragStart(t)},onDragEnd:function(t){return t.preventDefault(),t.stopPropagation(),instance.options.onDragEnd(t)},onDragOver:function(t){return t.preventDefault(),t.stopPropagation(),instance.options.onDragOver(t)},onDrop:function(t){return t.preventDefault(),t.stopPropagation(),instance.addFiles(t.originalEvent.dataTransfer.files),instance.options.onDrop(t)},uploadStarted:function(){instance.options.thumbnails&&(instance.currentThumbnail=instance.options.thumbnails.div.find('[data-upload-status="waiting"]:first'),instance.currentThumbnail.attr("data-upload-status","uploading"),instance.currentThumbnail.append(t('
').append(t("
"))))},onUploadProgress:function(t){return t.lengthComputable&&(instance.currentThumbnail&&0!=instance.currentThumbnail.length||instance.uploadStarted(),instance.currentThumbnail&&instance.currentThumbnail.find(".progress > div").width(100*t.loaded/t.total+"%")),instance.options.onUploadProgress(t)},uploadComplete:function(t){if(xhr=t.currentTarget,instance.canUpload=!0,200==xhr.status){var i=null;instance.currentThumbnail&&(instance.currentThumbnail.find(".progress > div").width("100%"),i=instance.currentThumbnail,instance.currentThumbnail=null),instance.options.afterUpload(t.target.response,i),instance.uploadNextFile()}else instance.uploadFailed()},uploadFailed:function(){this.canUpload=!0,this.currentThumbnail&&this.currentThumbnail.remove(),this.currentThumbnail=null,this.options.error("upload failed"),this.uploadNextFile()},uploadCanceled:function(){this.canUpload=!0,this.currentThumbnail=null,this.options.error("upload canceled"),this.uploadNextFile()},addUploadFile:function(t){this.allUploadedFileList.push(t),this.uploadFileList.push(t),this.uploadNextFile()},fileAlreadyUploaded:function(t){for(i in this.allUploadedFileList)if(f=this.allUploadedFileList[i],t.name==f.name&&t.size==f.size&&t.type==f.type)return!0;return!1},uploadNextFile:function(){this.canUpload&&this.uploadFileList.length>0&&(file=this.uploadFileList.shift(),this.canUpload=!1,this.uploadFile(file))},uploadFile:function(t){if(xhr=new XMLHttpRequest,xhr.upload&&this.options.beforeUpload()){if(xhr.open("POST",this.options.url),t instanceof File){var i=new FormData;i.append("file",t)}else{xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");var i="url="+encodeURIComponent(t.name)}xhr.upload.addEventListener("progress",this.onUploadProgress,!1),xhr.addEventListener("loadstart",this.uploadStarted,!1),xhr.addEventListener("load",this.uploadComplete,!1),xhr.addEventListener("error",this.uploadFailed,!1),xhr.addEventListener("abort",this.uploadCanceled,!1),xhr.setRequestHeader("X-Requested-With","XMLHttpRequest"),xhr.send(i)}},onFilesSelected:function(i){return i.preventDefault(),i.stopPropagation(),instance.addFiles(i.target.files),t(this).val(""),instance.options.onFilesSelected()},onUrlSelected:function(){var t=instance.options.urlField.val();return t&&instance.addFileByUrl(t),instance.options.onUrlSelected()},addFileByUrl:function(t){return this.addFile({name:t})},addFile:function(t){return this.addFiles([t])},addFiles:function(i){if(this.fileApiSupported())for(var n=null,e=0;e0&&file.size>this.options.maxFileSize)return this.options.error("the file you are trying to upload is too big");if(!this.options.allowDuplicate&&this.fileAlreadyUploaded(i[e]))return this.options.error("the file you are trying to upload has already been sent");this.options.onFileAdded(i[e]),(this.options.thumbnails||this.options.thumbnailReady!=t.noop)&&(i[e]instanceof File?(this.options.thumbnails.div.file=i[e],n=new FileReader,n.onload=function(t){instance.displayImage(t.target.result)},n.readAsDataURL(i[e])):this.displayImage(i[e].name));try{this.addUploadFile(i[e])}catch(o){this.uploadFailed()}}else alert("files api not supported")},displayImage:function(i){var n=new Image;n.src=i,t(n).hide();var e=t("
").attr("data-upload-status","waiting").css({overflow:"hidden",position:"relative"}).append(n);n.onload=function(){var i=instance.options.thumbnails.width,o=instance.options.thumbnails.height,s=n.width/n.height;if(instance.options.thumbnails.crop&&i>0&&o>0){e.width(i),e.height(o),t(n).css("position","absolute");var a=i/o;a>s?"zoom"==instance.options.thumbnails.crop?(n.width=i,n.height=i/s,t(n).css("top","-"+parseInt((n.height-o)/2)+"px")):(n.width=o*s,n.height=o,t(n).css("left",parseInt((i-n.width)/2)+"px")):"zoom"==instance.options.thumbnails.crop?(n.height=o,n.width=o*s,t(n).css("left","-"+parseInt((n.width-i)/2)+"px")):(n.width=i,n.height=o/s,t(n).css("top",parseInt((o-n.height)/2)+"px"))}else i>0?n.width=i:o>0&&(n.width=o*s),o>0?n.height=o:i>0&&(n.height=i/s);t(n).css({width:n.width,height:n.height}),t(n).show("slow")},instance.options.thumbnailReady!=t.noop?instance.options.thumbnailReady(e):instance.options.thumbnails.div.append(e)},prepareThumbnails:function(){if(this.options.thumbnails){if("object"!=typeof this.options.thumbnails){var i=null;"string"==typeof this.options.thumbnails&&(i=t(this.options.thumbnails)),this.options.thumbnails={div:i,width:null,height:null}}"string"==typeof this.options.thumbnails.div&&(this.options.thumbnails.div=t(this.options.thumbnails.div)),"object"==typeof this.options.thumbnails&&void 0==this.options.thumbnails.div&&(this.options.thumbnails.div=null),null==this.options.thumbnails.div&&(this.options.thumbnails.div=t('
'),this.options.dropZone.after(this.options.thumbnails.div))}},main:function(){var i=this;return null!=this.options.dropZone&&(this.options.dropZone.on("dragstart",this.onDragStart),this.options.dropZone.on("dragend",this.onDragEnd),this.options.dropZone.on("dragleave",this.onDragLeave),this.options.dropZone.on("dragenter",this.onDragEnter),this.options.dropZone.on("dragover",this.onDragOver),this.options.dropZone.on("drop",this.onDrop)),null!=this.options.fileField&&("string"==typeof this.options.fileField&&(this.options.fileField=t(this.options.fileField)),this.options.dropZone.on("click",function(){i.options.fileField.trigger("click")}),this.options.fileField.on("change",this.onFilesSelected),1==this.options.hideFileField&&this.hide(this.options.fileField)),null!=this.options.urlField&&("string"==typeof this.options.urlField&&(this.options.urlField=t(this.options.urlField)),null!==this.options.urlFieldSubmit?("string"==typeof this.options.urlFieldSubmit&&(this.options.urlFieldSubmit=t(this.options.urlFieldSubmit)),this.options.urlFieldSubmit.on("click",this.onUrlSelected)):this.options.urlField.on("change",this.onUrlSelected),1==this.options.hideUrlField&&this.hide(this.options.urlField)),this.prepareThumbnails(),this},hide:function(t){t.css({width:"0px",height:"0px",padding:"0px",margin:"0px",border:"none"})}},t.fn.imageUploader=function(i){i=t.extend({dropZone:t(this)},i);var e=new n(i);return t(this).data("imageUploader",e),this}}(jQuery);<commit_msg>minify file<commit_after>void 0!==typeof jQuery&&!function($){var ImageUploader=function(params){this.currentThumbnail=null,this.options=[],this.init(params),this.main()};ImageUploader.defaults={fileField:null,urlField:null,urlFieldSubmit:null,hideFileField:!0,hideUrlField:!0,url:null,thumbnails:{div:null,width:null,height:null},maxFileSize:0,allowDuplicate:!1,thumbnailReady:$.noop,onFileAdded:function(file){return!1},onFilesSelected:function(){return!1},onUrlSelected:function(){return!1},onDragStart:function(event){return!1},onDragEnd:function(event){return!1},onDragEnter:function(event){return!1},onDragLeave:function(event){return!1},onDragOver:function(event){return!1},onDrop:function(event){return!1},onUploadProgress:function(event){return!1},beforeUpload:function(){return!0},afterUpload:function(){return!1},error:function(msg){alert(msg)}},ImageUploader.prototype={init:function(params){this.options=$.extend({},ImageUploader.defaults,params),this.canUpload=!0,this.uploadFileList=new Array,this.allUploadedFileList=new Array,this.currentThumbnail=null},fileApiSupported:function(){return window.File&&window.FileReader&&window.FileList&&window.FormData},onDragLeave:function(event){return $(event.target)[0]===event.data.instance.options.dropZone[0]?event.data.instance.options.onDragLeave(event):void 0},onDragEnter:function(event){return $(event.target)[0]===event.data.instance.options.dropZone[0]?event.data.instance.options.onDragEnter(event):void 0},onDragStart:function(event){return event.preventDefault(),event.stopPropagation(),event.data.instance.options.onDragStart(event)},onDragEnd:function(event){return event.preventDefault(),event.stopPropagation(),event.data.instance.options.onDragEnd(event)},onDragOver:function(event){return event.preventDefault(),event.stopPropagation(),event.data.instance.options.onDragOver(event)},onDrop:function(event){return event.preventDefault(),event.stopPropagation(),event.data.instance.addFiles(event.originalEvent.dataTransfer.files),event.data.instance.options.onDrop(event)},uploadStarted:function(event){this.options.thumbnails&&(this.currentThumbnail=this.options.thumbnails.div.find('[data-upload-status="waiting"]:first'),this.currentThumbnail.attr("data-upload-status","uploading"),this.currentThumbnail.append($('
').append($("
"))))},onUploadProgress:function(event){return event.lengthComputable&&(this.currentThumbnail&&0!=this.currentThumbnail.length||this.uploadStarted(),this.currentThumbnail&&this.currentThumbnail.find(".progress > div").width(100*event.loaded/event.total+"%")),this.options.onUploadProgress(event)},uploadComplete:function(event){if(xhr=event.currentTarget,this.canUpload=!0,200==xhr.status){var thumbnailToReturn=null;this.currentThumbnail&&(this.currentThumbnail.find(".progress > div").width("100%"),thumbnailToReturn=this.currentThumbnail,this.currentThumbnail=null),this.options.afterUpload(event.target.response,thumbnailToReturn),this.uploadNextFile()}else this.uploadFailed()},uploadFailed:function(){this.canUpload=!0,this.currentThumbnail&&this.currentThumbnail.remove(),this.currentThumbnail=null,this.options.error("upload failed"),this.uploadNextFile()},uploadCanceled:function(){this.canUpload=!0,this.currentThumbnail=null,this.options.error("upload canceled"),this.uploadNextFile()},addUploadFile:function(file){this.allUploadedFileList.push(file),this.uploadFileList.push(file),this.uploadNextFile()},fileAlreadyUploaded:function(file){for(i in this.allUploadedFileList)if(f=this.allUploadedFileList[i],file.name==f.name&&file.size==f.size&&file.type==f.type)return!0;return!1},uploadNextFile:function(){this.canUpload&&this.uploadFileList.length>0&&(file=this.uploadFileList.shift(),this.canUpload=!1,this.uploadFile(file))},uploadFile:function(file){if(xhr=new XMLHttpRequest,xhr.upload&&this.options.beforeUpload()){if(xhr.open("POST",this.options.url),file instanceof File){var fd=new FormData;fd.append("file",file)}else{xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");var fd="url="+encodeURIComponent(file.name)}xhr.upload.addEventListener("progress",this.onUploadProgress.bind(this),!1),xhr.addEventListener("loadstart",this.uploadStarted.bind(this),!1),xhr.addEventListener("load",this.uploadComplete.bind(this),!1),xhr.addEventListener("error",this.uploadFailed.bind(this),!1),xhr.addEventListener("abort",this.uploadCanceled.bind(this),!1),xhr.setRequestHeader("X-Requested-With","XMLHttpRequest"),xhr.send(fd)}},onFilesSelected:function(event){return event.preventDefault(),event.stopPropagation(),event.data.instance.addFiles(event.target.files),$(this).val(""),event.data.instance.options.onFilesSelected()},onUrlSelected:function(event){var instance=event.data.instance,url=instance.options.urlField.val();return url&&instance.addFileByUrl(url),instance.options.onUrlSelected()},addFileByUrl:function(url){return this.addFile({name:url})},addFile:function(file){return this.addFiles([file])},addFiles:function(files){if(this.fileApiSupported())for(var reader=null,i=0;i<files.length;i++){if(this.options.maxFileSize>0&&file.size>this.options.maxFileSize)return this.options.error("the file you are trying to upload is too big");if(!this.options.allowDuplicate&&this.fileAlreadyUploaded(files[i]))return this.options.error("the file you are trying to upload has already been sent");if(this.options.onFileAdded(files[i]),this.options.thumbnails||this.options.thumbnailReady!=$.noop)if(files[i]instanceof File){this.options.thumbnails.div.file=files[i],reader=new FileReader;var _this=this;reader.onload=function(evt){_this.displayImage(evt.target.result)},reader.readAsDataURL(files[i])}else this.displayImage(files[i].name);try{this.addUploadFile(files[i])}catch(e){this.uploadFailed()}}else alert("files api not supported")},displayImage:function(src){var thumb=new Image;thumb.src=src,$(thumb).hide();var thumbContainer=$("
").attr("data-upload-status","waiting").css({overflow:"hidden",position:"relative"}).append(thumb),_this=this;thumb.onload=function(){var otw=_this.options.thumbnails.width,oth=_this.options.thumbnails.height,ratio=thumb.width/thumb.height;if(_this.options.thumbnails.crop&&otw>0&&oth>0){thumbContainer.width(otw),thumbContainer.height(oth),$(thumb).css("position","absolute");var wantedRatio=otw/oth;wantedRatio>ratio?"zoom"==_this.options.thumbnails.crop?(thumb.width=otw,thumb.height=otw/ratio,$(thumb).css("top","-"+parseInt((thumb.height-oth)/2)+"px")):(thumb.width=oth*ratio,thumb.height=oth,$(thumb).css("left",parseInt((otw-thumb.width)/2)+"px")):"zoom"==_this.options.thumbnails.crop?(thumb.height=oth,thumb.width=oth*ratio,$(thumb).css("left","-"+parseInt((thumb.width-otw)/2)+"px")):(thumb.width=otw,thumb.height=oth/ratio,$(thumb).css("top",parseInt((oth-thumb.height)/2)+"px"))}else otw>0?thumb.width=otw:oth>0&&(thumb.width=oth*ratio),oth>0?thumb.height=oth:otw>0&&(thumb.height=otw/ratio);$(thumb).css({width:thumb.width,height:thumb.height}),$(thumb).show("slow")},this.options.thumbnailReady!=$.noop?this.options.thumbnailReady(thumbContainer):this.options.thumbnails.div.append(thumbContainer)},prepareThumbnails:function(){if(this.options.thumbnails){if("object"!=typeof this.options.thumbnails){var tmpDiv=null;"string"==typeof this.options.thumbnails&&(tmpDiv=$(this.options.thumbnails)),this.options.thumbnails={div:tmpDiv,width:null,height:null}}"string"==typeof this.options.thumbnails.div&&(this.options.thumbnails.div=$(this.options.thumbnails.div)),"object"==typeof this.options.thumbnails&&void 0==this.options.thumbnails.div&&(this.options.thumbnails.div=null),null==this.options.thumbnails.div&&(this.options.thumbnails.div=$('
'),this.options.dropZone.after(this.options.thumbnails.div))}},main:function(){var _this=this;return null!=this.options.dropZone&&(this.options.dropZone.on("dragstart",{instance:this},this.onDragStart),this.options.dropZone.on("dragend",{instance:this},this.onDragEnd),this.options.dropZone.on("dragleave",{instance:this},this.onDragLeave),this.options.dropZone.on("dragenter",{instance:this},this.onDragEnter),this.options.dropZone.on("dragover",{instance:this},this.onDragOver),this.options.dropZone.on("drop",{instance:this},this.onDrop)),null!=this.options.fileField&&("string"==typeof this.options.fileField&&(this.options.fileField=$(this.options.fileField)),this.options.dropZone.on("click",function(){_this.options.fileField.trigger("click")}),this.options.fileField.on("change",{instance:this},this.onFilesSelected),1==this.options.hideFileField&&this.hide(this.options.fileField)),null!=this.options.urlField&&("string"==typeof this.options.urlField&&(this.options.urlField=$(this.options.urlField)),null!==this.options.urlFieldSubmit?("string"==typeof this.options.urlFieldSubmit&&(this.options.urlFieldSubmit=$(this.options.urlFieldSubmit)),this.options.urlFieldSubmit.on("click",{instance:this},this.onUrlSelected)):this.options.urlField.on("change",{instance:this},this.onUrlSelected),1==this.options.hideUrlField&&this.hide(this.options.urlField)),this.prepareThumbnails(),this},hide:function($element){$element.css({width:"0px",height:"0px",padding:"0px",margin:"0px",border:"none"})}},$.fn.imageUploader=function(params){params=$.extend({dropZone:$(this)},params);var instance=new ImageUploader(params);return $(this).data("imageUploader",instance),this}}(jQuery);
<|endoftext|>


<commit_before>import settings from 'settings';
import { get, set } from 'lodash/object';

export default (fields, values) => {
  const errors = {};

  fields && fields.map(field => {
    if (!field) {
      return;
    }

    const key = field.name;
    const value = get(values, key);
    const isRequired = field.html && field.html.required;
    const minLength = field.html && field.html.minLength;
    const maxLength = field.html && field.html.maxLength;
    const fieldType = field.html && field.html.type;
    const emailValidation = new RegExp(settings.emailRegex);
    const phoneValidation = new RegExp(settings.telephoneRegex);

    if (isRequired && values && !value) {
      // test for required fields
      set(errors, key, settings.requiredText);
    } else if (fieldType === 'email' && value && !emailValidation.test(value)) {
      // test telephone format
      set(errors, key, settings.emailInvalidText);
    } else if (fieldType === 'tel' && value && !phoneValidation.test(value)) {
      // test telephone format
      set(errors, key, settings.phoneInvalidText);
    } else if (maxLength && value && value.length > maxLength) {
      // test against maxLength
      set(errors, key, settings.maxLengthText.replace('%x', maxLength));
    } else if (minLength && value && value.length < minLength) {
      // test against minLength
      set(errors, key, settings.minLengthText.replace('%x', minLength));
    }
  });

  return errors;
};
<commit_msg>Comment spelling error<commit_after>import settings from 'settings';
import { get, set } from 'lodash/object';

export default (fields, values) => {
  const errors = {};

  fields && fields.map(field => {
    if (!field) {
      return;
    }

    const key = field.name;
    const value = get(values, key);
    const isRequired = field.html && field.html.required;
    const minLength = field.html && field.html.minLength;
    const maxLength = field.html && field.html.maxLength;
    const fieldType = field.html && field.html.type;
    const emailValidation = new RegExp(settings.emailRegex);
    const phoneValidation = new RegExp(settings.telephoneRegex);

    if (isRequired && values && !value) {
      // test for required fields
      set(errors, key, settings.requiredText);
    } else if (fieldType === 'email' && value && !emailValidation.test(value)) {
      // test email format
      set(errors, key, settings.emailInvalidText);
    } else if (fieldType === 'tel' && value && !phoneValidation.test(value)) {
      // test telephone format
      set(errors, key, settings.phoneInvalidText);
    } else if (maxLength && value && value.length > maxLength) {
      // test against maxLength
      set(errors, key, settings.maxLengthText.replace('%x', maxLength));
    } else if (minLength && value && value.length < minLength) {
      // test against minLength
      set(errors, key, settings.minLengthText.replace('%x', minLength));
    }
  });

  return errors;
};
<|endoftext|>


<commit_before>var normalize = require('../lib/normalize');

describe('normalize', function () {
    it('must support undefined', function () {
        normalize()
            .must.be.empty();
    });

    it('must support empty array', function () {
        normalize([])
            .must.be.empty();
    });

    it('must support objects', function () {
        normalize({ name: 'block' })
            .must.have.length(1);
    });

    it('must return set', function () {
        var decl = [
            { name: 'A' },
            { name: 'A' }
        ];

        normalize(decl).must.eql([
            { block: 'A' }
        ]);
    });

    it('must save order', function () {
        var decl = [
            { name: 'A' },
            { name: 'B' },
            { name: 'A' }
        ];

        normalize(decl).must.eql([
            { block: 'A' },
            { block: 'B' }
        ]);
    });

    it('must support array', function () {
        var decl = [
            { name: 'A' },
            { name: 'B' }
        ];

        normalize(decl).must.eql([
            { block: 'A' },
            { block: 'B' }
        ]);
    });

    describe('mods', function () {
        it('must support objects', function () {
            var decl = { name: 'block', mods: [{ name: 'mod', vals: [{ name: 'val' }] }] };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', modName: 'mod', modVal: 'val' }
            ]);
        });

        it('must support mod shortcut', function () {
            var decl = { name: 'block', mods: [{ name: 'mod' }] };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', modName: 'mod', modVal: true }
            ]);
        });
    });

    describe('elems', function () {
        it('must support arrays', function () {
            var decl = {
                name: 'block',
                elems: [
                    { name: 'elem-1' },
                    { name: 'elem-2' }
                ]
            };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', elem: 'elem-1' },
                { block: 'block', elem: 'elem-2' }
            ]);
        });

        it('must support objects', function () {
            var decl = {
                name: 'block',
                elems: [
                    { name: 'elem', mods: [{ name: 'mod', vals: [{ name: 'val' }] }] }
                ]
            };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', elem: 'elem' },
                { block: 'block', elem: 'elem', modName: 'mod', modVal: 'val' }
            ]);
        });

        it('must support mod shortcut', function () {
            var decl = {
                name: 'block',
                elems: [
                    { name: 'elem', mods: [{ name: 'mod' }] }
                ]
            };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', elem: 'elem' },
                { block: 'block', elem: 'elem', modName: 'mod', modVal: true }
            ]);
        });
    });
});
<commit_msg>Add test<commit_after>var normalize = require('../lib/normalize');

describe('normalize', function () {
    it('must support undefined', function () {
        normalize()
            .must.be.empty();
    });

    it('must support empty array', function () {
        normalize([])
            .must.be.empty();
    });

    it('must support objects', function () {
        normalize({ name: 'block' })
            .must.have.length(1);
    });

    it('must return set', function () {
        var decl = [
            { name: 'A' },
            { name: 'A' }
        ];

        normalize(decl).must.eql([
            { block: 'A' }
        ]);
    });

    it('must save order', function () {
        var decl = [
            { name: 'A' },
            { name: 'B' },
            { name: 'A' }
        ];

        normalize(decl).must.eql([
            { block: 'A' },
            { block: 'B' }
        ]);
    });

    it('must support array', function () {
        var decl = [
            { name: 'A' },
            { name: 'B' }
        ];

        normalize(decl).must.eql([
            { block: 'A' },
            { block: 'B' }
        ]);
    });

    describe('mods', function () {
        it('must support objects', function () {
            var decl = { name: 'block', mods: [{ name: 'mod', vals: [{ name: 'val' }] }] };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', modName: 'mod', modVal: 'val' }
            ]);
        });

        it('must support several items', function () {
            var decl = { name: 'block', mods: [
                { name: 'mod-1', vals: [{ name: 'val' }] },
                { name: 'mod-2', vals: [{ name: 'val' }] }
            ] };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', modName: 'mod-1', modVal: 'val' },
                { block: 'block', modName: 'mod-2', modVal: 'val' }
            ]);
        });

        it('must support mod shortcut', function () {
            var decl = { name: 'block', mods: [{ name: 'mod' }] };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', modName: 'mod', modVal: true }
            ]);
        });
    });

    describe('elems', function () {
        it('must support arrays', function () {
            var decl = {
                name: 'block',
                elems: [
                    { name: 'elem-1' },
                    { name: 'elem-2' }
                ]
            };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', elem: 'elem-1' },
                { block: 'block', elem: 'elem-2' }
            ]);
        });

        it('must support objects', function () {
            var decl = {
                name: 'block',
                elems: [
                    { name: 'elem', mods: [{ name: 'mod', vals: [{ name: 'val' }] }] }
                ]
            };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', elem: 'elem' },
                { block: 'block', elem: 'elem', modName: 'mod', modVal: 'val' }
            ]);
        });

        it('must support mod shortcut', function () {
            var decl = {
                name: 'block',
                elems: [
                    { name: 'elem', mods: [{ name: 'mod' }] }
                ]
            };

            normalize(decl).must.eql([
                { block: 'block' },
                { block: 'block', elem: 'elem' },
                { block: 'block', elem: 'elem', modName: 'mod', modVal: true }
            ]);
        });
    });
});
<|endoftext|>