JavaScript Using the DataView Example to create a photo gallery

I am building a web application using ExtJS. In my web application, the users can upload photos to the server directory. In addition, I also save the file path to a database table along with the user id so I know whose photo a certain photo is. Naturally, I would also want them to be able to view it. I can fetch the database rows properly based on the logged in user. However, the difficulty I'm having right now concerns showing the user his or her photos.

Upon searching the web, I saw this example provided by Sencha. Upon looking at the code, it seemed simple enough to integrate to my existing application.

Upon examining the provided data-view.js file, I saw that it uses 2 plugins that were already provided in the ext/src/ux/ subdirectory so I saw no purpose in adding them and my app.js file looks like this:

requires: [
    'Ext.Loader',
    'Ext.layout.container.Absolute',
    'Ext.layout.container.Column',
    'Ext.grid.*',
    'Ext.ux.DataView.DragSelector',
    'Ext.ux.DataView.LabelEditor'
],

Now, I also have my own model and my own store.

My model looks like:

Ext.define('LLOYDS_LMA.model.ciGallery', {
extend: 'Ext.data.Model',

requires: [
    'Ext.data.Field'
],

fields: [
    {
        name: 'image_path'
    },
    {
        name: 'description'
    },
    {
        name: 'upload_date'
    },
    {
        name: 'upload_time'
    }
]
});

And my store looks like a standard store used to do CRUD on database.

Now, in order to create the photo gallery example, what I did was to get the panel where I want the gallery to appear on and made a function for its afterrender property. In that after render function, what I basically did was to copy paste the entire example starting from Ext.create(....

It looks like this:

var store = Ext.getStore("ciGallery");

Ext.create('Ext.Panel', {
    id: 'images-view',
    frame: true,
    collapsible: true,
    width: 200,
    renderTo: 'dataview-example',
    title: 'Simple DataView (0 items selected)',
    items: Ext.create('Ext.view.View', {
        store: store,
        tpl: [
            '<tpl for=".">',
            '<div class="thumb-wrap" id="{name}">',
            '<div class="thumb"><img src="{url}" title="{name}"></div>',
            '<span class="x-editable">{shortName}</span></div>',
            '</tpl>',
            '<div class="x-clear"></div>'
        ],
        multiSelect: true,
        height: 310,
        trackOver: true,
        overItemCls: 'x-item-over',
        itemSelector: 'div.thumb-wrap',
        emptyText: 'No images to display',
        plugins: [
            Ext.create('Ext.ux.DataView.DragSelector', {}),
            Ext.create('Ext.ux.DataView.LabelEditor', {dataIndex: 'name'})
        ],

        prepareData: function(data) {
            Ext.apply(data, {
                shortName: Ext.util.Format.ellipsis(data.image_path, 15),
                sizeString: Ext.util.Format.fileSize(data.upload_date),
                dateString: Ext.util.Format.date(data.upload_time)
            });
            return data;
        },

        listeners: {
            selectionchange: function(dv, nodes ){
                var l = nodes.length,
                    s = l !== 1 ? 's' : '';
                this.up('panel').setTitle('Simple DataView (' + l + ' item' + s + ' selected)');
            }
        }
    })
});

Where ciGallery is my store, dataview-example is the id property of the parent panel, as well as adjustments to the prepareData function to match the properties of the model I use.

However, when I run my application and go to that panel, it seems like nothing rendered properly because I don't see anything, not even a blank panel.

Answer:1

I think for this to work properly your embedded DataView needs to be created in the initComponent method after the callParent has initialized your class.

Since I use this type of view frequently I created a base class 'DataPanel' that handles most of this setup and then just derive from that when needed passing only template-specific details.

Here is sample code from my actual implementation.

1) Create a separate include file named 'YourNamespace.view.DataPanel.js' containing this code:

Ext.define('YourNamespace.view.DataPanel', {
    extend: 'Ext.panel.Panel'
    , alias: 'widget.dataPanel'
    , title: ''
    , initTitle: ''
    , appendRecordToTitle: true
    , emptyText: undefined
    , itemSelector: ''
    , layout: 'fit'
    , store: ''
    , tpl: ''
    , autoWidth: true
    , overflowY: 'auto'
    , initComponent: function () {
        this.callParent(arguments);
            this.initTitle = this.title;
            var dataView = new Ext.DataView({
                emptyText: this.emptyText ? this.emptyText : 'No Items Available.'
                , title: this.initTitle
                , itemSelector: this.itemSelector
                , loadMask: false
                , overItemCls: 'x-view-over'
                , store: this.store
                , tpl: this.tpl
                , style: 'padding: 5px'
                , width: '100%'
                , listeners: {
                        selectionchange: function(dataview, selection) {
                            this.up().fireEvent('selectionchange', dataview, selection);
                        }
                    }
            });
            this.add(dataView);
        }
    , refreshTitle: function (recordTitle) {
            if (this.appendRecordToTitle) {
                this.setTitle(this.initTitle + ' ' + recordTitle);
            }
        }
    , reset: function() {
        }
});

