<commit_before>'use strict';

(function (angular) {
    angular
        .module('geoFencePluginContent')
        .controller('ContentHomeCtrl', ['$scope', '$timeout', 'Utils', 'COLLECTIONS', 'DB', 'Modals', 'DEFAULT_DATA', 'Buildfire',
            function ($scope, $timeout, Utils, COLLECTIONS, DB, Modals, DEFAULT_DATA, Buildfire) {
                var ContentHome = this;
                var _skip, _limit, searchOptions, tmrDelayForItem, GeoActions, updating;

                /**
                 * calculateRadiusInMilesAndFeet calculates the radius in miles and feet
                 * @param radiusInMiles
                 */
                function calculateRadiusInMilesAndFeet(radiusInMiles) {
                    ContentHome.radiusMiles = parseInt(radiusInMiles);
                    if (ContentHome.radiusMiles) {
                        ContentHome.radiusFeet = parseInt((parseFloat(radiusInMiles) % ContentHome.radiusMiles) * 5280);
                    }
                    else {
                        ContentHome.radiusFeet = parseInt(parseFloat(radiusInMiles) * 5280);
                    }
                }

                /**
                 * errorAddress shows the error message when copied address is invalid
                 */
                function errorAddress() {
                    ContentHome.validCopyAddressFailure = true;
                    $timeout(function () {
                        ContentHome.validCopyAddressFailure = false;
                    }, 5000);
                }

                /**
                 * errorCoordinates shows the error message when copied coordinates are invalid
                 * @param err
                 */
                function errorCoordinates(err) {
                    ContentHome.validCoordinatesFailure = true;
                    $timeout(function () {
                        ContentHome.validCoordinatesFailure = false;
                    }, 5000);
                }

                /**
                 * successSetCoordinates sets the coordinates
                 * @param resp
                 */
                function successSetCoordinates(resp) {
                    if (resp) {
                        ContentHome.center = {
                            lng: parseFloat(ContentHome.selectedLocation.split(",")[1].trim()),
                            lat: parseFloat(ContentHome.selectedLocation.split(",")[0].trim())
                        };
                    }
                }

                /**
                 * updateMasterItem will update the ContentMedia.masterItem with passed item
                 * @param item
                 */
                function updateMasterItem(item) {
                    ContentHome.masterGeoAction = angular.copy(item);
                }

                /**
                 * resetItem will reset the ContentMedia.item with ContentMedia.masterItem
                 */
                function resetItem() {
                    ContentHome.geoAction.data = angular.copy(ContentHome.masterGeoAction);
                }

                /**
                 * isUnChanged to check whether there is change in controller media item or not
                 * @param item
                 * @returns {*|boolean}
                 */
                function isUnChanged(item) {
                    return angular.equals(item, ContentHome.masterGeoAction);
                }

                /**
                 * insertAndUpdate inserts and  updates the item
                 * @param _item
                 */
                function insertAndUpdate(_item) {
                    updating = true;
                    if (_item.id) {
                        GeoActions.update(_item.id, _item.data).then(function (data) {
                            updateMasterItem(data);
                            updating = false;
                        }, function (err) {
                            updating = false;
                            resetItem();
                            console.error('Error while inserting an item data---', err);
                        });
                    }
                    else {
                        GeoActions.insert(_item.data).then(function (data) {
                            ContentHome.geoAction = data;
                            ContentHome.items.push(data);
                            updateMasterItem(data);
                            updating = false;
                        }, function (err) {
                            console.error('Error while updating an item data---', err);
                            resetItem();
                            updating = false;
                        });
                    }
                }

                /**
                 * isValidItem tells whether item is valid or not
                 * @param action
                 * @returns {*}
                 */
                function isValidItem(action) {
                    return action.data && action.data.title;
                }

                /**
                 * updateItemWithDelay called when ever there is some change in current geo action
                 * @param _item
                 */
                function updateItemsWithDelay(_item) {
                    if (updating)
                        return;
                    if (tmrDelayForItem) {
                        $timeout.cancel(tmrDelayForItem);
                    }
                    ContentHome.isItemValid = isValidItem(_item);
                    if (_item && !isUnChanged(_item) && ContentHome.isItemValid) {
                        tmrDelayForItem = $timeout(function () {
                            insertAndUpdate(_item);
                        }, 300);
                    }
                }

                /**
                 * initialization of variables
                 */
                function init() {

                    _skip = 0;
                    _limit = 10;
                    searchOptions = {
                        filter: {"$json.title": {"$regex": '/*'}},
                        skip: _skip,
                        limit: _limit + 1 // the plus one is to check if there are any more
                    };
                    tmrDelayForItem = null;
                    GeoActions = new DB(COLLECTIONS.GeoActions);
                    updating = false;
                    ContentHome.radiusMiles = 10;
                    ContentHome.radiusFeet = 0;
                    ContentHome.center = {};
                    ContentHome.geoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                    ContentHome.masterGeoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                    ContentHome.validCopyAddressFailure = false;
                    ContentHome.validCoordinatesFailure = false;
                    /**
                     * ContentHome.noMore tells if all data has been loaded
                     * @type {boolean}
                     */
                    ContentHome.noMore = false;
                    /**
                     * ContentHome.isBusy tells whether the scrolling is in progress or not.
                     * @type {boolean}
                     */
                    ContentHome.isBusy = false;
                }

                /**
                 * ContentHome.setCoordinates validates and sets the coordinates
                 */
                ContentHome.setCoordinates = function () {
                    var latlng = '';
                    if (ContentHome.selectedLocation) {
                        latlng = ContentHome.selectedLocation.split(',')[1] + "," + ContentHome.selectedLocation.split(',')[0]
                    }
                    Utils.validLongLats(latlng).then(successSetCoordinates, errorCoordinates);
                };

                /**
                 * ContentHome.setLocation sets the address and coordinates
                 * @param data
                 */
                ContentHome.setLocation = function (data) {
                    ContentHome.selectedLocation = data.location;
                    ContentHome.currentCoordinates = data.coordinates;
                    ContentHome.geoAction.data.epicenter.address = data.location;
                    ContentHome.geoAction.data.epicenter.coordinates = ContentHome.center;
                    ContentHome.center.lat = data.coordinates[1];
                    ContentHome.center.lng = data.coordinates[0];
                    $scope.$digest();
                };

                /**
                 * ContentHome.clearData clears the lat/lng
                 */
                ContentHome.clearData = function () {
                    if (!ContentHome.selectedLocation) {
                        ContentHome.center = {
                            lng: '',
                            lat: ''
                        };
                    }
                };

                /**
                 * ContentHome.locationAutocompletePaste finds the location lat/lng
                 */
                ContentHome.locationAutocompletePaste = function () {
                    $timeout(function () {
                        if ($(".pac-container .pac-item").length) {
                            var firstResult = $(".pac-container .pac-item:first").find('.pac-matched').map(function () {
                                return $(this).text();
                            }).get().join();
                            var geocoder = new google.maps.Geocoder();
                            geocoder.geocode({"address": firstResult}, function (results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                    var lat = results[0].geometry.location.lat(),
                                        lng = results[0].geometry.location.lng();
                                    ContentHome.geoAction.data.epicenter.address = firstResult;
                                    ContentHome.geoAction.data.epicenter.lat = lat;
                                    ContentHome.geoAction.data.epicenter.lng = lng;
                                    ContentHome.center = {lat: lat, lng: lng};
                                    $("#googleMapAutocomplete").blur();
                                }
                                else {
                                    console.error('--lat long does not find-- corresponding to input');
                                }
                            });
                        }
                        else if (ContentHome.selectedLocation && (ContentHome.selectedLocation.split(',').length == 2)) {
                            ContentHome.setCoordinates();
                        }
                        else {
                            errorAddress();
                        }
                    }, 1000);

                };

                /**
                 *  ContentHome.addNewItem allow us to add new Item
                 */
                ContentHome.addNewItem = function () {
                    ContentHome.geoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                    ContentHome.selectedLocation = '';
                    ContentHome.center = {
                        lat: '',
                        lng: ''
                    };
                    ContentHome.radiusMiles = 10;
                    ContentHome.radiusFeet = 0;
                };

                /**
                 * ContentHome.getMore is used to load the items
                 */
                ContentHome.getMore = function () {
                    if (ContentHome.isBusy && !ContentHome.noMore) {
                        return;
                    }
                    ContentHome.isBusy = true;
                    GeoActions.find(searchOptions).then(function (result) {
                        if (result.length <= _limit) {// to indicate there are more
                            ContentHome.noMore = true;
                        }
                        else {
                            result.pop();
                            searchOptions.skip = searchOptions.skip + _limit;
                            ContentHome.noMore = false;
                        }
                        ContentHome.items = ContentHome.items ? ContentHome.items.concat(result) : result;
                        ContentHome.isBusy = false;
                    }, function () {
                        ContentHome.isBusy = false;
                    });
                };

                /**
                 * ContentHome.updateRadius updates the radius of a geoAction
                 */
                ContentHome.updateRadius = function () {
                    ContentHome.radiusMiles=(parseInt(ContentHome.radiusMiles) || 0);
                    ContentHome.radiusFeet=(parseInt(ContentHome.radiusFeet) || 0);
                    ContentHome.geoAction.data.radius = parseInt(ContentHome.radiusMiles) + parseFloat(ContentHome.radiusFeet / 5280);
                };

                /**
                 * ContentHome.removeListItem() used to delete an item from section list
                 * @param index
                 * @param event
                 */
                ContentHome.removeListItem = function (index, event) {

                    if ("undefined" == typeof index) {
                        return;
                    }
                    var item = ContentHome.items[index];
                    if ("undefined" !== typeof item) {

                        Modals.removePopupModal({event: event}).then(function (result) {
                            if (result) {
                                if (item.id == ContentHome.geoAction.id) {
                                    ContentHome.geoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                                    ContentHome.selectedLocation = '';
                                    ContentHome.center = {
                                        lat: '',
                                        lng: ''
                                    };
                                    ContentHome.radiusMiles = 10;
                                    ContentHome.radiusFeet = 0;
                                }
                                GeoActions.delete(item.id).then(function (data) {
                                    ContentHome.items.splice(index, 1);
                                }, function (err) {
                                    console.error('Error while deleting an item-----', err);
                                });
                            }
                        }, function (cancelData) {
                            //do something on cancel
                        });
                    }
                };

                /**
                 * ContentHome.selectItem shows the selected item in edit mode
                 * @param item
                 */
                ContentHome.selectItem = function (item) {
                    if (item && item.data) {
                        ContentHome.geoAction = item;
                        updateMasterItem(item);
                        calculateRadiusInMilesAndFeet(item.data.radius);
                        if (item.data.epicenter && item.data.epicenter.coordinates) {
                            ContentHome.center = item.data.epicenter.coordinates;
                            ContentHome.selectedLocation = item.data.epicenter.address;
                        }
                    }

                };

                /**
                 * ContentHome.clearAction clears the selection action
                 */
                ContentHome.clearAction = function () {
                    ContentHome.geoAction.data.actionToPerform = {};
                };

                /**
                 *  ContentHome.getKeyName returns the value of key
                 * @param key
                 * @returns {*}
                 */
                ContentHome.getKeyName = function (key) {
                    if (key) {
                        switch (key) {
                            case 'action':
                                return 'Action Type';
                            case 'url':
                                return 'Url';
                            case 'openIn' :
                                return 'OpenIn';
                            case 'title' :
                                return 'Title';
                            case 'email' :
                                return 'Email Address';
                            case 'subject' :
                                return 'Subject';
                            case 'body' :
                                return 'Body';
                            case 'phoneNumber' :
                                return 'PhoneNumber';
                            case 'address' :
                                return 'Address';
                            case 'lat' :
                                return 'Lat';
                            case 'lng' :
                                return 'Lng';
                            default :
                                return key;
                        }
                    }

                };

                /**
                 * ContentHome.openActionPopup opens the Popup to select the action
                 */
                ContentHome.openActionPopup = function () {
                    var linkOptions = {"icon": "true"};
                    var callback = function (error, result) {
                        if (error) {
                            return console.error('Error while selecting an action : ', error);
                        }
                        if (result)
                            ContentHome.geoAction.data.actionToPerform = result;
                        if (result && result.action == "sendSms") {
                            result.body = "Hello, How are you? This is a test message."
                        }
                        $scope.$digest();
                    };
                    Buildfire.actionItems.showDialog(null, linkOptions, callback);
                };

                /**
                 * Watcher to save the data with every change
                 */
                $scope.$watch(function () {
                    return ContentHome.geoAction;
                }, updateItemsWithDelay, true);

                init();
            }]);
})(window.angular);<commit_msg>title of an action shows blank in list<commit_after>'use strict';

