Git Product home page Git Product logo

geoext's Introduction

GeoExt

JavaScript Toolkit for Rich Web Mapping Applications.

Build Status Coverage Status dependencies Status devDependencies Status

GeoExt logo

GeoExt is Open Source and enables building desktop-like GIS applications through the web. It is a JavaScript framework that combines the GIS functionality of OpenLayers with the user interface savvy of the ExtJS library provided by Sencha.

Version 3 of GeoExt was the successor to the GeoExt 2.x-series and has been built atop the following versions of its base libraries: OpenLayers v3.x / v4.x and ExtJS 6.

With version 4 GeoExt supports the newest official installment v6.x of OpenLayers and ExtJS 6.2.

We are trying hard to keep up with developments on both our parent libraries. The current state of GeoExt is compatible with ExtJS 6.2.0 and OpenLayers 7.1.0. This state is released as GeoExt v4.0.0.

OpenLayers ExtJS GeoExt
7.1.0 6.2.0 5.0.x
6.5.0 6.2.0 4.0.x
4.6.5 6.2.0 3.4.0 & 3.3.x & 3.2.0
3.20.1 / 4.3.x 6.2.0 3.1.0
3.20.1 6.2.0 3.0.0

More information on GeoExt

Have a look at the official homepage: https://geoext.github.io/geoext/

You will find examples, API documentation (with and without inherited functionality from ExtJS), links to mailinglists and more over there.

What you see on https://geoext.github.io/geoext/ are the contents of the gh-pages-branch. If you encounter anything that should be fixed, please issue a pull request against that branch and we will merge it as soon as possible.

How to use GeoExt inside your Sencha app

You can use GeoExt either via an npm install @geoext/geoext in your application folder, or (if you want the latest and greatest), you can use it from a git clone of this repository.

Configuring your apps classpath

You will have to adjust the classpath in you app.json to include geoext3, like below. Depending on how you retrieved the code from the step before, you will have to adapt the path. When you installed geoext3 via npm, the path needs to look like ./node_modules/@geoext/geoext/src. Else it will be the folder where you cloned the repository into.

    "classpath": [
        "app",
        "${toolkit.name}/src",
        "./lib/geoext/src"
    ]

In the snippet above, lib/geoext is a git clone of the GeoExt repo.

GeoExt also offers components, which are only compatible with the classic toolkit of ExtJS (e.g. StateProvider or GeocoderCombo). In case you want to use them you also have to add the classic folder to the classpath. So your complete classpath definition could look like below:

    "classpath": [
        "app",
        "${toolkit.name}/src",
        "./lib/geoext/src",
        "./lib/geoext/classic"
    ]

To help with your first GeoExt project, follow the instructions provided to build a GeoExt Universal app. This app runs on the desktop and on mobile.

Examples

Classic Toolkit

https://geoext.github.io/geoext/master/examples/component/map.html

Modern Toolkit

Want to contribute? Yes, please ๐Ÿ˜€

Read the hints for developers to get started. We look forward to your contributions!

Initial Codesprint

To kickstart the new GeoExt 3 project a code sprint has been done in Bonn from 17th to 19th of June 2015. For more informations check the following links: Code sprint WIKI page, Official blog post of code sprint day 1, Official blog post of the code sprint days 2 and 3


OSGeo Community Project

GeoExt is an OSGeo Community project

geoext's People

Contributors

ahennr avatar annarieger avatar bartvde avatar bentrm avatar buehner avatar chrismayer avatar dnlkoch avatar geographika avatar greenkeeper[bot] avatar greenkeeperio-bot avatar hwbllmnn avatar jakobmiksch avatar jansule avatar jgrocha avatar juliensam avatar kaivolland avatar marcjansen avatar patryksosinski avatar simonseyock avatar weskamm avatar woodstocktm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geoext's Issues

Generate documentation using one process only to reenable the API docs autoupdate

(See also: #164)

For the record, I think I have managed to fix it with the following commits:

  • cc1ed7d API documentation formatting
  • 04f2987 Update secured environment variable
  • c198ca1 Don't push silently
  • 56c8f1a Temporarily allow output of update-gh-pages.sh
  • 1c1d2e6 Disable multiple processes when running jsduck
  • 5c96cf5 No output from ^A^A./ci/update-gh-pages.sh sorry for the bad commit message
  • 981249c Reuse old secured environment variable
  • 922d7ee Push silently again
  • 15a0643 Minor API doc formatting change
  • 57c9509 Push quietly, not silently

Here is the combined diff of these changes:

diff --git a/ci/update-gh-pages.sh b/ci/update-gh-pages.sh
index b7853da..979cce9 100755
--- a/ci/update-gh-pages.sh
+++ b/ci/update-gh-pages.sh
@@ -99,6 +99,7 @@ jsduck \
      --title="$GEOEXT_PACKAGE_NAME $GEOEXT_PACKAGE_VERSION$DOC_SUFFIX Documentation" \
      --output="$DOCS_DIR/" \
      --eg-iframe=$TRAVIS_BUILD_DIR/docresources/eg-iframe.html \
+     --processes=0 \
      $TRAVIS_BUILD_DIR/src/

 #3.2 โ€ฆ with ExtJS
@@ -110,6 +111,7 @@ jsduck \
      --eg-iframe=$TRAVIS_BUILD_DIR/docresources/eg-iframe.html \
      "$DOWN_DIR/ext-$SENCHA_EXTJS_VERSION/packages/core/src" \
      "$DOWN_DIR/ext-$SENCHA_EXTJS_VERSION/classic/classic/src" \
+     --processes=0 \
      $TRAVIS_BUILD_DIR/src/

 #4. done.
diff --git a/src/mixin/SymbolCheck.js b/src/mixin/SymbolCheck.js
index cf3fe80..c863e07 100644
--- a/src/mixin/SymbolCheck.js
+++ b/src/mixin/SymbolCheck.js
@@ -34,7 +34,7 @@
  *     });
  *
  * Since this sort of checking usually only makes sense in debug mode, you can