2) Here is a sample showing usage of this base class:

Ext.define('YourNamespace.view.EmployeePhotoPanel', {
    extend: 'YourNamespace.view.DataPanel'
    , alias: 'widget.employeeSearchResultsPanel'
    , minHeight: 600
    , itemSelector: 'div.employee'
    , store: Ext.create('YourNamespace.store.Employees')
    , title: 'Search Results'
    , tpl: new Ext.XTemplate(
            '<tpl for=".">'
            , '<div class="employee">'
                , '<img src="/employee/photo?id={employeeNumber}&scale=thumbnail")">'
                , '<div class="displayLabel">{displayName:ellipsis(20)}</div>'
            , '</div>'
            , '</tpl>'
        )
    , load: function(searchCriteria) {
        this.store.load({
            params: {
                '$filter': searchCriteria
            }
                , scope: this
        })
        }
    }
);

3) Your model for this example might look something like this:

Ext.define('YourNamespace.model.Employee', {
    extend: 'Ext.data.Model'
  , requires: ['Ext.data.proxy.Rest']
  , idProperty: 'employeeNumber'
  , fields: [
      'employeeNumber', 'displayName'
   ]
  , proxy: {
        type: 'rest'
        , url: '/employee/record/summary'
  }
});

4) The store is simple:

Ext.define('YourNamespace.store.Employees', {
    extend: 'Ext.data.Store'
    , model: 'YourNamespace.model.Employee'
});

5) The .css to make it look right:

.employee {
    background-color: #F7F7F9;
    text-align: center;
    vertical-align: bottom;
    border: 1px outset #D0D0D0;
    padding: 4px;
    margin: 2px;
    float: left;
    display: inherit;
    overflow: hidden;
    font: normal .8em Arial;
    height: 130px;
    width: 108px;
}
.employee .displayLabel {
    white-space: nowrap;
    overflow: hidden;
    color: #000000;
}
.employee:hover{
   border:1px solid red;
}

6) Somewhere in your controller you will want to call your store load method. That call should auto-populate your DataView with info. This sample template has an embedded html img tag which makes a restful call back to the server for each store record to return the bytes that make up the image file. If you have static images modify the template to point directly to the image url (possibly even returning the url in the model record).

Hope this helps!

Answer:2

I'd like to insert millions of records as a batch process from MongoDB to Aerospike. I follow the documentation and found this doc: http://www.aerospike.com/docs/client/nodejs/usage/kvs/write.html but ...

I'd like to insert millions of records as a batch process from MongoDB to Aerospike. I follow the documentation and found this doc: http://www.aerospike.com/docs/client/nodejs/usage/kvs/write.html but ...

My website use $(window).bind('hashchange', function ()) to check if redirect is required. However, my site works fine in firefox not in IE9 $(window).bind('hashchange', function () { ...

My website use $(window).bind('hashchange', function ()) to check if redirect is required. However, my site works fine in firefox not in IE9 $(window).bind('hashchange', function () { ...

I have an input: <input type="text" placeholder="filter by country name" /> And a list of lists: <ul> <li v-for="continent in continents"> {{ continent[0]....

I have an input: <input type="text" placeholder="filter by country name" /> And a list of lists: <ul> <li v-for="continent in continents"> {{ continent[0]....

  1. vuejs input filter
  2. vuejs filter input value
  3. vuejs v-model input filter

in Three.js i'm trying to draw a cube with dashed line edges but the lines are still showing as solid. Here's my code: var mat_line = new THREE.LineDashedMaterial( { color: "black", dashSize: 1, ...

in Three.js i'm trying to draw a cube with dashed line edges but the lines are still showing as solid. Here's my code: var mat_line = new THREE.LineDashedMaterial( { color: "black", dashSize: 1, ...

  1. three js dashed line
  2. three js dashed line not working
  3. three.js line dashed material