(function (angular) {
    angular
        .module('geoFencePluginContent')
        .controller('ContentHomeCtrl', ['$scope', '$timeout', 'Utils', 'COLLECTIONS', 'DB', 'Modals', 'DEFAULT_DATA', 'Buildfire',
            function ($scope, $timeout, Utils, COLLECTIONS, DB, Modals, DEFAULT_DATA, Buildfire) {
                var ContentHome = this;
                var _skip, _limit, searchOptions, tmrDelayForItem, GeoActions, updating;

                /**
                 * calculateRadiusInMilesAndFeet calculates the radius in miles and feet
                 * @param radiusInMiles
                 */
                function calculateRadiusInMilesAndFeet(radiusInMiles) {
                    ContentHome.radiusMiles = parseInt(radiusInMiles);
                    if (ContentHome.radiusMiles) {
                        ContentHome.radiusFeet = parseInt((parseFloat(radiusInMiles) % ContentHome.radiusMiles) * 5280);
                    }
                    else {
                        ContentHome.radiusFeet = parseInt(parseFloat(radiusInMiles) * 5280);
                    }
                }

                /**
                 * errorAddress shows the error message when copied address is invalid
                 */
                function errorAddress() {
                    ContentHome.validCopyAddressFailure = true;
                    $timeout(function () {
                        ContentHome.validCopyAddressFailure = false;
                    }, 5000);
                }

                /**
                 * errorCoordinates shows the error message when copied coordinates are invalid
                 * @param err
                 */
                function errorCoordinates(err) {
                    ContentHome.validCoordinatesFailure = true;
                    $timeout(function () {
                        ContentHome.validCoordinatesFailure = false;
                    }, 5000);
                }

                /**
                 * successSetCoordinates sets the coordinates
                 * @param resp
                 */
                function successSetCoordinates(resp) {
                    if (resp) {
                        ContentHome.center = {
                            lng: parseFloat(ContentHome.selectedLocation.split(",")[1].trim()),
                            lat: parseFloat(ContentHome.selectedLocation.split(",")[0].trim())
                        };
                    }
                }

                /**
                 * updateMasterItem will update the ContentMedia.masterItem with passed item
                 * @param item
                 */
                function updateMasterItem(item) {
                    ContentHome.masterGeoAction = angular.copy(item);
                }

                /**
                 * resetItem will reset the ContentMedia.item with ContentMedia.masterItem
                 */
                function resetItem() {
                    ContentHome.geoAction.data = angular.copy(ContentHome.masterGeoAction);
                }

                /**
                 * isUnChanged to check whether there is change in controller media item or not
                 * @param item
                 * @returns {*|boolean}
                 */
                function isUnChanged(item) {
                    return angular.equals(item, ContentHome.masterGeoAction);
                }

                /**
                 * insertAndUpdate inserts and  updates the item
                 * @param _item
                 */
                function insertAndUpdate(_item) {
                    updating = true;
                    if (_item.id) {
                        GeoActions.update(_item.id, _item.data).then(function (data) {
                            updateMasterItem(data);
                            updating = false;
                        }, function (err) {
                            updating = false;
                            resetItem();
                            console.error('Error while inserting an item data---', err);
                        });
                    }
                    else {
                        GeoActions.insert(_item.data).then(function (data) {
                            ContentHome.geoAction = data;
                            ContentHome.items.push(data);
                            updateMasterItem(data);
                            updating = false;
                        }, function (err) {
                            console.error('Error while updating an item data---', err);
                            resetItem();
                            updating = false;
                        });
                    }
                }

                /**
                 * isValidItem tells whether item is valid or not
                 * @param action
                 * @returns {*}
                 */
                function isValidItem(action) {
                    return action.data && action.data.title;
                }

                /**
                 * updateItemWithDelay called when ever there is some change in current geo action
                 * @param _item
                 */
                function updateItemsWithDelay(_item) {
                    if (updating)
                        return;
                    if (tmrDelayForItem) {
                        $timeout.cancel(tmrDelayForItem);
                    }
                    ContentHome.isItemValid = isValidItem(_item);
                    if (_item && !isUnChanged(_item) && ContentHome.isItemValid) {
                        tmrDelayForItem = $timeout(function () {
                            insertAndUpdate(_item);
                        }, 300);
                    }
                    else{
                        if(!ContentHome.isItemValid)
                        ContentHome.geoAction.data.title=angular.copy(ContentHome.masterGeoAction.data.title);
                    }
                }

                /**
                 * initialization of variables
                 */
                function init() {

                    _skip = 0;
                    _limit = 10;
                    searchOptions = {
                        filter: {"$json.title": {"$regex": '/*'}},
                        skip: _skip,
                        limit: _limit + 1 // the plus one is to check if there are any more
                    };
                    tmrDelayForItem = null;
                    GeoActions = new DB(COLLECTIONS.GeoActions);
                    updating = false;
                    ContentHome.radiusMiles = 10;
                    ContentHome.radiusFeet = 0;
                    ContentHome.center = {};
                    ContentHome.geoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                    ContentHome.masterGeoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                    ContentHome.validCopyAddressFailure = false;
                    ContentHome.validCoordinatesFailure = false;
                    /**
                     * ContentHome.noMore tells if all data has been loaded
                     * @type {boolean}
                     */
                    ContentHome.noMore = false;
                    /**
                     * ContentHome.isBusy tells whether the scrolling is in progress or not.
                     * @type {boolean}
                     */
                    ContentHome.isBusy = false;
                }

                /**
                 * ContentHome.setCoordinates validates and sets the coordinates
                 */
                ContentHome.setCoordinates = function () {
                    var latlng = '';
                    if (ContentHome.selectedLocation) {
                        latlng = ContentHome.selectedLocation.split(',')[1] + "," + ContentHome.selectedLocation.split(',')[0]
                    }
                    Utils.validLongLats(latlng).then(successSetCoordinates, errorCoordinates);
                };

                /**
                 * ContentHome.setLocation sets the address and coordinates
                 * @param data
                 */
                ContentHome.setLocation = function (data) {
                    ContentHome.selectedLocation = data.location;
                    ContentHome.currentCoordinates = data.coordinates;
                    ContentHome.geoAction.data.epicenter.address = data.location;
                    ContentHome.geoAction.data.epicenter.coordinates = ContentHome.center;
                    ContentHome.center.lat = data.coordinates[1];
                    ContentHome.center.lng = data.coordinates[0];
                    $scope.$digest();
                };

                /**
                 * ContentHome.clearData clears the lat/lng
                 */
                ContentHome.clearData = function () {
                    if (!ContentHome.selectedLocation) {
                        ContentHome.center = {
                            lng: '',
                            lat: ''
                        };
                    }
                };

                /**
                 * ContentHome.locationAutocompletePaste finds the location lat/lng
                 */
                ContentHome.locationAutocompletePaste = function () {
                    $timeout(function () {
                        if ($(".pac-container .pac-item").length) {
                            var firstResult = $(".pac-container .pac-item:first").find('.pac-matched').map(function () {
                                return $(this).text();
                            }).get().join();
                            var geocoder = new google.maps.Geocoder();
                            geocoder.geocode({"address": firstResult}, function (results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                    var lat = results[0].geometry.location.lat(),
                                        lng = results[0].geometry.location.lng();
                                    ContentHome.geoAction.data.epicenter.address = firstResult;
                                    ContentHome.geoAction.data.epicenter.lat = lat;
                                    ContentHome.geoAction.data.epicenter.lng = lng;
                                    ContentHome.center = {lat: lat, lng: lng};
                                    $("#googleMapAutocomplete").blur();
                                }
                                else {
                                    console.error('--lat long does not find-- corresponding to input');
                                }
                            });
                        }
                        else if (ContentHome.selectedLocation && (ContentHome.selectedLocation.split(',').length == 2)) {
                            ContentHome.setCoordinates();
                        }
                        else {
                            errorAddress();
                        }
                    }, 1000);

                };

                /**
                 *  ContentHome.addNewItem allow us to add new Item
                 */
                ContentHome.addNewItem = function () {
                    ContentHome.geoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                    ContentHome.selectedLocation = '';
                    ContentHome.center = {
                        lat: '',
                        lng: ''
                    };
                    ContentHome.radiusMiles = 10;
                    ContentHome.radiusFeet = 0;
                };

                /**
                 * ContentHome.getMore is used to load the items
                 */
                ContentHome.getMore = function () {
                    if (ContentHome.isBusy && !ContentHome.noMore) {
                        return;
                    }
                    ContentHome.isBusy = true;
                    GeoActions.find(searchOptions).then(function (result) {
                        if (result.length <= _limit) {// to indicate there are more
                            ContentHome.noMore = true;
                        }
                        else {
                            result.pop();
                            searchOptions.skip = searchOptions.skip + _limit;
                            ContentHome.noMore = false;
                        }
                        ContentHome.items = ContentHome.items ? ContentHome.items.concat(result) : result;
                        ContentHome.isBusy = false;
                    }, function () {
                        ContentHome.isBusy = false;
                    });
                };

                /**
                 * ContentHome.updateRadius updates the radius of a geoAction
                 */
                ContentHome.updateRadius = function () {
                    ContentHome.radiusMiles=(parseInt(ContentHome.radiusMiles) || 0);
                    ContentHome.radiusFeet=(parseInt(ContentHome.radiusFeet) || 0);
                    ContentHome.geoAction.data.radius = parseInt(ContentHome.radiusMiles) + parseFloat(ContentHome.radiusFeet / 5280);
                };

                /**
                 * ContentHome.removeListItem() used to delete an item from section list
                 * @param index
                 * @param event
                 */
                ContentHome.removeListItem = function (index, event) {

                    if ("undefined" == typeof index) {
                        return;
                    }
                    var item = ContentHome.items[index];
                    if ("undefined" !== typeof item) {

                        Modals.removePopupModal({event: event}).then(function (result) {
                            if (result) {
                                if (item.id == ContentHome.geoAction.id) {
                                    ContentHome.geoAction = angular.copy(DEFAULT_DATA.GEO_ACTION);
                                    ContentHome.selectedLocation = '';
                                    ContentHome.center = {
                                        lat: '',
                                        lng: ''
                                    };
                                    ContentHome.radiusMiles = 10;
                                    ContentHome.radiusFeet = 0;
                                }
                                GeoActions.delete(item.id).then(function (data) {
                                    ContentHome.items.splice(index, 1);
                                }, function (err) {
                                    console.error('Error while deleting an item-----', err);
                                });
                            }
                        }, function (cancelData) {
                            //do something on cancel
                        });
                    }
                };

                /**
                 * ContentHome.selectItem shows the selected item in edit mode
                 * @param item
                 */
                ContentHome.selectItem = function (item) {
                    if (item && item.data) {
                        ContentHome.geoAction = item;
                        updateMasterItem(item);
                        calculateRadiusInMilesAndFeet(item.data.radius);
                        if (item.data.epicenter && item.data.epicenter.coordinates) {
                            ContentHome.center = item.data.epicenter.coordinates;
                            ContentHome.selectedLocation = item.data.epicenter.address;
                        }
                    }

                };

                /**
                 * ContentHome.clearAction clears the selection action
                 */
                ContentHome.clearAction = function () {
                    ContentHome.geoAction.data.actionToPerform = {};
                };

                /**
                 *  ContentHome.getKeyName returns the value of key
                 * @param key
                 * @returns {*}
                 */
                ContentHome.getKeyName = function (key) {
                    if (key) {
                        switch (key) {
                            case 'action':
                                return 'Action Type';
                            case 'url':
                                return 'Url';
                            case 'openIn' :
                                return 'OpenIn';
                            case 'title' :
                                return 'Title';
                            case 'email' :
                                return 'Email Address';
                            case 'subject' :
                                return 'Subject';
                            case 'body' :
                                return 'Body';
                            case 'phoneNumber' :
                                return 'PhoneNumber';
                            case 'address' :
                                return 'Address';
                            case 'lat' :
                                return 'Lat';
                            case 'lng' :
                                return 'Lng';
                            default :
                                return key;
                        }
                    }

                };

                /**
                 * ContentHome.openActionPopup opens the Popup to select the action
                 */
                ContentHome.openActionPopup = function () {
                    var linkOptions = {"icon": "true"};
                    var callback = function (error, result) {
                        if (error) {
                            return console.error('Error while selecting an action : ', error);
                        }
                        if (result)
                            ContentHome.geoAction.data.actionToPerform = result;
                        if (result && result.action == "sendSms") {
                            result.body = "Hello, How are you? This is a test message."
                        }
                        $scope.$digest();
                    };
                    Buildfire.actionItems.showDialog(null, linkOptions, callback);
                };

                /**
                 * Watcher to save the data with every change
                 */
                $scope.$watch(function () {
                    return ContentHome.geoAction;
                }, updateItemsWithDelay, true);

                init();
            }]);
})(window.angular);<|endoftext|>