- * additionally wrap the `symbols`-configuration in these <debug>-line
+ * additionally wrap the `symbols`-configuration in these `<debug>`-line
  * comments:
  *
  *     Ext.define('MyNewClass.DependingOnOpenLayersClasses', {

You can see that the changeset is actually really trivial.

Thanks @weskamm for allowing me to temporarily commit directly without review.

This issue will directly be closed, but I create it so we have a reference.

Road to a "universal app"

In order to use GeoExt3 in an universalapp, in other words, with toolkit "classic" and "modern" or "ext" and "touch", we need to harmonize some components.

The biggest issue are the different component names (and proeprties / methods..), e.g. Ext.panel.Panel in the classic toolkit and Ext.Panel in the modern toolkit.
Because of this, we currently cannot build an universalapp with GeoExt included in the simple way, which means requiring the GeoExt Package in the app.json file, as e.g. the GeoExt.panel.Popup extends from Ext.panel.Panel, which cannot bre resolved in the modern toolkit.

This can be fixed relatively easily by changing the extending class to something more low level, like Ext.Component.

There will be of course some components which always will rely on a Ext.panel.Panel, like the treepanel. These classes need to stay as is and should get an "modern" counterpart, something like a nested list for maplayers.

Another problem is that the method to initialize a component is named differently in the toolkits:
initComponent in the classic, and initialize in the modern one.
Two options here:
1.) A GeoExt class needs to provide a universal initialisation method which is called from either initComponent (classic) or initialize (modern).

2.) An alternative would be to use the constructor, which is shared between the both frameworks and should be preferred if possible.

I adopted the second approach to the GeoExt.component.map in the PR #63.
That way we currently can build a universal application using the Map Component with GeoExt.

To keep the build of a universal app intact while having mixed classes of both toolkits in GeoExt, one can currently describe the build section in the app.json as follows:

"builds": {
        "classic": {
            "toolkit": "classic",
            "theme": "theme-neptune",
            "requires": [
                "GeoExt",
                "font-awesome"
            ]
        },
        "modern": {
            "toolkit": "modern",
            "theme": "theme-neptune"
        }
    }

As you can see, there is no require on GeoExt for the modern toolkit. Instead we use explicit pathes for GeoExt-Components in the classpath declaration of the app.json file:

"classpath": "app,${toolkit.name}/src,packages/remote/GeoExt/src/component,packages/remote/GeoExt/src/data",

So to get GeoExt3 compatible with the modern toolkit, some more classes need adjustments.
I will extend this Issue when Classes and Problems arise.
Feel free to give opinions / thoughts and problems you may observe

FOSS4G code sprint

Hi,
I'm available to work on GeoExt 3 at FOSS4G code sprint. I have experience with GeoExt 2 and ExtJs 4.x. If some contributor is able to work on GeoExt 3 at FOSS4G code sprint, I will be glad to help.
I would like to create an example with GeoExt 3 + Ext.Direct + node.js.
Regards!

Why GPL licensing?

I would like to see the licensing revert to the previous licensing model, i.e. not GPL.

I don't want to debate the merits of the various licensing models but GPL is more restrictive than the previous model. I do know that ExtJS is GPL but they offer a commercial license as well. Open Layers has BSD licensing. Making the license more restrictive limits the set of people who can use the software.

Failing Test for GeoExt.data.serializer.Vector

At the moment we have a failing test:

