Search code examples
javascriptextjsgeolocationrequireweather

ExtJS Geolocation usage for classic toolkit


I'm following this Geolocation usage for Sencha Touch tutorial but I need to use for both classic and modern toolkit. During sencha app watch / refresh / build commands I get the error for the requirement for Ext.util.Geolocation class;

C2008: Requirement had no matching files (Ext.util.Geolocation)
[ERR] BUILD FAILED
[ERR] com.sencha.exceptions.ExBuild: Failed to find any files for /..../WeatherView.js::ClassRequire::Ext.util.Geolocation
[ERR]   at sun.reflect.Delegat
[ERR] ingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Despite when I try to sencha app watch modern command, then I get an error for Ext.form.field.Text. I can not disable textfield usage in my app. So what could be the solution for Geolocation service?

Here is a code snippet which occurs the error:

refreshGeoLocation : function( refresh ) {
    if (!this.geoLocationObj || (true == refresh)) {
        Ext.create('Ext.util.Geolocation', {
            autoUpdate: false,
            listeners: {
                locationupdate: function (geo) {
                    Ext.Msg.alert('Refresh Geolocation', 'New latitude: ' + geo.getLatitude() + ' , Longitude: ' + geo.getLongitude(), Ext.emptyFn);
                },
                locationerror: function (geo, bTimeout, bPermissionDenied, bLocationUnavailable, message) {
                    if (bTimeout) {
                        alert('Timeout occurred');
                    } else {
                        alert('Error occurred');
                    }
                }
            }
        });

        this.geoLocationObj.updateLocation();
    }
}

(*) Tutorial: https://wtcindia.wordpress.com/2013/02/08/using-yahoo-weather-api-in-sencha-touch/