<commit_before>const jsonImporter = require('node-sass-json-importer');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');

module.exports = ({ config, isDevelopment }) => webpackConfig => {
  return {
    ...webpackConfig,
    module: {
      rules: [
        /*
         * ------------------------------------------------
         * Styling (scss and css)
         * ------------------------------------------------
         */
        {
          test: /\.scss$/,
          oneOf: (() => {
            function getScssLoaders(cssModules) {
              const loaders = [
                {
                  loader: 'css-loader',
                  options: {
                    sourceMap: isDevelopment,
                    localIdentName: '[local]-[hash:base64:7]',
                    camelCase: true,
                    importLoaders: 2,
                    modules: cssModules,
                  },
                },
                {
                  loader: 'postcss-loader',
                  options: {
                    sourceMap: isDevelopment,
                  },
                },
                {
                  loader: 'sass-loader',
                  options: {
                    importer: jsonImporter(),
                    data: '@import "src/asset/style/utils.scss";',
                    includePaths: ['src/asset/style'],
                    sourceMap: isDevelopment,
                  },
                },
              ];

              if (isDevelopment) {
                loaders.unshift({ loader: 'style-loader' });
              } else {
                loaders.unshift(MiniCssExtractPlugin.loader);
              }

              return loaders;
            }

            return [
              {
                resourceQuery: /module/,
                use: getScssLoaders(true),
              },
              {
                use: getScssLoaders(false),
              },
            ];
          })(),
        },
        /*
         * ------------------------------------------------
         * JavaScript and TypeScript
         * ------------------------------------------------
         */
        ...(() => {
          const babelLoaderConfig = {
            loader: 'babel-loader',
            options: {
              cacheDirectory: isDevelopment,
              configFile: path.join(config.projectRoot, './babel.config.js'),
            },
          };

          return [
            {
              test: /\.js$/,
              use: babelLoaderConfig,
              include: [path.join(config.projectRoot, 'src')],
              exclude: /node_modules/,
            },
            {
              test: /\.ts$/,
              include: [path.join(config.projectRoot, 'src')],
              use: [
                babelLoaderConfig,
                {
                  loader: 'awesome-typescript-loader',
                  options: {
                    configFileName: path.resolve(config.projectRoot, './tsconfig.json'),
                  },
                },
              ],
            },
          ];
        })(),
        /*
         * ------------------------------------------------
         * Vue
         * ------------------------------------------------
         */
        {
          test: /\.vue$/,
          use: [
            {
              loader: 'vue-loader',
              options: {
                transformAssetUrls: {
                  source: ['src', 'srcset'],
                },
              },
            },
          ],
        },
        /*
         * ------------------------------------------------
         * Images and SVG
         * ------------------------------------------------
         */
        {
          test: /\.(png|jpe?g|gif)(\?.*)?$/,
          use: [
            {
              loader: 'url-loader',
              options: {
                limit: 10000,
                name: path.posix.join(
                  isDevelopment ? '' : config.dist.versionPath,
                  'image/[name].[hash:7].[ext]',
                ),
              },
            },
          ],
        },
        {
          test: /\.svg$/,
          oneOf: (() => {
            const svgoLoaderConfig = {
              loader: 'svgo-loader',
              options: {
                plugins: [
                  { removeViewBox: false },
                  { removeStyleElement: true },
                  { removeComments: true },
                  { removeDesc: true },
                  { removeUselessDefs: true },
                  { removeTitle: true },
                  { removeMetadata: true },
                  { removeComments: true },
                  { cleanupIDs: { remove: true, prefix: '' } },
                  { convertColors: { shorthex: false } },
                ],
              },
            };

            return [
              {
                resourceQuery: /inline/,
                use: [{ loader: 'svg-inline-loader' }, svgoLoaderConfig],
              },
              {
                use: [{ loader: 'url-loader' }, svgoLoaderConfig],
              },
            ];
          })(),
        },
        /*
         * ------------------------------------------------
         * Fonts
         * ------------------------------------------------
         */
        {
          test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
          use: [
            {
              loader: 'url-loader',
              options: {
                limit: 10000,
                name: path.posix.join(
                  isDevelopment ? '' : config.dist.versionPath,
                  'font/[name].[hash:7].[ext]',
                ),
              },
            },
          ],
        },
        /*
         * ------------------------------------------------
         * Other
         * ------------------------------------------------
         */
        {
          test: /\.modernizrrc$/,
          loader: 'modernizr-loader!json-loader',
        },
        {
          test: /\.(glsl|txt)$/,
          use: 'raw-loader',
        },
      ],
    },
  };
};
<commit_msg>add support for audio and video<commit_after>const jsonImporter = require('node-sass-json-importer');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');