1) GeoExt.data.serializer.Vector serializing behaviour serializes as expected:

      Error: expected { geoJson: 
   { type: 'FeatureCollection',
     features: [ [Object], [Object], [Object], [Object] ] },
  opacity: 0.8,
  style: 
   { version: 2,
     '[_gx3_style_0 = \'ext-110\']': { symbolizers: [Object] },
     '[_gx3_style_1 = \'ext-111\']': { symbolizers: [Object] },
     '[_gx3_style_0 = \'ext-112\']': { symbolizers: [Object] },
     '[_gx3_style_0 = \'ext-113\']': { symbolizers: [Object] },
     '[_gx3_style_1 = \'ext-114\']': { symbolizers: [Object] } },
  type: 'geojson' } to sort of equal { geoJson: 
   { type: 'FeatureCollection',
     features: [ [Object], [Object], [Object], [Object] ] },
  opacity: 0.8,
  style: 
   { version: 2,
     '[_gx3_style_0 = \'ext-110\']': { symbolizers: [Object] },
     '[_gx3_style_1 = \'ext-111\']': { symbolizers: [Object] },
     '[_gx3_style_0 = \'ext-112\']': { symbolizers: [Object] },
     '[_gx3_style_0 = \'ext-113\']': { symbolizers: [Object] },
     '[_gx3_style_1 = \'ext-114\']': { symbolizers: [Object] } },
  type: 'geojson' }
      + expected - actual

           }
           "[_gx3_style_0 = 'ext-113']": {
             "symbolizers": [
               {
      -          "fontColor": "#333333"
                 "fontFamily": ""sans serif""
                 "fontSize": "16px"
                 "fontWeight": "normal"
                 "label": "GeoExt3"
           }
           "[_gx3_style_1 = 'ext-114']": {
             "symbolizers": [
               {
      -          "fontColor": "#333333"
                 "fontFamily": ""sans serif""
                 "fontSize": "16px"
                 "fontWeight": "normal"
                 "label": "Ngeo"

FeatureStore with fields config do not work

If you create an instance of GeoExt.data.store.Features with an explicit fields configuration the creation fails in case of connecting a grid with a FeatureRenderer in one of its columns (Mostly like we do in the official FeatureGrid example.

Here is the failing code:

var featStore = Ext.create('GeoExt.data.store.Features',  {
  fields: ['city'],
  layer: vectorLayer,
  map: olMap
});
var grid = Ext.create('Ext.grid.Panel', {
  border: true,
  region: 'east',
  store: featStore,
  columns: [
    {
        xtype: 'widgetcolumn',
        width: 40,
        widget: {
            xtype: 'gx_renderer'
        },
        onWidgetAttach: function(column, gxRenderer, record) {
         // update the symbolizer with the related feature
          var feature = record.olObject;
         gxRenderer.update({
            feature: feature,
            symbolizers: featRenderer.determineStyle(record)
         });
       }
     },
     {text: 'Name', dataIndex: 'city', flex: 2}
 ],
 width: 250
});

In case you remove the fields declaration it works.

A first short look into this topic showed me that the main reason of failing is the fact that the records in the store do not have an olObject. So no feature could be retrieved from the record.

Build failed with extjs6

Hi, I try to refresh it but got some errors like
"Failed to resolve dependency Ext.tree.Panel for file GeoExt.tree.Panel"
"com.sencha.exceptions.ExNotFound: Unknown definition for dependency : Ext.tree.Panel"

Not quite sure it is a bug or not.

I use exactly same step to refresh as README said.

Cheers

Allow preview of examples in GeoExt 3 documentation

To allow users to see and change the code of the examples on the documentation, we need to:

  • Create a small html container geoext3/docresources/eg-iframe.html that will be used to run the examples. This container has to include ExtJs and OL libraries.
  • Improve the geoext3/ci/update-gh-pages.sh deploy script.
    • jsduck must be called with an additional parameter --eg-iframe=docresources/eg-iframe.html
    • Copy the extjs build (downloaded to create GeoExt package) to the docs folder, to enable the live preview of the examples.
  • Last, we need to write the examples in the source code.

Missing class definition in models extending GeoExt.data.model.OlObject?

All child models of GeoExt.data.model.OlObject try to transform a possibly given plain object to an appropriate OpenLayers object (see https://github.com/geoext/geoext3/blob/master/src/data/model/OlObject.js#L96).
But the class used for this is ol.Object in all cases. Shouldn't it be a transformation to the child model's OpenLayer class pendant? E.g. that GeoExt.data.model.Feature knows that it has to create ol.Feature objects? Or am I missing anything?

In a quick test overwriting the member variable olClass in every child model of GeoExt.data.model.OlObject did the trick.

Adding OverviewMap Make The Map hidden

Hi I'm a bit new to geoext3
I saw the example of making OverviewMap and I tried to make one like it
but whenever I add the overviewmap the main map disappear
here's my code
(the sample is working fine on my device)

Ext.require([
    'GeoExt.component.Map',
    'Ext.panel.Panel',
    'Ext.Viewport' , 
    'GeoExt.component.OverviewMap'
]);

var olMap;
var mapComponent;
var mapPanel;

Ext.application({
    name: 'MapComponent',
    launch: function() {
        var description;
       
        var projection = new ol.proj.Projection({
            code: 'urn:x-ogc:def:crs:EPSG:2000',
            units: 'm',
            axisOrientation: 'neu',
            global: false
        });

        olMap = new ol.Map({
            layers: [
                new ol.layer.Image({
                    source: new ol.source.ImageWMS({
                        ratio: 1,
                        url: 'http://localhost:8080/geoserver/wms',
                        params: {
                            'FORMAT': 'image/png',
                            'VERSION': '1.1.1',
                            STYLES: '',
                            LAYERS: 'Syria'
                        }  
                    })
                })
            ],
            view: new ol.View({
                projection: projection
            })
        });
        
        mapComponent = Ext.create('GeoExt.component.Map', {
            map: olMap
        });

        mapPanel = Ext.create('Ext.panel.Panel', {
            title: 'GeoExt.component.Map Example',
            region: 'center',
            layout: 'fit',
            border:false ,            
            items: [mapComponent]
        });

        description = Ext.create('Ext.panel.Panel', {
            contentEl: 'description',
            title: 'Description',
            region: 'east',
            width: 300,
            border: true,
            bodyPadding: 5
        });
        
      var overviewMap = Ext.create('GeoExt.component.OverviewMap', {
            parentMap: olMap
        });
        
        var ovMapPanel1 = Ext.create('Ext.panel.Panel', {
            title: 'OverviewMap (default)',
            flex: 1,
            layout: 'fit',
            items: overviewMap
        });
        
        Ext.create('Ext.Viewport', {
            layout: 'border',
            items: [
                mapPanel ,
                {
                    xtype: 'panel',
                    region: 'east',
                    width: 400,
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                        description 
                  //      ,ovMapPanel1 
                        
                        
                    ]
                }
            ]
        });
        
        var bounds = [-50, -50,
                50, 50];
       olMap.getView().fit(bounds, olMap.getSize());
    }
});

GeoExt 3 Dual licensing

The GeoExt PSC has been actively discussing with Sencha about the ExtJS
licensing change that prevented us to use GeoExt with a commercial ExtJS
license. The change made in version 6 forced us to switch from a BSD
licence to GPL preventing GeoExt to be used with a Commercial ExtJS.

After several months we are really pleased to announced an agreement
from Sencha to Dual-Licence GeoExt 3. Users of GeoExt 3 will be able to
get it under GPLv3 or, if they own an ExtJS commercial licence, use it
under a BSD licence.

To be able to proceed with this licence change we require a written
agreement from every code contributors:

Best regards,
The GeoExt PSC team

Running coverage report command scrambles working copy if parse error present

Title pretty much says it. With any parse error in a test spec or in a source file in src running the html-coverage command fries the src directory. Of course this never happened to me, because I lint all the time.. :neckbeard:

In the worst case, one may recover changes from the generated/copied src_old directory but this may be a bit too exciting.

Use ol.Map layerGroup as root node of GeoExt.data.TreeStore

Right now, the tree store is init with a plain root node. When expanded the actual layer tree is init by appending GeoExt.data.model.LayerTreeNodes.

As the LayerTreeStore is initialized with the ol.layer.Group that can be retrieved from ol.Map#getLayerGroup it should be used as root right away.

What is "Repository Committer Name"

I am interested in geoext/geoext3 project, I'd like join and contribute. When I fill the agreement, I don't know what is "Repository Committer Name"? pick up a name or username of my GitHub account? Thanks.

Release v3.0.0

@chrismayer and me have agreed on the following procedure:

  • I will release v3.0.0 (probably Monday, 2017-03-13)
  • Directly afterwards, I will remove the part where the CI script would auto-update the published package for every commit on master
    • This means that people who want to use the package mechanism to load GeoExt, need to stick with v3.0.0 and will not directly receive changes on master.
    • This also means, that we have to think about how we want to publish a package for say v3.0.1. More logic / magic in the ci/update-gh-pages.sh script is needed.
    • โœ… done #263
  • I will update the website
    • to link to the published v3.0.0 resources (docs and examples)
    • and (less prominent) the published master resources (docs and examples)

During an upcoming event (FOSSGIS 2017), @chrismayer and me want to figure out what needs to be done for the above tasks.

Roadmap to release v3.0.0

This issue tries to list the things we should do before we can release v3.0.0. As such we will probably edit the content.

In order to see where we are, I propose to release an early v3.0.0-alpha.1 soon. Then we can tackle any of the following for subsequent pre releases or the final v3.0.0.

  • Fix FeatureStore Bug #171
  • Add an example for a universal app or link to a repo containing one (see also e.g. #115)
  • Add an example for all the different aspects of the library (At least double check we have one)
    • Update or remove the MapViewForm example (see also e.g. #54), done with #121
  • Test untested lines/statements. Can we reach 90% coverage?
  • Update the README.md and probably restructure it with content available in DEVELOPMENT.md
  • Double check the packaging done by the CI.
    • Does the subfolder generation work when we are building for a git-tag?
    • Can we release the packages under a subfolder? Currently one sencha package replaces the previous one. This is IMO only OK while we don't have v3.0.0. I never want to loose the v3.0.0 package, even if we already are at say v3.1.0.
  • Better API docs with more inline examples. See #118
  • Update issue #65 "Road to universal app".
  • Fix or delay remaining issues
    • Popup enhancements and remaining issues #25
  • Check if and how we can publish the package also in the sencha Market
  • Document differences to previous versions. If we provide fewer functionality, hint at a possible solution without dedicated components.

Please feel free to share your thoughts and ideas here. For any of the above tasks fell free to add dedicated tickets (and link them here).

Build a new GeoExt 3 application using Sencha cmd

It is not easy to create a first GeoExt 3 application with the documentation provided.
To address the issues discussed in #65 (excellent discussion!) and the problems mentioned in #89 we should provide a simple example (the GeoExt 3 Hello world).

Probably the usage examples should go to the GeoExt 3 documentation. For now, I wrote a small tutorial in markdown to help new users to build a proper ExtJS 6 application with the GeoExt 3 package. I also update the Readme.md to point to the tutorial, replacing the existing brief notes.

The example provided is ready to run on both toolkits (classic and modern).

I would appreciate some feedback about what we should put on this small example. I did the minimum possible to have a GeoExt 3 based application running using the Sencha way.

Help tools measure Webgis

Good Morning.
I'm trying to create a web mapping for a project of the university, and as I am a beginner to program come here to ask for your help.
I used the example of the Tree Panel of the geoext3 site and changed to what I needed.
Only now I have to join measurement tool as lengths and areas such as openlayrs 3
http://openlayers.org/en/latest/examples/measure.html
Can anyone give me a hand was very urgent.
Here's my link to my web mapping
https://www.dropbox.com/s/2ri8a59yjqcxb9p/WebSig.rar?dl=0
Thank you all
greetings

FeatureRenderer does not work with layers with styleFunction

The FeatureRenderer (GeoExt.component.FeatureRenderer) does not work properly when drawing a feature, which derives a style by its layer's style function.

It seems that the arguments of the ol.StyleFunction are wrong in the case described above. Normally that function takes an ol.Feature and a number representing the view's resolution, but here the function only has the numeric argument. So if you refer to the feature in the style function you will get an exception.

Naming strategy for non-public methods or properties

We should agree on a common way of how we want to name things that are private, i.e. not exposed as part of a public API.

  • Should we use leading or dangling underscores (_)?
  • Or do we don't need this type of additional warning for users?

In the current codebase we have a mixture of these things, and a harmonized strategy would be cool.

I personally do not care about this too much, but like the idea that non-public methods also look 'special'. IMO this hints to users who learn about these properties/methods (e.g. via console.log() and friends), that these may change and/or be replaced without further notice.

Share your thoughts here.

Remaining popup issues and wanted enhancements

Since #14 we have popups, and since #17 they have been enhanced in several minor ways.

We want to do the following stuff:

  • More Unit tests
  • Get rid of anchor image, CSS solution is preferred

Maybe even an inline data URI would already be efficient enough, no need IMO for fully fledged CSS-arrows

  • Make closeable

With regard to the last point:

We create the ol.Overlay() with stopEvent having the default of true, this is why buttons or closable do not work as intended.

If we explicitly include stopEvent: true, then buttons e.g. work, but you'll experience other odd behaviour. I have to think about how we want to approach that.

QGIS Client II

Hi,
The QGIS community wants to develop a new QGIS Web Client. The current QGIS Web Client is based on GeoExt 2.
They already wrote a detailed requirements document. Are we able to finish GeoExt 3 to be usable by the new QGIS Web Client?
It would be great...

Uncaught Error: The schema can only be reconfigured once

Hi,

When using GeoExt 3 with applications that also extends 'Ext.data.Model', the browser complains with the error ๐Ÿ’ฅ:

Uncaught Error: The schema can only be reconfigured once

This was discussed on sencha forum and the solution is to provide an id for the schema.

So, I would like to add an id to schema in our class 'GeoExt.data.model.Base'.

The class would become:

Ext.define('GeoExt.data.model.Base', {
    extend: 'Ext.data.Model',
    requires: [
        'Ext.data.identifier.Uuid'
    ],
    schema: {
        id: 'geoext-schema',
        namespace: 'GeoExt.data.model'
    },
    identifier: 'uuid'
});

Does anyone already experienced this yet? Comments?

LayerTree - wrong layer ordering for groups

Hi again,

I think there is a bug with layer ordering for groups (or maybe i am doing something wrong). Assume that i have 5 layers and i create a group:
var layers = [layer4, layer3, layer2, layer1, layer0];
var group = new ol.layer.Group({
layers : layers
});

Now for each layer or group in GeoExt.data.store.LayersTree method addLayerNode is called. OpenLayers return layers ( map.getLayers(), or group.getLayers()) ordered by index so addLayerNode is called first for the most bottom layer. With inverseLayerOrder parameter set to true the following code is called:

var layerIdx = GeoExt.util.Layer.getLayerIndex(layerOrGroup, group);

if (me.inverseLayerOrder) {
var totalInGroup = group.getLayers().getLength();
layerIdx = totalInGroup - layerIdx - 1;
}

which calculates following indexes:
layer4, map layerIdx = 0 --> 5 - 0 - 1 = 4
layer3, map layerIdx = 1 --> 5 - 1 - 1 = 3
layer2 --> 2
layer1 --> 1
layer0 --> 0

and then for each layer following is called:
parentNode.insertChild(layerIdx, layerNode).

The problem is that inserting node at specified index when there are no other elements in array inserts element at 0 position (i don't know if it is a ExtJS bug or desired bahaviour?), so
layer4 gets inserted at idx 0
layer3 gets inserted at 1
layer2 --> 2
layer3 --> again at 1 pushing other nodes
layer0 --> 0

so at the end it is totally messed up.

GeoExt3 Universal App

Hi there, I was following the (really nice) guide and, while it ends up working, it shows an error regarding one of the GeoExt Classes when running sencha app refresh.

sdout shows:

04:39:09 ~/www/MyGeoExtApp$ ../../bin/Sencha/Cmd/sencha app refresh
Sencha Cmd v6.0.2.14
[INF] Processing Build Descriptor : classic
[WRN] Failed to resolve package basepackage
[WRN] Failed to resolve package basepackage
[WRN] Failed to resolve package basepackage
[INF] Starting server on port : 1841
[INF] Mapping http://localhost:1841/~cmd to /home/cg/bin/Sencha/Cmd/6.0.2.14...
[INF] Mapping http://localhost:1841/ to /home/cg/www/MyGeoExtApp...
[INF] Application available at http://localhost:1841
[WRN] Failed to resolve package basepackage
[INF] Loading app json manifest...
[INF] Appending content to /home/cg/www/MyGeoExtApp/bootstrap.js
[INF] Writing content to /home/cg/www/MyGeoExtApp/classic.json
[INF] Processing Build Descriptor : modern
[INF] Starting server on port : 1841
[INF] Mapping http://localhost:1841/~cmd to /home/cg/bin/Sencha/Cmd/6.0.2.14...
[INF] Mapping http://localhost:1841/ to /home/cg/www/MyGeoExtApp...
[INF] Application available at http://localhost:1841
[INF] Loading app json manifest...
[ERR] C2008: Requirement had no matching files (GeoExt.util.Layer) -- /home/cg/www/MyGeoExtApp/packages/remote/GeoExt/src/data/store/LayersTree.js:28:10
[ERR] 
[ERR] BUILD FAILED
[ERR] com.sencha.exceptions.ExBuild: Failed to find any files for /home/cg/www/MyGeoExtApp/packages/remote/GeoExt/src/data/store/LayersTree.js::ClassRequire::GeoExt.util.Layer
[ERR] 
[ERR] Total time: 4 seconds
[WRN] 1 threads could not be stopped
[ERR] The following error occurred while executing this line:
/home/cg/bin/Sencha/Cmd/6.0.2.14/plugins/ext/current/plugin.xml:427: The following error occurred while executing this line:
/home/cg/www/MyGeoExtApp/.sencha/app/build-impl.xml:381: The following error occurred while executing this line:
/home/cg/www/MyGeoExtApp/.sencha/app/init-impl.xml:382: com.sencha.exceptions.ExBuild: Failed to find any files for /home/cg/www/MyGeoExtApp/packages/remote/GeoExt/src/data/store/LayersTree.js::ClassRequire::GeoExt.util.Layer

After that, if I run sencha app watch everything seems to work, just to let you know. As I am just starting to try this I'm not able to tell if further errors are generated or what its consequences are. Browser console shows no errors and the map tab looks fine.
Thanks

Dashboard example with GeoExt 3 panel

Hi,

I hope that 2016 is the GeoExt 3 year! The many months of pregnancy should already be coming to an end.

I added to the well known ExtJS Dashboard Demo a map, with a synchronized grid and a tree layer. It does not add much to the existing examples, but the result looks great and it is a starting point for those less familiar with the ExtJS 6 view model and view controller architecture.

I've created a panel geo.MapPanel with 3 views:

    items: [{
        xtype: 'geo-mapcanvas',
        responsiveCls: 'big-100',
        height: 400
    }, {
        xtype: 'geo-mapgrid',
        reference: 'geo-mapgrid',
        responsiveCls: 'big-60'
    }, {
        xtype: 'geo-tree',
        responsiveCls: 'big-40'
    }]

and all these components inherit the same view model of this panel. I add dynamically the feature store and the tree store to this view model, to keep the data related to the map in one well defined place.

I upload the source to github and published a demo online.
Any suggestions to improve this example? Should I try to add more features?

If the example is good for others, I can added it to the GeoExt 3 examples. Otherwise I'll keep it in my github.

Happy 2016 ๐Ÿป ๐Ÿธ to all GeoExt developers!

Website lists old dependencies

Just a reminder to

  • update the gh-pages branch to reflect the actual state of the underlying frameworks
  • mention the CMD version tested and used with the package

Extending LayersTree and LayerTreeNode

Hi,

I need to add functionalities to layerTreeNode (setting my own icons etc.). So i created my own LayerTree and LayerTreeNode classes that extend proper geoext classess. Something like this:

//store
Ext.define('XX.store.LayerTree', {
    requires:[
       'GeoExt.data.store.LayersTree', 
       'XX.geoext.TreeNode'
    ],
    extend: 'GeoExt.data.store.LayersTree',
    model: 'XX.geoext.TreeNode',
});

//node
Ext.define('XX.geoext.TreeNode',{
    requires:['GeoExt.data.model.LayerTreeNode'],
    extend:'GeoExt.data.model.LayerTreeNode',
    constructor: function() {
        var layer;
        this.callParent(arguments);
        layer = this.getOlLayer();
        if (layer instanceof ol.layer.Base) {
            var icon = layer.get('icon');
            if (icon) {
                this.set('icon', 'img/treeIcons/' + icon + '.png');
            }else if (layer instanceof ol.layer.Group){
                this.set('icon', 'img/treeIcons/folder.png');
            }else{
                this.set('icon', 'img/treeIcons/map.png');
            }
            var expanded = (layer.layerConfig && layer.layerConfig.expand) || layer.get('expanded');
            if (expanded) {
                this.set('expanded', true);

            }
        }
    }
});

and now there is a problem as in LayersTree#addLayerNode the node is created using static className not a model name:

var layerNode = Ext.create('GeoExt.data.model.LayerTreeNode',
            layerOrGroup
        );

My idea to fix this is to change above to:

var layerNode = Ext.create(this.model,
            layerOrGroup
    );

Should i create PR for this?

layersTree stops working/slow

I create a test for drag drop of kml files.
I discovered the browser did not respond after adding 7+ files. I discovered it was the layersTree that failed. If i deactivate the Update of layersTree i can drag and drop 150+ kml files without any problems.

I did a test without drag and drop too. I created a button with a handler that run treestore.onLayerCollectionChanged().
The map has 2 base maps and 3 overlayers. If i click the Button that will activate the refresh of the legend i can push the button like 7 times and the refresh gets slower and slower.

I did not have the time to look more into the function yet.
I also noticed that you can add too many layers that the layersTree will not show all. I will get the actual max numbers on monday.

Print module doesn't work

By clicking on "print button" the module doesn't work.

Uncaught Error: Cannot get uid of non-object. [ext-all.js:22]

Building in a ExtJS 6.0.0.640 workspace changes sass/example/bootstrap.js

The last upgrade for the final 6.0.0.640 GPL ExtJS version was quite possibly made from a non-ExtJS 6.0.0.640 workspace, so that a build in such aworkspace leads to the following diff:

diff --git a/sass/example/bootstrap.js b/sass/example/bootstrap.js
index 7380753..5fb69f7 100644
--- a/sass/example/bootstrap.js
+++ b/sass/example/bootstrap.js
@@ -11,6 +11,7 @@ var Ext = Ext || {};
 Ext.Boot = Ext.Boot || (function (emptyFn) {

     var doc = document,
+        _emptyArray = [],
         _config = {
             /*
              * @cfg {Boolean} [disableCaching=true]
@@ -278,17 +279,26 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
                 return platforms;
             },

-            filterPlatform: function (platform) {
-                platform = [].concat(platform);
-                var len, p, tag;
+            filterPlatform: function (platform, excludes) {
+                platform = _emptyArray.concat(platform || _emptyArray);
+                excludes = _emptyArray.concat(excludes || _emptyArray);

-                for (len = platform.length, p = 0; p < len; p++) {
-                    tag = platform[p];
-                    if (_tags.hasOwnProperty(tag)) {
-                        return !!_tags[tag];
-                    }
+                var plen = platform.length,
+                    elen = excludes.length,
+                    include = (!plen && elen), // default true if only excludes specified
+                    i, tag;
+
+                for (i = 0; i < plen && !include; i++) {
+                    tag = platform[i];
+                    include = !!_tags[tag];
                 }
-                return false;
+
+                for (i = 0; i < elen && include; i++) {
+                    tag = excludes[i];
+                    include = !_tags[tag];
+                }
+
+                return include;
             },

             init: function () {
@@ -345,14 +355,6 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {

                 Boot.detectPlatformTags();
                 Ext.filterPlatform = Boot.filterPlatform;
-
-                // temporary workaround for https://sencha.jira.com/browse/EXTJS-16101
-                if (_tags.ios) {
-                    var meta = document.createElement('meta');
-                    meta.setAttribute('name', 'viewport');
-                    meta.setAttribute('content', 'width=device-width, height=device-height, initial-scale=1, maximum-scale=1, user-scalable=no');
-                    document.head.appendChild(meta);
-                }
             },

             /*
@@ -961,20 +963,22 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
             cache = (cfg.cache !== undefined) ? cfg.cache : (loader && loader.cache),
             buster, busterParam;

-        if(cache === undefined) {
-            cache = !Boot.config.disableCaching;
-        }
+        if (Boot.config.disableCaching) {
+            if (cache === undefined) {
+                cache = !Boot.config.disableCaching;
+            }

-        if(cache === false) {
-            buster = +new Date();
-        } else if(cache !== true) {
-            buster = cache;
-        }
+            if (cache === false) {
+                buster = +new Date();
+            } else if (cache !== true) {
+                buster = cache;
+            }

-        if(buster) {
-            busterParam = (loader && loader.cacheParam) || Boot.config.disableCachingParam;
-            buster = busterParam + "=" + buster;
-        };
+            if (buster) {
+                busterParam = (loader && loader.cacheParam) || Boot.config.disableCachingParam;
+                buster = busterParam + "=" + buster;
+            }
+        }

         _apply(cfg, {
             charset: charset,
@@ -1454,17 +1458,21 @@ Ext.Microloader = Ext.Microloader || (function () {
         _warn = function (message) {
             console.log("[WARN] " + message);
         },
-        _privatePrefix = '_sencha',
-        _location = window.document.location,
-        _documentUri = _location.protocol + '//' + _location.hostname + _location.pathname + _location.search,
-        postProcessor;
-
-    // Returns a unique key to a manifest file
-    function getManifestStorageKey (url) {
-        return  _privatePrefix + '-' + _documentUri + url;
-    }
+        _privatePrefix = '_ext:' + location.pathname,
+
+        /**
+         * The Following combination is used to create isolated local storage keys
+         * '_ext' is used to scope all the local storage keys that we internally by Ext
+         * 'location.pathname' is used to force each assets to cache by an absolute URL (/build/MyApp) (dev vs prod)
+         * 'url' is used to force each asset to cache relative to the page (app.json vs resources/app.css)
+         * 'profileId' is used to differentiate the builds of an application (neptune vs crisp)
+         * 'Microloader.appId' is unique to the application and will differentiate apps on the same host (dev mode running app watch against multiple apps)
+         */
+        getStorageKey = function(url, profileId) {
+            return  _privatePrefix + url + '-' + (profileId ? profileId + '-' : '') + Microloader.appId;
+        },
+        postProcessor, _storage;

-    var _storage;
     try {
         _storage = window['localStorage'];
     } catch(ex) {
@@ -1474,14 +1482,20 @@ Ext.Microloader = Ext.Microloader || (function () {
     var _cache = window['applicationCache'],
         // Local Storage Controller
         LocalStorage = {
-            clearAllPrivate: function() {
+            clearAllPrivate: function(manifest) {
                 if(_storage) {
+
+                    //Remove the entry for the manifest first
+                    _storage.removeItem(manifest.key);
+
                     var i, key,
                         removeKeys = [],
+                        suffix = manifest.profile + '-' + Microloader.appId,
                         ln = _storage.length;
                     for (i = 0; i < ln; i++) {
                         key = _storage.key(i);
-                        if (key.indexOf(_privatePrefix) === 0) {
+                        // If key starts with the private key and the suffix is present we can clear this entry
+                        if (key.indexOf(_privatePrefix) === 0 && key.indexOf(suffix) !== -1) {
                             removeKeys.push(key);
                         }
                     }
@@ -1529,7 +1543,7 @@ Ext.Microloader = Ext.Microloader || (function () {
             }

             this.type = cfg.type;
-            this.key = cfg.manifestKey + '-' + this.assetConfig.path;
+            this.key = getStorageKey(this.assetConfig.path, cfg.manifest.profile);

             if (cfg.loadFromCache) {
                 this.loadFromCache();
@@ -1540,7 +1554,7 @@ Ext.Microloader = Ext.Microloader || (function () {
             shouldCache: function() {
                 return _storage && this.assetConfig.update && this.assetConfig.hash && !this.assetConfig.remote;
             },
-            
+
             is: function (asset) {
                 return (!!asset && this.assetConfig && asset.assetConfig && (this.assetConfig.hash === asset.assetConfig.hash))
             },
@@ -1577,20 +1591,38 @@ Ext.Microloader = Ext.Microloader || (function () {
                 this.content = cfg.content;
             }
             this.assetMap = {};
-            
+
             this.url = cfg.url;
             this.fromCache = !!cfg.cached;
             this.assetCache = !(cfg.assetCache === false);
-            this.key = getManifestStorageKey(this.url);
+            this.key = getStorageKey(this.url);

             // Pull out select properties for repetitive use
+            this.profile = this.content.profile;
             this.hash = this.content.hash;
             this.loadOrder = this.content.loadOrder;
             this.deltas = this.content.cache ? this.content.cache.deltas : null;
             this.cacheEnabled = this.content.cache ? this.content.cache.enable : false;
-            
+
             this.loadOrderMap = (this.loadOrder) ? Boot.createLoadOrderMap(this.loadOrder) : null;
-            
+
+            var tags = this.content.tags,
+                platformTags = Ext.platformTags;
+
+            if (tags) {
+                if (tags instanceof Array) {
+                    for (var i = 0; i < tags.length; i++) {
+                        platformTags[tags[i]] = true;
+                    }
+                } else {
+                    Boot.apply(platformTags, tags);
+                }
+
+                // re-apply the query parameters, so that the params as specified
+                // in the url always has highest priority
+                Boot.apply(platformTags, Boot.loadPlatformsParam());
+            }
+
             // Convert all assets into Assets
             this.js = this.processAssets(this.content.js, 'js');
             this.css = this.processAssets(this.content.css, 'css');
@@ -1599,7 +1631,7 @@ Ext.Microloader = Ext.Microloader || (function () {
         Manifest.prototype = {
             processAsset:  function(assetConfig, type) {
                 var processedAsset = new Asset({
-                    manifestKey: this.key,
+                    manifest: this,
                     assetConfig: assetConfig,
                     type: type,
                     loadFromCache: this.assetCache
@@ -1652,7 +1684,7 @@ Ext.Microloader = Ext.Microloader || (function () {
             uncache: function() {
                 LocalStorage.setAsset(this.key, null);
             },
-            
+
             exportContent: function() {
                 return Boot.apply({
                     loadOrderMap: this.loadOrderMap
@@ -1670,6 +1702,13 @@ Ext.Microloader = Ext.Microloader || (function () {
         Microloader = {
             init: function () {
                 Ext.microloaded = true;
+
+                // data-app is in the dev template for an application and is also
+                // injected into the app my CMD for production
+                // We use this to prefix localStorage cache to prevent collisions
+                var microloaderElement = document.getElementById('microloader');
+                Microloader.appId = microloaderElement ? microloaderElement.getAttribute('data-app') : '';
+
                 if (Ext.beforeLoad) {
                     postProcessor = Ext.beforeLoad(Ext.platformTags);
                 }
@@ -1696,7 +1735,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                         url = manifest.indexOf(extension) === manifest.length - extension.length
                             ? manifest
                             : manifest + ".json",
-                        key = getManifestStorageKey(url),
+                        key = getStorageKey(url),
                         content = LocalStorage.retrieveAsset(key);

                     // Manifest found in local storage, use this for immediate boot except in PhantomJS environments for building.
@@ -1731,8 +1770,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                 // Embedded Manifest into JS file
                 } else {
                     manifest = new Manifest({
-                        content: manifest,
-                        url: 'embedded'
+                        content: manifest
                     });
                     Microloader.load(manifest);
                 }
@@ -1753,10 +1791,7 @@ Ext.Microloader = Ext.Microloader || (function () {

                 for (len = assets.length, i = 0; i < len; i++) {
                     asset = assets[i];
-                    include = true;
-                    if (asset.assetConfig.platform && !Boot.filterPlatform(asset.assetConfig.platform)) {
-                        include = false;
-                    }
+                    include = Microloader.filterAsset(asset);
                     if (include) {
                         // Asset is using the localStorage caching system
                         if (manifest.shouldCache() && asset.shouldCache()) {
@@ -1798,7 +1833,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                 Microloader.remainingCachedAssets--;

                 if (!result.error) {
-                    checksum = Microloader.checksum(asset.assetConfig.hash, result.content);
+                    checksum = Microloader.checksum(result.content, asset.assetConfig.hash);
                     if (!checksum) {
                         _warn("Cached Asset '" + asset.assetConfig.path + "' has failed checksum. This asset will be uncached for future loading");

@@ -1811,11 +1846,11 @@ Ext.Microloader = Ext.Microloader || (function () {
                     asset.cache();
                 } else {
                     _warn("There was an error pre-loading the asset '" + asset.assetConfig.path + "'. This asset will be uncached for future loading");
-                    
+
                     // Un cache this asset so it is loaded next time
                     asset.uncache();
-                } 
-                
+                }
+
                 if (Microloader.remainingCachedAssets === 0) {
                     Microloader.onCachedAssetsReady();
                 }
@@ -1886,7 +1921,7 @@ Ext.Microloader = Ext.Microloader || (function () {

                 return output.join('');
             },
-            
+
             checkAllUpdates: function() {
                 if(window['removeEventListener']) {
                     window.removeEventListener('online', Microloader.checkAllUpdates, false);
@@ -1948,9 +1983,18 @@ Ext.Microloader = Ext.Microloader || (function () {
                 Microloader.notifyUpdateReady();
             },

+
+            filterAsset: function(asset) {
+                var cfg = (asset && asset.assetConfig) || {};
+                if(cfg.platform || cfg.exclude) {
+                    return Boot.filterPlatform(cfg.platform, cfg.exclude);
+                }
+                return true;
+            },
+
             onUpdatedManifestLoaded: function (result) {
                 result = Microloader.parseResult(result);
-                
+
                 if (!result.error) {
                     var currentAssets, newAssets, currentAsset, newAsset, prop,
                         assets, deltas, deltaPath, include,
@@ -1972,7 +2016,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                     if (!manifest.shouldCache()) {

                         Microloader.updatedManifest = manifest;
-                        LocalStorage.clearAllPrivate();
+                        LocalStorage.clearAllPrivate(manifest);
                         Microloader.onAllUpdatedAssetsReady();
                         return;
                     }
@@ -1988,7 +2032,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                         for (prop in newAssets) {
                             newAsset = newAssets[prop];
                             currentAsset = Microloader.manifest.getAsset(newAsset.assetConfig.path);
-                            include = !(newAsset.assetConfig.platform && !Boot.filterPlatform(newAsset.assetConfig.platform));
+                            include = Microloader.filterAsset(newAsset);

                             if (include && (!currentAsset || (newAsset.shouldCache() && (!currentAsset.is(newAsset))))) {
                                 updatingAssets.push({_new: newAsset, _current: currentAsset});
@@ -2001,7 +2045,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                             newAsset = manifest.getAsset(currentAsset.assetConfig.path);

                             //New version of this asset has been filtered out
-                            include = !(newAsset.assetConfig.platform && !Boot.filterPlatform(newAsset.assetConfig.platform));
+                            include = !Microloader.filterAsset(newAsset);

                             if (!include || !newAsset || (currentAsset.shouldCache() && !newAsset.shouldCache())) {
                                 Microloader.removedAssets.push(currentAsset);
@@ -2058,10 +2102,9 @@ Ext.Microloader = Ext.Microloader || (function () {
                 var checksum;
                 result = Microloader.parseResult(result);
                 Microloader.remainingUpdatingAssets--;
-                
+
                 if (!result.error) {
-                    
-                    checksum = Microloader.checksum(asset.assetConfig.hash, result.content);
+                    checksum = Microloader.checksum(result.content, asset.assetConfig.hash);
                     if (!checksum) {

                         // uncache this asset as there is a new version somewhere that has not been loaded.
@@ -2071,7 +2114,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                         Microloader.updatedAssets.push(asset);
                     }
                 } else {
-                    
+
                     // uncache this asset as there is a new version somewhere that has not been loaded.
                     asset.uncache();
                 }
@@ -2153,7 +2196,7 @@ Ext.Microloader = Ext.Microloader || (function () {
                     }
                 }
             },
-            
+
             fireAppUpdate: function() {
                 if (Ext.GlobalEvents) {
                     // We defer dispatching this event slightly in order to let the application finish loading
@@ -2163,12 +2206,16 @@ Ext.Microloader = Ext.Microloader || (function () {
                     }, 100);
                 }
             },
-            
+
             checksum: function(content, hash) {
+                if(!content || !hash) {
+                    return false;
+                }
+
                 var passed = true,
                     hashLn = hash.length,
                     checksumType = content.substring(0, 1);
-                
+
                 if (checksumType == '/') {
                     if (content.substring(2, hashLn + 2) !== hash) {
                         passed = false;
@@ -2203,92 +2250,7 @@ Ext.Microloader = Ext.Microloader || (function () {
     return Microloader;
 }());

-//</editor-fold>
-
 /**
- * the current application manifest
- *
- *
- * {
- *  name: 'name',
- *  version: <checksum>,
- *  debug: {
- *      hooks: {
- *          "*": true
- *      }
- *  },
- *  localStorage: false,
- *  mode: production,
- *  js: [
- *      ...
- *      {
- *          path: '../boo/baz.js',
- *          version: <checksum>,
- *          update: full | delta | <falsy>,
- *          platform: ['phone', 'ios', 'android']
- *      },
- *      {
- *          path: 'http://some.domain.com/api.js',
- *          remote: true
- *      },
- *      ...
- *  ],
- *  css: [
- *      ...
- *      {
- *          path: '../boo/baz.css',
- *          version: <checksum>,
- *          update: full | delta | <falsy>,
- *          platform: ['phone', 'ios', 'android']
- *      },
- *      ...
- *  ],
- *  localStorage: false,
- *  paths: {...},
- *  loadOrder: [
- *      ...
- *      {
- *          path: '../foo/bar.js",
- *          idx: 158,
- *          requires; [1,2,3,...,145,157],
- *          uses: [182, 193]
- *      },
- *      ...
- *  ],
- *  classes: {
- *      ...
- *      'Ext.panel.Panel': {
- *          requires: [...],
- *          uses: [...],
- *          aliases: [...],
- *          alternates: [...],
- *          mixins: [...]
- *      },
- *      'Ext.rtl.util.Renderable': {
- *          requires: [...],
- *          uses: [...],
- *          aliases: [...],
- *          alternates: [...],
- *          mixins: [...]
- *          override: 'Ext.util.Renderable'
- *      },
- *      ...
- *  },
- *  packages: {
- *      ...
- *      "sencha-core": {
- *          version: '1.2.3.4',
- *          requires: []
- *      },
- *      "ext": {
- *          version: '5.0.0.0',
- *          requires: ["sencha-core"]
- *      }.
- *      ...
- *  }
- * }
- *
- *
  * @type {String/Object}
  */
 Ext.manifest = Ext.manifest || "bootstrap";

Two options

  1. update the file in the repo with above patch
  2. remove the file from the repo and ignore it (via .gitignore)

I am open to suggestions.

Refactor MapfishPrintProvider separating serializer registry and model logic

I would like to suggest some changes before implementing a PR.

The MapfishPrintProvider right now is only a wrapper class around:

  • static functions and properties to keep track of registered serializers and
  • a capabilities record which holds the actual starting point to access the retrieved printing info

I think this should be separated into:

  • a singleton class SerializerProvider
  • an actual capabilities model (which is already in place)

Models can be configured with proxies, so it's possible to use the capabilities model directly to access remote information. Even better, it's not necessary to have extra logic to initialize the very same model from a properties map directly which cuts down on boilerplate code. I don't think it's necessary to go with class names like MapfishSerializerProvider or alike as I find it quite unlikely there will be any others?

Do you think this are desired changes?

Bug GeoExt.data.store.LayersTree not synchronized with map

HI, I think there is a bug In LayersTree store. In function onLayerCollectionRemove we are searching for child node without deep search. This results in node not being removed from tree if node was removed from layer group as the proper candidate cannot be found. Was it done this way on purpose? Below code fixes the issue for me.

var node = me.getRootNode().findChildBy(function(candidate) {
return candidate.getOlLayer() === layerOrGroup;
}, me, true);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.