Solution

  • Reason of this error (Requirement had no matching files (Ext.util.Geolocation)) is may be somewhere(app.js or Application.js) you have requires this class Ext.util.Geolocation.

    Ext.util.Geolocation is only available in modern toolkit. So instead of app.js you should requires inside modern folder.

    For this "Despite when I try to sencha app watch modern command, then I get an error for Ext.form.field.Text."

    This class Ext.form.field.Text available only classic toolkit. Instead of this Ext.form.field.Text you need to use this Ext.field.Text inside of modern toolkit.

    If you want to use Geolocation in classic toolkit, so you need to add custom class inside classic folder.

    For further details you can refer this my ExtJS-GeoLocation project.

    I hope this will guide you to solve your error..

    /**
     * Provides a cross browser class for retrieving location information.
     * Source from https://docs.sencha.com/extjs/6.0.0/modern/src/Geolocation.js.html
     * Based on the [Geolocation API Specification](http://dev.w3.org/geo/api/spec-source.html)
     *
     * When instantiated, by default this class immediately begins tracking location information,
     * firing a {@link #locationupdate} event when new location information is available.  To disable this
     * location tracking (which may be battery intensive on mobile devices), set {@link #autoUpdate} to `false`.
     *
     * When this is done, only calls to {@link #updateLocation} will trigger a location retrieval.
     *
     * A {@link #locationerror} event is raised when an error occurs retrieving the location, either due to a user
     * denying the application access to it, or the browser not supporting it.
     *
     * The below code shows a GeoLocation making a single retrieval of location information.
     *
     *      //{GeoLocation} is your application name
     *     var geo = Ext.create('GeoLocation.util.Geolocation', {
     *         autoUpdate: false,
     *         listeners: {
     *             locationupdate: function(geo) {
     *                 Ext.Msg.alert('Success', `New latitude: ${geo.getLatitude()} <br>New Longitude: ${geo.getLongitude()}`);
     *             },
     *             locationerror: function(geo, bTimeout, bPermissionDenied, bLocationUnavailable, message) {
     *                 if(bTimeout){
     *                     Ext.Msg.alert('Error', 'Timeout occurred.');
     *                 } else {
     *                      Ext.Msg.alert('Error', 'Error occurred');
     *                 }
     *             }
     *         }
     *     });
     *     geo.updateLocation();
     */
    //{GeoLocation} is your application name
    Ext.define('GeoLocation.util.Geolocation', {
        extend: 'Ext.Evented',
    
        alternateClassName: ['Geolocation'],
    
        config: {
            /**
             * @event locationerror
             * Raised when a location retrieval operation failed.
             *
             * In the case of calling updateLocation, this event will be raised only once.
             *
             * If {@link #autoUpdate} is set to `true`, this event could be raised repeatedly.
             * The first error is relative to the moment {@link #autoUpdate} was set to `true`
             * (or this {@link Ext.util.Geolocation} was initialized with the {@link #autoUpdate} config option set to `true`).
             * Subsequent errors are relative to the moment when the device determines that it's position has changed.
             * @param {Ext.util.Geolocation} this
             * @param {Boolean} timeout
             * Boolean indicating a timeout occurred
             * @param {Boolean} permissionDenied
             * Boolean indicating the user denied the location request
             * @param {Boolean} locationUnavailable
             * Boolean indicating that the location of the device could not be determined.
             * For instance, one or more of the location providers used in the location acquisition
             * process reported an internal error that caused the process to fail entirely.
             * @param {String} message An error message describing the details of the error encountered.
             *
             * This attribute is primarily intended for debugging and should not be used
             * directly in an application user interface.
             */
    
            /**
             * @event locationupdate
             * Raised when a location retrieval operation has been completed successfully.
             * @param {Ext.util.Geolocation} this
             * Retrieve the current location information from the GeoLocation object by using the read-only
             * properties: {@link #latitude}, {@link #longitude}, {@link #accuracy}, {@link #altitude}, {@link #altitudeAccuracy}, {@link #heading}, and {@link #speed}.
             */
    
            /**
             * @cfg {Boolean} autoUpdate
             * When set to `true`, continually monitor the location of the device (beginning immediately)
             * and fire {@link #locationupdate} and {@link #locationerror} events.
             */
            autoUpdate: true,
    
            /**
             * @cfg {Number} frequency
             * The frequency of each update if {@link #autoUpdate} is set to `true`.
             */
            frequency: 10000,
    
            /**
             * @cfg {Number} latitude
             * Read-only property representing the last retrieved
             * geographical coordinate specified in degrees.
             * @readonly
             */
            latitude: null,
    
            /**
             * @cfg {Number} longitude
             * Read-only property representing the last retrieved
             * geographical coordinate specified in degrees.
             * @readonly
             */
            longitude: null,
    
            /**
             * @cfg {Number} accuracy
             * Read-only property representing the last retrieved
             * accuracy level of the latitude and longitude coordinates,
             * specified in meters.
             *
             * This will always be a non-negative number.
             *
             * This corresponds to a 95% confidence level.
             * @readonly
             */
            accuracy: null,
    
            /**
             * @cfg {Number} altitude
             * Read-only property representing the last retrieved
             * height of the position, specified in meters above the ellipsoid
             * [WGS84](http://dev.w3.org/geo/api/spec-source.html#ref-wgs).
             * @readonly
             */
            altitude: null,
    
            /**
             * @cfg {Number} altitudeAccuracy
             * Read-only property representing the last retrieved
             * accuracy level of the altitude coordinate, specified in meters.
             *
             * If altitude is not null then this will be a non-negative number.
             * Otherwise this returns `null`.
             *
             * This corresponds to a 95% confidence level.
             * @readonly
             */
            altitudeAccuracy: null,
    
            /**
             * @cfg {Number} heading
             * Read-only property representing the last retrieved
             * direction of travel of the hosting device,
             * specified in non-negative degrees between 0 and 359,
             * counting clockwise relative to the true north.
             *
             * If speed is 0 (device is stationary), then this returns `NaN`.
             * @readonly
             */
            heading: null,
    
            /**
             * @cfg {Number} speed
             * Read-only property representing the last retrieved
             * current ground speed of the device, specified in meters per second.
             *
             * If this feature is unsupported by the device, this returns `null`.
             *
             * If the device is stationary, this returns 0,
             * otherwise it returns a non-negative number.
             * @readonly
             */
            speed: null,
    
            /**
             * @cfg {Date} timestamp
             * Read-only property representing when the last retrieved
             * positioning information was acquired by the device.
             * @readonly
             */
            timestamp: null,
    
            //PositionOptions interface
            /**
             * @cfg {Boolean} allowHighAccuracy
             * When set to `true`, provide a hint that the application would like to receive
             * the best possible results. This may result in slower response times or increased power consumption.
             * The user might also deny this capability, or the device might not be able to provide more accurate
             * results than if this option was set to `false`.
             */
            allowHighAccuracy: false,
    
            /**
             * @cfg {Number} timeout
             * The maximum number of milliseconds allowed to elapse between a location update operation
             * and the corresponding {@link #locationupdate} event being raised.  If a location was not successfully
             * acquired before the given timeout elapses (and no other internal errors have occurred in this interval),
             * then a {@link #locationerror} event will be raised indicating a timeout as the cause.
             *
             * Note that the time that is spent obtaining the user permission is **not** included in the period
             * covered by the timeout.  The `timeout` attribute only applies to the location acquisition operation.
             *
             * In the case of calling `updateLocation`, the {@link #locationerror} event will be raised only once.
             *
             * If {@link #autoUpdate} is set to `true`, the {@link #locationerror} event could be raised repeatedly.
             * The first timeout is relative to the moment {@link #autoUpdate} was set to `true`
             * (or this {@link Ext.util.Geolocation} was initialized with the {@link #autoUpdate} config option set to `true`).
             * Subsequent timeouts are relative to the moment when the device determines that it's position has changed.
             */
            timeout: Infinity,
    
            /**
             * @cfg {Number} maximumAge
             * This option indicates that the application is willing to accept cached location information whose age
             * is no greater than the specified time in milliseconds. If `maximumAge` is set to 0, an attempt to retrieve
             * new location information is made immediately.
             *
             * Setting the `maximumAge` to Infinity returns a cached position regardless of its age.
             *
             * If the device does not have cached location information available whose age is no
             * greater than the specified `maximumAge`, then it must acquire new location information.
             *
             * For example, if location information no older than 10 minutes is required, set this property to 600000.
             */
            maximumAge: 0,
    
            /**
             * @private
             */
            provider: undefined
        },
    
        updateMaximumAge: function() {
            if (this.watchOperation) {
                this.updateWatchOperation();
            }
        },
    
        updateTimeout: function() {
            if (this.watchOperation) {
                this.updateWatchOperation();
            }
        },
    
        updateAllowHighAccuracy: function() {
            if (this.watchOperation) {
                this.updateWatchOperation();
            }
        },
    
        applyProvider: function(config) {
            if (Ext.feature.has.Geolocation) {
                if (!config) {
                    if (navigator && navigator.geolocation) {
                        config = navigator.geolocation;
                    } else if (window.google) {
                        config = google.gears.factory.create('beta.geolocation');
                    }
                }
            } else {
                this.fireEvent('locationerror', this, false, false, true, 'This device does not support Geolocation.');
            }
            return config;
        },
    
        updateAutoUpdate: function(newAutoUpdate, oldAutoUpdate) {
            var me = this,
                provider = me.getProvider();
    
            if (oldAutoUpdate && provider) {
                Ext.uninterval(me.watchOperationId);
                me.watchOperationId = null;
            }
    
            if (newAutoUpdate) {
                if (!provider) {
                    me.fireEvent('locationerror', me, false, false, true, null);
                    return;
                }
    
                try {
                    me.updateWatchOperation();
                } catch (e) {
                    me.fireEvent('locationerror', me, false, false, true, e.message);
                }
            }
        },
    
        /**
         * @private
         */
        updateWatchOperation: function() {
            var me = this,
                provider = me.getProvider();
    
            // The native watchPosition method is currently broken in iOS5...
    
            if (me.watchOperationId) {
                Ext.uninterval(me.watchOperationId);
            }
    
            function pollPosition() {
                provider.getCurrentPosition(
                    Ext.bind(me.fireUpdate, me),
                    Ext.bind(me.fireError, me),
                    me.parseOptions()
                );
            }
    
            pollPosition();
            me.watchOperationId = Ext.interval(pollPosition, this.getFrequency());
        },
    
        /**
         * Executes a onetime location update operation,
         * raising either a {@link #locationupdate} or {@link #locationerror} event.
         *
         * Does not interfere with or restart ongoing location monitoring.
         * @param {Function} callback
         * A callback method to be called when the location retrieval has been completed.
         *
         * Will be called on both success and failure.
         *
         * The method will be passed one parameter, {@link Ext.util.Geolocation}
         * (**this** reference), set to `null` on failure.
         *
         *     geo.updateLocation(function (geo) {
         *         alert('Latitude: ' + (geo !== null ? geo.latitude : 'failed'));
         *     });
         *
         * @param {Object} [scope]
         * The scope (**this** reference) in which the handler function is executed.
         *
         * **If omitted, defaults to the object which fired the event.**
         *
         * @param {Object} [positionOptions] (private) See W3C spec
         */
        updateLocation: function(callback, scope, positionOptions) {
            var me = this,
                provider = me.getProvider();
    
            var failFunction = function(message, error) {
                if (error) {
                    me.fireError(error);
                } else {
                    me.fireEvent('locationerror', me, false, false, true, message);
                }
                if (callback) {
                    callback.call(scope || me, null, me); //last parameter for legacy purposes
                }
            };
    
            if (!provider) {
                failFunction(null);
                return;
            }
    
            try {
                provider.getCurrentPosition(
                    //success callback
                    function(position) {
                        me.fireUpdate(position);
                        if (callback) {
                            callback.call(scope || me, me, me); //last parameter for legacy purposes
                        }
                    },
                    //error callback
                    function(error) {
                        failFunction(null, error);
                    },
                    positionOptions || me.parseOptions()
                );
            } catch (e) {
                failFunction(e.message);
            }
        },
    
        /**
         * @private
         */
        fireUpdate: function(position) {
            var me = this,
                coords = position.coords;
    
            this.position = position;
    
            me.setConfig({
                timestamp: position.timestamp,
                latitude: coords.latitude,
                longitude: coords.longitude,
                accuracy: coords.accuracy,
                altitude: coords.altitude,
                altitudeAccuracy: coords.altitudeAccuracy,
                heading: coords.heading,
                speed: coords.speed
            });
    
            me.fireEvent('locationupdate', me);
        },
    
        /**
         * @private
         */
        fireError: function(error) {
            var errorCode = error.code;
            this.fireEvent('locationerror', this,
                errorCode == error.TIMEOUT,
                errorCode == error.PERMISSION_DENIED,
                errorCode == error.POSITION_UNAVAILABLE,
                error.message == undefined ? null : error.message
            );
        },
    
        /**
         * @private
         */
        parseOptions: function() {
            var timeout = this.getTimeout(),
                ret = {
                    maximumAge: this.getMaximumAge(),
                    enableHighAccuracy: this.getAllowHighAccuracy()
                };
    
            //Google doesn't like Infinity
            if (timeout !== Infinity) {
                ret.timeout = timeout;
            }
            return ret;
        },
    
        destroy: function() {
            this.setAutoUpdate(false);
            this.callParent();
        }
    });