module.exports = ({ config, isDevelopment }) => webpackConfig => {
  return {
    ...webpackConfig,
    module: {
      rules: [
        /*
         * ------------------------------------------------
         * Styling (scss and css)
         * ------------------------------------------------
         */
        {
          test: /\.scss$/,
          oneOf: (() => {
            function getScssLoaders(cssModules) {
              const loaders = [
                {
                  loader: 'css-loader',
                  options: {
                    sourceMap: isDevelopment,
                    localIdentName: '[local]-[hash:base64:7]',
                    camelCase: true,
                    importLoaders: 2,
                    modules: cssModules,
                  },
                },
                {
                  loader: 'postcss-loader',
                  options: {
                    sourceMap: isDevelopment,
                  },
                },
                {
                  loader: 'sass-loader',
                  options: {
                    importer: jsonImporter(),
                    data: '@import "src/asset/style/utils.scss";',
                    includePaths: ['src/asset/style'],
                    sourceMap: isDevelopment,
                  },
                },
              ];

              if (isDevelopment) {
                loaders.unshift({ loader: 'style-loader' });
              } else {
                loaders.unshift(MiniCssExtractPlugin.loader);
              }

              return loaders;
            }

            return [
              {
                resourceQuery: /module/,
                use: getScssLoaders(true),
              },
              {
                use: getScssLoaders(false),
              },
            ];
          })(),
        },
        /*
         * ------------------------------------------------
         * JavaScript and TypeScript
         * ------------------------------------------------
         */
        ...(() => {
          const babelLoaderConfig = {
            loader: 'babel-loader',
            options: {
              cacheDirectory: isDevelopment,
              configFile: path.join(config.projectRoot, './babel.config.js'),
            },
          };

          return [
            {
              test: /\.js$/,
              use: babelLoaderConfig,
              include: [path.join(config.projectRoot, 'src')],
              exclude: /node_modules/,
            },
            {
              test: /\.ts$/,
              include: [path.join(config.projectRoot, 'src')],
              use: [
                babelLoaderConfig,
                {
                  loader: 'awesome-typescript-loader',
                  options: {
                    configFileName: path.resolve(config.projectRoot, './tsconfig.json'),
                  },
                },
              ],
            },
          ];
        })(),
        /*
         * ------------------------------------------------
         * Vue
         * ------------------------------------------------
         */
        {
          test: /\.vue$/,
          use: [
            {
              loader: 'vue-loader',
              options: {
                transformAssetUrls: {
                  source: ['src', 'srcset'],
                },
              },
            },
          ],
        },
        /*
         * ------------------------------------------------
         * Images and SVG
         * ------------------------------------------------
         */
        {
          test: /\.(png|jpe?g|gif)(\?.*)?$/,
          use: [
            {
              loader: 'url-loader',
              options: {
                limit: 10000,
                name: path.posix.join(
                  isDevelopment ? '' : config.dist.versionPath,
                  'image/[name].[hash:7].[ext]',
                ),
              },
            },
          ],
        },
        {
          test: /\.(mp4|webm|ogv)(\?.*)?$/,
          use: [
            {
              loader: 'file-loader',
              options: {
                name: path.posix.join(
                  isDevelopment ? '' : config.dist.versionPath,
                  'video/[name].[hash:7].[ext]',
                ),
              },
            },
          ],
        },
        {
          test: /\.(mp3|ogg|wav)(\?.*)?$/,
          use: [
            {
              loader: 'file-loader',
              options: {
                name: path.posix.join(
                  isDevelopment ? '' : config.dist.versionPath,
                  'audio/[name].[hash:7].[ext]',
                ),
              },
            },
          ],
        },
        {
          test: /\.svg$/,
          oneOf: (() => {
            const svgoLoaderConfig = {
              loader: 'svgo-loader',
              options: {
                plugins: [
                  { removeViewBox: false },
                  { removeStyleElement: true },
                  { removeComments: true },
                  { removeDesc: true },
                  { removeUselessDefs: true },
                  { removeTitle: true },
                  { removeMetadata: true },
                  { removeComments: true },
                  { cleanupIDs: { remove: true, prefix: '' } },
                  { convertColors: { shorthex: false } },
                ],
              },
            };

            return [
              {
                resourceQuery: /inline/,
                use: [{ loader: 'svg-inline-loader' }, svgoLoaderConfig],
              },
              {
                use: [{ loader: 'url-loader' }, svgoLoaderConfig],
              },
            ];
          })(),
        },
        /*
         * ------------------------------------------------
         * Fonts
         * ------------------------------------------------
         */
        {
          test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
          use: [
            {
              loader: 'url-loader',
              options: {
                limit: 10000,
                name: path.posix.join(
                  isDevelopment ? '' : config.dist.versionPath,
                  'font/[name].[hash:7].[ext]',
                ),
              },
            },
          ],
        },
        /*
         * ------------------------------------------------
         * Other
         * ------------------------------------------------
         */
        {
          test: /\.modernizrrc$/,
          loader: 'modernizr-loader!json-loader',
        },
        {
          test: /\.(glsl|txt)$/,
          use: 'raw-loader',
        },
      ],
    },
  };
};
<|endoftext|>


<commit_before>import isPromise from 'is-promise';
import {
  checkResolved, getComponents, getRouteMatches, getRouteValues, isResolved,
} from 'found/lib/ResolverUtils';
import Relay from 'react-relay';
import checkRelayQueryData from 'react-relay/lib/checkRelayQueryData';

import createElements from './createElements';

const { hasOwnProperty } = Object.prototype;

// TODO: Should we disable Relay query caching for SSR? If so, we should cache
// query sets ourselves.

const PENDING_READY_STATE = {
  aborted: false,
  done: false,
  error: null,
  events: [],
  ready: false,
  stale: false,
};

const STALE_READY_STATE = {
  ...PENDING_READY_STATE,
  ready: true,
  stale: true,
};

const DONE_READY_STATE = {
  ...PENDING_READY_STATE,
  done: true,
  ready: true,
};

export default function createResolveElements(environment) {
  return async function* resolveElements(match) {
    // TODO: Close over and abort earlier requests?

    const routeMatches = getRouteMatches(match);
    const { routeIndices } = match;

    const Components = getComponents(routeMatches);
    const matchQueries = getRouteValues(
      routeMatches,
      route => route.getQueries,
      route => route.queries,
    );
    const extraQueryNodes = getRouteValues(
      routeMatches,
      route => route.getExtraQuery,
      route => route.extraQuery,
    );
    const forceFetches = getRouteValues(
      routeMatches,
      route => route.getForceFetch,
      route => route.forceFetch,
    );

    let params = null;

    const routeParams = routeMatches.map((routeMatch) => {
      const { route } = routeMatch;

      // We need to always run this to make sure we don't miss params.
      params = { ...params, ...routeMatch.routeParams };
      if (route.prepareParams) {
        params = route.prepareParams(params, routeMatch);
      }

      return params;
    });

    const queryConfigs = matchQueries.map((queries, i) => {
      if (!queries) {
        return null;
      }

      return {
        name: `__route_${i}_${routeIndices[i]}`,
        queries,
        params: routeParams[i],
      };
    });

    const extraQueries = extraQueryNodes.map((extraQueryNode, i) => {
      if (!extraQueryNode) {
        return null;
      }

      return Relay.createQuery(extraQueryNode, routeParams[i]);
    });

    const earlyComponents = Components.some(isPromise) ?
      await Promise.all(Components.map(checkResolved)) : Components;

    const recordStore = environment.getStoreData().getQueuedStore();

    const earlyReadyStates = earlyComponents.map((Component, i) => {
      const queryConfig = queryConfigs[i];
      const extraQuery = extraQueries[i];

      if (!queryConfig && !extraQuery) {
        return null;
      }

      if (!isResolved(Component)) {
        return PENDING_READY_STATE;
      }

      // TODO: What about deferred queries?
      // We use checkRelayQueryData here because I want to batch all the Relay
      // requests. We can send out requests for resolved components, but that
      // runs the risk of the data we request now being out-of-sync with the
      // data we request later.
      if (queryConfig) {
        const querySet = Relay.getQueries(Component, queryConfig);
        const hasQueryData = Object.values(querySet).every(query => (
          !query || checkRelayQueryData(recordStore, query)
        ));

        if (!hasQueryData) {
          return PENDING_READY_STATE;
        }
      }

      if (extraQuery && !checkRelayQueryData(recordStore, extraQuery)) {
        return PENDING_READY_STATE;
      }

      return forceFetches[i] ? STALE_READY_STATE : DONE_READY_STATE;
    });

    const earlyRouteExtraData = extraQueries.map((extraQuery, i) => (
      extraQuery && earlyReadyStates[i].ready ?
        environment.readQuery(extraQuery)[0] : null
    ));

    if (earlyReadyStates.some(readyState => readyState && !readyState.done)) {
      yield createElements(
        environment,
        routeMatches,
        earlyComponents,
        queryConfigs,
        earlyReadyStates,
        null, // No retry here, as these will never be in error.
        earlyRouteExtraData,
      );
    }

    const fetchedComponents = earlyComponents.every(isResolved) ?
      earlyComponents : await Promise.all(Components);

    const routeRunQueries = fetchedComponents.map((Component, i) => {
      const queryConfig = queryConfigs[i];
      const extraQuery = extraQueries[i];

      if (!queryConfig && !extraQuery) {
        return null;
      }

      let querySet;
      if (queryConfig) {
        querySet = Relay.getQueries(Component, queryConfig);
      }

      if (extraQuery) {
        let extraQueryKey = '__extra';
        while (hasOwnProperty.call(querySet, extraQueryKey)) {
          extraQueryKey = `_${extraQueryKey}`;
        }

        // Relay caches query sets, so it's very important to not modify the
        // query set in-place.
        querySet = { ...querySet, [extraQueryKey]: extraQuery };
      }

      return function runQueries(onReadyStateChange) {
        return forceFetches[i] ?
          environment.forceFetch(querySet, onReadyStateChange) :
          environment.primeCache(querySet, onReadyStateChange);
      };
    });

    // TODO: What about deferred queries?
    const fetchedReadyStates = await Promise.all(routeRunQueries.map(
      (runQueries) => {
        if (!runQueries) {
          return null;
        }

        return new Promise((resolve) => {
          runQueries((readyState) => {
            if (readyState.aborted || readyState.done || readyState.error) {
              resolve(readyState);
            }
          });
        });
      },
    ));

    const routeExtraData = extraQueries.map((extraQuery, i) => (
      extraQuery && fetchedReadyStates[i].ready ?
        environment.readQuery(extraQuery)[0] : null
    ));

    yield createElements(
      environment,
      routeMatches,
      fetchedComponents,
      queryConfigs,
      fetchedReadyStates,
      routeRunQueries,
      routeExtraData,
    );
  };
}
<commit_msg>Fix extraData shape<commit_after>import isPromise from 'is-promise';
import {
  checkResolved, getComponents, getRouteMatches, getRouteValues, isResolved,
} from 'found/lib/ResolverUtils';
import Relay from 'react-relay';
import checkRelayQueryData from 'react-relay/lib/checkRelayQueryData';

import createElements from './createElements';

const { hasOwnProperty } = Object.prototype;

// TODO: Should we disable Relay query caching for SSR? If so, we should cache
// query sets ourselves.

const PENDING_READY_STATE = {
  aborted: false,
  done: false,
  error: null,
  events: [],
  ready: false,
  stale: false,
};

const STALE_READY_STATE = {
  ...PENDING_READY_STATE,
  ready: true,
  stale: true,
};

const DONE_READY_STATE = {
  ...PENDING_READY_STATE,
  done: true,
  ready: true,
};

export default function createResolveElements(environment) {
  function getExtraData(extraQuery, readyState) {
    if (!extraQuery || !readyState.ready) {
      return null;
    }

    const identifyingArg = extraQuery.getIdentifyingArg();
    const queryData = environment.readQuery(extraQuery);
    const fieldData = identifyingArg && Array.isArray(identifyingArg.value) ?
      queryData : queryData[0];

    return { [extraQuery.getFieldName()]: fieldData };
  }

  return async function* resolveElements(match) {
    // TODO: Close over and abort earlier requests?

    const routeMatches = getRouteMatches(match);
    const { routeIndices } = match;

    const Components = getComponents(routeMatches);
    const matchQueries = getRouteValues(
      routeMatches,
      route => route.getQueries,
      route => route.queries,
    );
    const extraQueryNodes = getRouteValues(
      routeMatches,
      route => route.getExtraQuery,
      route => route.extraQuery,
    );
    const forceFetches = getRouteValues(
      routeMatches,
      route => route.getForceFetch,
      route => route.forceFetch,
    );

    let params = null;

    const routeParams = routeMatches.map((routeMatch) => {
      const { route } = routeMatch;

      // We need to always run this to make sure we don't miss params.
      params = { ...params, ...routeMatch.routeParams };
      if (route.prepareParams) {
        params = route.prepareParams(params, routeMatch);
      }

      return params;
    });

    const queryConfigs = matchQueries.map((queries, i) => {
      if (!queries) {
        return null;
      }

      return {
        name: `__route_${i}_${routeIndices[i]}`,
        queries,
        params: routeParams[i],
      };
    });

    const extraQueries = extraQueryNodes.map((extraQueryNode, i) => {
      if (!extraQueryNode) {
        return null;
      }

      return Relay.createQuery(extraQueryNode, routeParams[i]);
    });

    const earlyComponents = Components.some(isPromise) ?
      await Promise.all(Components.map(checkResolved)) : Components;

    const recordStore = environment.getStoreData().getQueuedStore();

    const earlyReadyStates = earlyComponents.map((Component, i) => {
      const queryConfig = queryConfigs[i];
      const extraQuery = extraQueries[i];

      if (!queryConfig && !extraQuery) {
        return null;
      }

      if (!isResolved(Component)) {
        return PENDING_READY_STATE;
      }

      // TODO: What about deferred queries?
      // We use checkRelayQueryData here because I want to batch all the Relay
      // requests. We can send out requests for resolved components, but that
      // runs the risk of the data we request now being out-of-sync with the
      // data we request later.
      if (queryConfig) {
        const querySet = Relay.getQueries(Component, queryConfig);
        const hasQueryData = Object.values(querySet).every(query => (
          !query || checkRelayQueryData(recordStore, query)
        ));

        if (!hasQueryData) {
          return PENDING_READY_STATE;
        }
      }

      if (extraQuery && !checkRelayQueryData(recordStore, extraQuery)) {
        return PENDING_READY_STATE;
      }

      return forceFetches[i] ? STALE_READY_STATE : DONE_READY_STATE;
    });

    const earlyRouteExtraData = extraQueries.map((extraQuery, i) => (
      getExtraData(extraQuery, earlyReadyStates[i])
    ));

    if (earlyReadyStates.some(readyState => readyState && !readyState.done)) {
      yield createElements(
        environment,
        routeMatches,
        earlyComponents,
        queryConfigs,
        earlyReadyStates,
        null, // No retry here, as these will never be in error.
        earlyRouteExtraData,
      );
    }

    const fetchedComponents = earlyComponents.every(isResolved) ?
      earlyComponents : await Promise.all(Components);

    const routeRunQueries = fetchedComponents.map((Component, i) => {
      const queryConfig = queryConfigs[i];
      const extraQuery = extraQueries[i];

      if (!queryConfig && !extraQuery) {
        return null;
      }

      let querySet;
      if (queryConfig) {
        querySet = Relay.getQueries(Component, queryConfig);
      }

      if (extraQuery) {
        let extraQueryKey = '__extra';
        while (hasOwnProperty.call(querySet, extraQueryKey)) {
          extraQueryKey = `_${extraQueryKey}`;
        }

        // Relay caches query sets, so it's very important to not modify the
        // query set in-place.
        querySet = { ...querySet, [extraQueryKey]: extraQuery };
      }

      return function runQueries(onReadyStateChange) {
        return forceFetches[i] ?
          environment.forceFetch(querySet, onReadyStateChange) :
          environment.primeCache(querySet, onReadyStateChange);
      };
    });

    // TODO: What about deferred queries?
    const fetchedReadyStates = await Promise.all(routeRunQueries.map(
      (runQueries) => {
        if (!runQueries) {
          return null;
        }

        return new Promise((resolve) => {
          runQueries((readyState) => {
            if (readyState.aborted || readyState.done || readyState.error) {
              resolve(readyState);
            }
          });
        });
      },
    ));

    const routeExtraData = extraQueries.map((extraQuery, i) => (
      getExtraData(extraQuery, fetchedReadyStates[i])
    ));

    yield createElements(
      environment,
      routeMatches,
      fetchedComponents,
      queryConfigs,
      fetchedReadyStates,
      routeRunQueries,
      routeExtraData,
    );
  };
}
<|endoftext|>


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

  /**
   * Class constructor for Data Table Card MDL component.
   * Implements MDL component design pattern defined at:
   * https://github.com/jasonmayes/mdl-component-design-pattern
   *
   * @constructor
   * @param {Element} element The element that will be upgraded.
   */
  var MaterialDataTable = function MaterialDataTable(element) {
    this.element_ = element;

    // Initialize instance.
    this.init();
  };

  window['MaterialDataTable'] = MaterialDataTable;

  /**
   * Store constants in one place so they can be updated easily.
   *
   * @enum {string | number}
   * @private
   */
  MaterialDataTable.prototype.Constant_ = {
    // None at the moment.
  };

  /**
   * Store strings for class names defined by this component that are used in
   * JavaScript. This allows us to simply change it in one place should we
   * decide to modify at a later date.
   *
   * @enum {string}
   * @private
   */
  MaterialDataTable.prototype.CssClasses_ = {
    DATA_TABLE: 'mdl-data-table',
    SELECTABLE: 'mdl-data-table--selectable',
    SELECT_ELEMENT: 'mdl-data-table__select',
    IS_SELECTED: 'is-selected',
    IS_UPGRADED: 'is-upgraded'
  };

  /**
   * Generates and returns a function that toggles the selection state of a
   * single row (or multiple rows).
   *
   * @param {Element} checkbox Checkbox that toggles the selection state.
   * @param {Element} row Row to toggle when checkbox changes.
   * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
   * @private
   */
  MaterialDataTable.prototype.selectRow_ = function(checkbox, row, opt_rows) {
    if (row) {
      return function() {
        if (checkbox.checked) {
          row.classList.add(this.CssClasses_.IS_SELECTED);
        } else {
          row.classList.remove(this.CssClasses_.IS_SELECTED);
        }
      }.bind(this);
    }

    if (opt_rows) {
      return function() {
        var i;
        var el;
        if (checkbox.checked) {
          for (i = 0; i < opt_rows.length; i++) {
            el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
            el['MaterialCheckbox'].check();
            opt_rows[i].classList.add(this.CssClasses_.IS_SELECTED);
          }
        } else {
          for (i = 0; i < opt_rows.length; i++) {
            el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
            el['MaterialCheckbox'].uncheck();
            opt_rows[i].classList.remove(this.CssClasses_.IS_SELECTED);
          }
        }
      }.bind(this);
    }
  };

  /**
   * Creates a checkbox for a single or or multiple rows and hooks up the
   * event handling.
   *
   * @param {Element} row Row to toggle when checkbox changes.
   * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
   * @private
   */
  MaterialDataTable.prototype.createCheckbox_ = function(row, opt_rows) {
    var label = document.createElement('label');
    var labelClasses = [
      'mdl-checkbox',
      'mdl-js-checkbox',
      'mdl-js-ripple-effect',
      this.CssClasses_.SELECT_ELEMENT
    ];
    label.className = labelClasses.join(' ');
    var checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.classList.add('mdl-checkbox__input');

    if (row) {
      checkbox.checked = row.classList.contains(this.CssClasses_.IS_SELECTED);
      checkbox.addEventListener('change', this.selectRow_(checkbox, row));
    } else if (opt_rows) {
      checkbox.addEventListener('change', this.selectRow_(checkbox, null, opt_rows));
    }

    label.appendChild(checkbox);
    componentHandler.upgradeElement(label, 'MaterialCheckbox');
    return label;
  };

  /**
   * Initialize element.
   */
  MaterialDataTable.prototype.init = function() {
    if (this.element_) {
      var firstHeader = this.element_.querySelector('th');
      var bodyRows = Array.prototype.slice.call(this.element_.querySelectorAll('tbody tr'));
      var footRows = Array.prototype.slice.call(this.element_.querySelectorAll('tfoot tr'));
      var rows = bodyRows.concat(footRows);

      if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) {
        var th = document.createElement('th');
        var headerCheckbox = this.createCheckbox_(null, rows);
        th.appendChild(headerCheckbox);
        firstHeader.parentElement.insertBefore(th, firstHeader);

        for (var i = 0; i < rows.length; i++) {
          var firstCell = rows[i].querySelector('td');
          if (firstCell) {
            var td = document.createElement('td');
            if (rows[i].parentNode.nodeName.toUpperCase() === 'TBODY') {
              var rowCheckbox = this.createCheckbox_(rows[i]);
              td.appendChild(rowCheckbox);
            }
            rows[i].insertBefore(td, firstCell);
          }
        }
        this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
      }
    }
  };

  // The component registers itself. It can assume componentHandler is available
  // in the global scope.
  componentHandler.register({
    constructor: MaterialDataTable,
    classAsString: 'MaterialDataTable',
    cssClass: 'mdl-js-data-table'
  });
})();
<commit_msg>Automatic uncheck header checkbox<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
  'use strict';

  /**
   * Class constructor for Data Table Card MDL component.
   * Implements MDL component design pattern defined at:
   * https://github.com/jasonmayes/mdl-component-design-pattern
   *
   * @constructor
   * @param {Element} element The element that will be upgraded.
   */
  var MaterialDataTable = function MaterialDataTable(element) {
    this.element_ = element;

    // Initialize instance.
    this.init();
  };

  window['MaterialDataTable'] = MaterialDataTable;

  /**
   * Store constants in one place so they can be updated easily.
   *
   * @enum {string | number}
   * @private
   */
  MaterialDataTable.prototype.Constant_ = {
    // None at the moment.
  };

  /**
   * Store strings for class names defined by this component that are used in
   * JavaScript. This allows us to simply change it in one place should we
   * decide to modify at a later date.
   *
   * @enum {string}
   * @private
   */
  MaterialDataTable.prototype.CssClasses_ = {
    DATA_TABLE: 'mdl-data-table',
    SELECTABLE: 'mdl-data-table--selectable',
    SELECT_ELEMENT: 'mdl-data-table__select',
    IS_SELECTED: 'is-selected',
    IS_UPGRADED: 'is-upgraded'
  };

  /**
   * Generates and returns a function that toggles the selection state of a
   * single row (or multiple rows).
   *
   * @param {Element} checkbox Checkbox that toggles the selection state.
   * @param {Element} row Row to toggle when checkbox changes.
   * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
   * @private
   */
  MaterialDataTable.prototype.selectRow_ = function(checkbox, row, opt_rows) {
    if (row) {
      return function() {
        if (checkbox.checked) {
          row.classList.add(this.CssClasses_.IS_SELECTED);
        } else {
          row.classList.remove(this.CssClasses_.IS_SELECTED);
          var thead_checkbox = this.element_.tHead.querySelector('.mdl-checkbox.is-checked');
          if(thead_checkbox !== null){
            thead_checkbox['MaterialCheckbox'].uncheck();
          }
        }
      }.bind(this);
    }

    if (opt_rows) {
      return function() {
        var i;
        var el;
        if (checkbox.checked) {
          for (i = 0; i < opt_rows.length; i++) {
            el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
            el['MaterialCheckbox'].check();
            opt_rows[i].classList.add(this.CssClasses_.IS_SELECTED);
          }
        } else {
          for (i = 0; i < opt_rows.length; i++) {
            el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
            el['MaterialCheckbox'].uncheck();
            opt_rows[i].classList.remove(this.CssClasses_.IS_SELECTED);
          }
        }
      }.bind(this);
    }
  };

  /**
   * Creates a checkbox for a single or or multiple rows and hooks up the
   * event handling.
   *
   * @param {Element} row Row to toggle when checkbox changes.
   * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
   * @private
   */
  MaterialDataTable.prototype.createCheckbox_ = function(row, opt_rows) {
    var label = document.createElement('label');
    var labelClasses = [
      'mdl-checkbox',
      'mdl-js-checkbox',
      'mdl-js-ripple-effect',
      this.CssClasses_.SELECT_ELEMENT
    ];
    label.className = labelClasses.join(' ');
    var checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.classList.add('mdl-checkbox__input');

    if (row) {
      checkbox.checked = row.classList.contains(this.CssClasses_.IS_SELECTED);
      checkbox.addEventListener('change', this.selectRow_(checkbox, row));
    } else if (opt_rows) {
      checkbox.addEventListener('change', this.selectRow_(checkbox, null, opt_rows));
    }

    label.appendChild(checkbox);
    componentHandler.upgradeElement(label, 'MaterialCheckbox');
    return label;
  };

  /**
   * Initialize element.
   */
  MaterialDataTable.prototype.init = function() {
    if (this.element_) {
      var firstHeader = this.element_.querySelector('th');
      var bodyRows = Array.prototype.slice.call(this.element_.querySelectorAll('tbody tr'));
      var footRows = Array.prototype.slice.call(this.element_.querySelectorAll('tfoot tr'));
      var rows = bodyRows.concat(footRows);

      if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) {
        var th = document.createElement('th');
        var headerCheckbox = this.createCheckbox_(null, rows);
        th.appendChild(headerCheckbox);
        firstHeader.parentElement.insertBefore(th, firstHeader);

        for (var i = 0; i < rows.length; i++) {
          var firstCell = rows[i].querySelector('td');
          if (firstCell) {
            var td = document.createElement('td');
            if (rows[i].parentNode.nodeName.toUpperCase() === 'TBODY') {
              var rowCheckbox = this.createCheckbox_(rows[i]);
              td.appendChild(rowCheckbox);
            }
            rows[i].insertBefore(td, firstCell);
          }
        }
        this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
      }
    }
  };

  // The component registers itself. It can assume componentHandler is available
  // in the global scope.
  componentHandler.register({
    constructor: MaterialDataTable,
    classAsString: 'MaterialDataTable',
    cssClass: 'mdl-js-data-table'
  });
})();
<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function(scope) {

  // imports

  var api = scope.api;
  var isBase = scope.isBase;
  var extend = scope.extend;

  // prototype api

  var prototype = {
    register: function(name, extendee) {
      // build prototype combining extendee, Polymer base, and named api
      this.prototype = this.buildPrototype(name, extendee);
      // back reference declaration element
      // TODO(sjmiles): replace `element` with `elementElement` or `declaration`
      this.prototype.element = this;
      // more declarative features
      this.desugar(name, extendee);
      // register our custom element with the platform
      this.registerPrototype(name, extendee);
      // reference constructor in a global named by 'constructor' attribute
      this.publishConstructor();
    },
    buildPrototype: function(name, extendee) {
      // get our custom prototype (before chaining)
      var prototype = scope.getRegisteredPrototype(name);
      // get basal prototype
      var base = this.generateBasePrototype(extendee);
      // transcribe `attributes` declarations onto own prototype's `publish`
      this.publishAttributes(prototype, base);
      // `publish` properties to the prototype and to attribute watch
      this.publishProperties(prototype, base);
      // infer observers for `observe` list based on method names
      this.inferObservers(prototype);
      // desugar compound observer syntax, e.g. 'a b c'
      this.explodeObservers(prototype);
      // chain various meta-data objects to inherited versions
      this.inheritMetaData(prototype, base);
      // chain custom api to inherited
      prototype = this.chainObject(prototype, base);
      // build side-chained lists to optimize iterations
      this.optimizePropertyMaps(prototype);
      // x-platform fixup
      ensurePrototypeTraversal(prototype);
      return prototype;
    },
    inheritMetaData: function(prototype, base) {
      // chain observe object to inherited
      this.inheritObject('observe', prototype, base);
      // chain publish object to inherited
      this.inheritObject('publish', prototype, base);
      // chain our lower-cased publish map to the inherited version
      this.inheritObject('_publishLC', prototype, base);
      // chain our instance attributes map to the inherited version
      this.inheritObject('_instanceAttributes', prototype, base);
      // chain our event delegates map to the inherited version
      this.inheritObject('eventDelegates', prototype, base);
    },
    // implement various declarative features
    desugar: function(name, extendee) {
      // compile list of attributes to copy to instances
      this.accumulateInstanceAttributes();
      // parse on-* delegates declared on `this` element
      this.parseHostEvents();
      // install external stylesheets as if they are inline
      this.installSheets();
      //
      this.adjustShadowElement();
      //
      // TODO(sorvell): install a helper method this.resolvePath to aid in
      // setting resource paths. e.g.
      // this.$.image.src = this.resolvePath('images/foo.png')
      // Potentially remove when spec bug is addressed.
      // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
      this.addResolvePathApi();
      // under ShadowDOMPolyfill, transforms to approximate missing CSS features
      if (window.ShadowDOMPolyfill) {
        Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);
      }
      // allow custom element access to the declarative context
      if (this.prototype.registerCallback) {
        this.prototype.registerCallback(this);
      }
    },
    // TODO(sorvell): remove when spec addressed:
    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22460
    // make <shadow></shadow> be <shadow><content></content></shadow>
    adjustShadowElement: function() {
      // TODO(sorvell): avoid under SD polyfill until this bug is addressed:
      // https://github.com/Polymer/ShadowDOM/issues/297
      if (!window.ShadowDOMPolyfill) {
        var content = this.templateContent();
        if (content) {
          var s$ = content.querySelectorAll('shadow');
          for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {
            if (!s.children.length) {
              s.appendChild(document.createElement('content'));
            }
          }
        }
      }
    },
    // if a named constructor is requested in element, map a reference
    // to the constructor to the given symbol
    publishConstructor: function() {
      var symbol = this.getAttribute('constructor');
      if (symbol) {
        window[symbol] = this.ctor;
      }
    },
    // build prototype combining extendee, Polymer base, and named api
    generateBasePrototype: function(extnds) {
      var prototype = this.findBasePrototype(extnds);
      if (!prototype) {
        // create a prototype based on tag-name extension
        var prototype = HTMLElement.getPrototypeForTag(extnds);
        // insert base api in inheritance chain (if needed)
        prototype = this.ensureBaseApi(prototype);
        // memoize this base
        memoizedBases[extnds] = prototype;
      }
      return prototype;
    },
    findBasePrototype: function(name) {
      return memoizedBases[name];
    },
    // install Polymer instance api into prototype chain, as needed
    ensureBaseApi: function(prototype) {
      if (prototype.PolymerBase) {
        return prototype;
      }
      var extended = Object.create(prototype);
      // we need a unique copy of base api for each base prototype
      // therefore we 'extend' here instead of simply chaining
      // we could memoize instead, especially for the common cases,
      // in particular, for base === HTMLElement.prototype
      for (var n in api.instance) {
        extend(extended, api.instance[n]);
      }
      // TODO(sjmiles): sharing methods across prototype chains is
      // not supported by our 'super' implementation which optimizes
      // by memoizing prototype relationships.
      // Probably we should have a version of 'extend' that is
      // share-aware: it could study the text of each function,
      // look for usage of 'super', and wrap those functions in
      // closures.
      // As of now, there is only one problematic method, so
      // we just patch it manually.
      this.mixinMethod(extended, prototype, api.instance.mdv, 'bind');
      // return buffed-up prototype
      return extended;
    },
    mixinMethod: function(extended, prototype, api, name) {
      var $super = function(args) {
        return prototype[name].apply(this, args);
      };
      extended[name] = function() {
        this.super = $super;
        var value = api[name].apply(this, arguments);
        this.super = extended.super;
        return value;
      }
    },
    // ensure prototype[name] inherits from a prototype.prototype[name]
    inheritObject: function(name, prototype, base) {
      // require an object
      var source = prototype[name] || {};
      // chain inherited properties onto a new object
      prototype[name] = this.chainObject(source, base[name]);
    },
    // register 'prototype' to custom element 'name', store constructor
    registerPrototype: function(name, extendee) {
      var info = {
        prototype: this.prototype
      }
      // native element must be specified in extends
      var typeExtension = this.findTypeExtension(extendee);
      if (typeExtension) {
        info.extends = typeExtension;
      }
      // register the custom type
      this.ctor = document.registerElement(name, info);
      // constructor shenanigans
      this.prototype.constructor = this.ctor;
      // register the prototype with HTMLElement for name lookup
      HTMLElement.register(name, this.prototype);
    },
    findTypeExtension: function(name) {
      if (name && name.indexOf('-') < 0) {
        return name;
      } else {
        var p = this.findBasePrototype(name);
        if (p.element) {
          return this.findTypeExtension(p.element.extends);
        }
      }
    }
  };

  // implementation of 'chainObject' depends on support for __proto__
  if (Object.__proto__) {
    prototype.chainObject = function(object, inherited) {
      if (object && inherited && object !== inherited) {
        object.__proto__ = inherited;
      }
      return object;
    }
  } else {
    prototype.chainObject = function(object, inherited) {
      if (object && inherited && object !== inherited) {
        var chained = Object.create(inherited);
        object = extend(chained, object);
      }
      return object;
    }
  }

  // memoize base prototypes
  memoizedBases = {};

  // On platforms that do not support __proto__ (version of IE), the prototype
  // chain of a custom element is simulated via installation of __proto__.
  // Although custom elements manages this, we install it here so it's
  // available during desugaring.
  function ensurePrototypeTraversal(prototype) {
    if (!Object.__proto__) {
      var ancestor = Object.getPrototypeOf(prototype);
      prototype.__proto__ = ancestor;
      if (isBase(ancestor)) {
        ancestor.__proto__ = Object.getPrototypeOf(ancestor);
      }
    }
  }

  // exports

  api.declaration.prototype = prototype;

})(Polymer);
<commit_msg>apply path fixup in polymer-element<commit_after>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function(scope) {

  // imports

  var api = scope.api;
  var isBase = scope.isBase;
  var extend = scope.extend;

  // prototype api

  var prototype = {
    register: function(name, extendee) {
      // build prototype combining extendee, Polymer base, and named api
      this.prototype = this.buildPrototype(name, extendee);
      // back reference declaration element
      // TODO(sjmiles): replace `element` with `elementElement` or `declaration`
      this.prototype.element = this;
      // more declarative features
      this.desugar(name, extendee);
      // register our custom element with the platform
      this.registerPrototype(name, extendee);
      // reference constructor in a global named by 'constructor' attribute
      this.publishConstructor();
    },
    buildPrototype: function(name, extendee) {
      // get our custom prototype (before chaining)
      var prototype = scope.getRegisteredPrototype(name);
      // get basal prototype
      var base = this.generateBasePrototype(extendee);
      // transcribe `attributes` declarations onto own prototype's `publish`
      this.publishAttributes(prototype, base);
      // `publish` properties to the prototype and to attribute watch
      this.publishProperties(prototype, base);
      // infer observers for `observe` list based on method names
      this.inferObservers(prototype);
      // desugar compound observer syntax, e.g. 'a b c'
      this.explodeObservers(prototype);
      // chain various meta-data objects to inherited versions
      this.inheritMetaData(prototype, base);
      // chain custom api to inherited
      prototype = this.chainObject(prototype, base);
      // build side-chained lists to optimize iterations
      this.optimizePropertyMaps(prototype);
      // x-platform fixup
      ensurePrototypeTraversal(prototype);
      return prototype;
    },
    inheritMetaData: function(prototype, base) {
      // chain observe object to inherited
      this.inheritObject('observe', prototype, base);
      // chain publish object to inherited
      this.inheritObject('publish', prototype, base);
      // chain our lower-cased publish map to the inherited version
      this.inheritObject('_publishLC', prototype, base);
      // chain our instance attributes map to the inherited version
      this.inheritObject('_instanceAttributes', prototype, base);
      // chain our event delegates map to the inherited version
      this.inheritObject('eventDelegates', prototype, base);
    },
    // implement various declarative features
    desugar: function(name, extendee) {
      // install external stylesheets as if they are inline
      this.installSheets();
      // adjust any paths in dom from imports
      this.resolveElementPaths(this);
      // compile list of attributes to copy to instances
      this.accumulateInstanceAttributes();
      // parse on-* delegates declared on `this` element
      this.parseHostEvents();
      //
      this.adjustShadowElement();
      //
      // TODO(sorvell): install a helper method this.resolvePath to aid in
      // setting resource paths. e.g.
      // this.$.image.src = this.resolvePath('images/foo.png')
      // Potentially remove when spec bug is addressed.
      // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
      this.addResolvePathApi();
      // under ShadowDOMPolyfill, transforms to approximate missing CSS features
      if (window.ShadowDOMPolyfill) {
        Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);
      }
      // allow custom element access to the declarative context
      if (this.prototype.registerCallback) {
        this.prototype.registerCallback(this);
      }
    },
    // TODO(sorvell): remove when spec addressed:
    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22460
    // make <shadow></shadow> be <shadow><content></content></shadow>
    adjustShadowElement: function() {
      // TODO(sorvell): avoid under SD polyfill until this bug is addressed:
      // https://github.com/Polymer/ShadowDOM/issues/297
      if (!window.ShadowDOMPolyfill) {
        var content = this.templateContent();
        if (content) {
          var s$ = content.querySelectorAll('shadow');
          for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {
            if (!s.children.length) {
              s.appendChild(document.createElement('content'));
            }
          }
        }
      }
    },
    // if a named constructor is requested in element, map a reference
    // to the constructor to the given symbol
    publishConstructor: function() {
      var symbol = this.getAttribute('constructor');
      if (symbol) {
        window[symbol] = this.ctor;
      }
    },
    // build prototype combining extendee, Polymer base, and named api
    generateBasePrototype: function(extnds) {
      var prototype = this.findBasePrototype(extnds);
      if (!prototype) {
        // create a prototype based on tag-name extension
        var prototype = HTMLElement.getPrototypeForTag(extnds);
        // insert base api in inheritance chain (if needed)
        prototype = this.ensureBaseApi(prototype);
        // memoize this base
        memoizedBases[extnds] = prototype;
      }
      return prototype;
    },
    findBasePrototype: function(name) {
      return memoizedBases[name];
    },
    // install Polymer instance api into prototype chain, as needed
    ensureBaseApi: function(prototype) {
      if (prototype.PolymerBase) {
        return prototype;
      }
      var extended = Object.create(prototype);
      // we need a unique copy of base api for each base prototype
      // therefore we 'extend' here instead of simply chaining
      // we could memoize instead, especially for the common cases,
      // in particular, for base === HTMLElement.prototype
      for (var n in api.instance) {
        extend(extended, api.instance[n]);
      }
      // TODO(sjmiles): sharing methods across prototype chains is
      // not supported by our 'super' implementation which optimizes
      // by memoizing prototype relationships.
      // Probably we should have a version of 'extend' that is
      // share-aware: it could study the text of each function,
      // look for usage of 'super', and wrap those functions in
      // closures.
      // As of now, there is only one problematic method, so
      // we just patch it manually.
      this.mixinMethod(extended, prototype, api.instance.mdv, 'bind');
      // return buffed-up prototype
      return extended;
    },
    mixinMethod: function(extended, prototype, api, name) {
      var $super = function(args) {
        return prototype[name].apply(this, args);
      };
      extended[name] = function() {
        this.super = $super;
        var value = api[name].apply(this, arguments);
        this.super = extended.super;
        return value;
      }
    },
    // ensure prototype[name] inherits from a prototype.prototype[name]
    inheritObject: function(name, prototype, base) {
      // require an object
      var source = prototype[name] || {};
      // chain inherited properties onto a new object
      prototype[name] = this.chainObject(source, base[name]);
    },
    // register 'prototype' to custom element 'name', store constructor
    registerPrototype: function(name, extendee) {
      var info = {
        prototype: this.prototype
      }
      // native element must be specified in extends
      var typeExtension = this.findTypeExtension(extendee);
      if (typeExtension) {
        info.extends = typeExtension;
      }
      // register the custom type
      this.ctor = document.registerElement(name, info);
      // constructor shenanigans
      this.prototype.constructor = this.ctor;
      // register the prototype with HTMLElement for name lookup
      HTMLElement.register(name, this.prototype);
    },
    findTypeExtension: function(name) {
      if (name && name.indexOf('-') < 0) {
        return name;
      } else {
        var p = this.findBasePrototype(name);
        if (p.element) {
          return this.findTypeExtension(p.element.extends);
        }
      }
    }
  };

  // implementation of 'chainObject' depends on support for __proto__
  if (Object.__proto__) {
    prototype.chainObject = function(object, inherited) {
      if (object && inherited && object !== inherited) {
        object.__proto__ = inherited;
      }
      return object;
    }
  } else {
    prototype.chainObject = function(object, inherited) {
      if (object && inherited && object !== inherited) {
        var chained = Object.create(inherited);
        object = extend(chained, object);
      }
      return object;
    }
  }

  // memoize base prototypes
  memoizedBases = {};

  // On platforms that do not support __proto__ (version of IE), the prototype
  // chain of a custom element is simulated via installation of __proto__.
  // Although custom elements manages this, we install it here so it's
  // available during desugaring.
  function ensurePrototypeTraversal(prototype) {
    if (!Object.__proto__) {
      var ancestor = Object.getPrototypeOf(prototype);
      prototype.__proto__ = ancestor;
      if (isBase(ancestor)) {
        ancestor.__proto__ = Object.getPrototypeOf(ancestor);
      }
    }
  }

  // exports

  api.declaration.prototype = prototype;

})(Polymer);
<|endoftext|>