├── .gitignore
├── sass
├── config.rb
├── example
│ ├── theme.html
│ ├── fashion.html
│ └── render.js
└── src
│ └── Application.scss
├── app.js
├── app
├── Application.js
└── view
│ └── main
│ ├── Main.js
│ ├── MainViewModel.js
│ ├── FilterForm.js
│ ├── MainViewController.js
│ ├── Hero.js
│ └── Devcards.js
├── index.html
├── README.md
├── workspace.json
├── app.json
└── resources
└── devs.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | ext/
3 | build/
4 | bootstrap.*
--------------------------------------------------------------------------------
/sass/config.rb:
--------------------------------------------------------------------------------
1 | cur_dir = File.dirname(__FILE__)
2 | output_style = :nested
3 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | Ext.application({
2 | extend: 'MyApp.Application',
3 | name: 'MyApp'
4 | });
5 |
--------------------------------------------------------------------------------
/app/Application.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.Application', {
2 | extend: 'Ext.app.Application',
3 | namespace: 'MyApp',
4 |
5 | requires: [
6 | 'MyApp.*'
7 | ],
8 |
9 | // The name of the initial view to create. With the classic toolkit this class
10 | // will gain a "viewport" plugin if it does not extend Ext.Viewport. With the
11 | // modern toolkit, the main view will be added to the Viewport.
12 | //
13 | mainView: 'MyApp.view.main.Main'
14 | });
15 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Modern Tutorial
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/view/main/Main.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.view.main.Main', {
2 | extend: 'Ext.Container',
3 | controller: 'main',
4 | viewModel: 'main',
5 |
6 | // list the classes required by the Main class so that
7 | // Cmd loads them ahead of this class when building the app
8 | requires: [
9 | 'MyApp.view.main.Hero',
10 | 'MyApp.view.main.Devcards',
11 | 'MyApp.view.main.MainViewController',
12 | 'MyApp.view.main.MainViewModel'
13 | ],
14 |
15 | layout: {
16 | type: 'card',
17 | animation: {
18 | type: 'slide',
19 | direction: 'up'
20 | }
21 | },
22 |
23 | items: [{
24 | // our hero (landing) page that we’ll define later
25 | xtype: 'hero'
26 | }, {
27 | // our developer list / details cards that we’ll define later
28 | xtype: 'devcards'
29 | }]
30 | });
--------------------------------------------------------------------------------
/sass/example/theme.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | Ext JS Theme Harness
8 |
9 |
10 |
11 |
14 |
15 |
16 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/view/main/MainViewModel.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.view.main.MainViewModel', {
2 | extend: 'Ext.app.ViewModel',
3 | alias: 'viewmodel.main', // the alias for this view model
4 |
5 | // the initial values for our views' data bindings
6 | data: {
7 | extjs: true,
8 | touch: true,
9 | architect: true,
10 | themer: true,
11 | inspector: true,
12 | devsCount: 0
13 | },
14 | stores: {
15 | // the 'devs' store is described here and
16 | // used via binding by our developers List
17 | devs: {
18 | autoLoad: true, // load the data immediately
19 | proxy: {
20 | type: 'ajax',
21 | // the URL for our remote data
22 | url: 'resources/devs.json',
23 | reader: {
24 | type: 'json',
25 | // the root property from which all of our data is read
26 | rootProperty: 'results'
27 | }
28 | },
29 | // a load event listener used to communicate
30 | // how many records were read in
31 | listeners: {
32 | load: 'onDevsLoad'
33 | }
34 | }
35 | }
36 | });
--------------------------------------------------------------------------------
/sass/example/fashion.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | Ext JS Theme Harness
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Taking the Modern Tutorial to Production
2 |
3 | Let's walk through the steps of creating the app we've been working on above in a real world environment.
4 |
5 | ##Download the Ext JS Framework
6 |
7 | If you have not already done so, download and unpack the Ext JS framework from either the Products section
8 | of the main Sencha website [sencha.com](www.sencha.com) or from the downloads section of the Sencha Support portal.
9 |
10 | ##Add Cmd to your App
11 |
12 | Once you have your application where you want it, "cd" into its directory in your Command Line Interface (CLI). Then,
13 | issue the following command:
14 |
15 | sencha app install --framework=/path/to/extjs/
16 |
17 | This command will wrap your app code folder with a Sencha Cmd framework that allows your application to benefit
18 | from Cmd's many features.
19 |
20 | **Note:** "/path/to/extjs/" should be replaced with the path to wherever you unzipped the Ext JS framework on your machine.
21 |
22 | **Hint:** If you're having trouble getting Sencha Cmd installed, see the following Cmd Starter Overview.
23 |
24 | ##Download the Sample Application
25 | Download the contents of this repository that we're currently in.
26 |
27 | ##Move Zip to Application
28 | Copy the contents of the downloaded application into the ModernTutorial folder.
29 |
30 | ##Build Your Application
31 | Finally, cd into your ModernTutorial folder and run:
32 |
33 | sencha app build
34 |
35 | You can now visit your application at its local address on your web server. You can also run this command so
36 | that Cmd will generate a web server for you:
37 |
38 | sencha app watch
39 |
40 | You can now visit the resulting address displayed in your console. It will usually be found here:
41 |
42 | http://localhost:1841
43 |
--------------------------------------------------------------------------------
/workspace.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * An object containing key value pair framework descriptors.
4 | *
5 | * The value can be a string or an object containing at least one of "dir" or "pkg",
6 | * where "dir" can be a filesystem path to the framework sources and "pkg" can be a
7 | * package name. For example:
8 | *
9 | * "frameworks": {
10 | *
11 | * "ext-x": "/absolute/path/to/ext",
12 | * "ext-y": {
13 | * "source": "../relative/path/to/ext",
14 | * "path": "ext"
15 | * },
16 | * "ext-z": {
17 | * "package": "ext@n.n.n",
18 | * "path": "ext-n.n.n"
19 | * },
20 | * "touch": "touch"
21 | * }
22 | *
23 | */
24 | "frameworks": {
25 | "ext": {
26 | "path":"ext",
27 | "version":"7.0.0.116"
28 | }
29 |
30 |
31 | },
32 |
33 | /**
34 | * This is the folder for build outputs in the workspace.
35 | */
36 | "build": {
37 | "dir": "${workspace.dir}/build"
38 | },
39 |
40 | /**
41 | * These configs determine where packages are generated and extracted to (when downloaded).
42 | */
43 | "packages": {
44 | /**
45 | * This folder contains all local packages.
46 | * If a comma-separated string is used as value the first path will be used as the path to generate new packages.
47 | */
48 | "dir": "${workspace.dir}/packages/local,${workspace.dir}/packages",
49 |
50 | /**
51 | * This folder contains all extracted (remote) packages.
52 | */
53 | "extract": "${workspace.dir}/packages/remote"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/view/main/FilterForm.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.view.main.FilterForm', {
2 | extend: 'Ext.form.Panel',
3 | xtype: 'filterform', // the alias used by the List and its Container
4 | // configuration options set in the defaults config will be applied
5 | // to all child components in the items array below (unless a config is
6 | // overridden explicitly in an item's config)
7 | defaults: {
8 | xtype: 'checkboxfield',
9 | labelWidth: 100,
10 | // we'll go ahead and point to a checkbox change handler method that
11 | // we'll author later in the guide for filtering the developer List
12 | listeners: {
13 | change: 'onFilterChange'
14 | }
15 | },
16 | cls: 'filter-form',
17 | bodyPadding: 8,
18 | items: [
19 | {
20 | xtype: 'titlebar',
21 | title: 'Filter By',
22 | docked: 'top',
23 | platformConfig: {
24 | '!phone': {
25 | hidden: true
26 | }
27 | },
28 | items: {
29 | xtype: 'button',
30 | iconCls: 'md-icon-close',
31 | align: 'right',
32 | listeners: {
33 | tap: 'onFilterMenuCloseButtonTap'
34 | }
35 | }
36 | },
37 | {
38 | // each checkboxfield has a form field label corresponding to the
39 | // skill it will filter by. Additionally, we'll set up the data
40 | // binding to point to a data value on the main View Model we'll
41 | // describe a bit later in the tutorial
42 | label: 'Ext JS',
43 | bind: {
44 | checked: '{extjs}'
45 | }
46 | }, {
47 | label: 'Touch',
48 | bind: {
49 | checked: '{touch}'
50 | }
51 | }, {
52 | label: 'Architect',
53 | bind: {
54 | checked: '{architect}'
55 | }
56 | }, {
57 | label: 'Themer',
58 | bind: {
59 | checked: '{themer}'
60 | }
61 | }, {
62 | label: 'Inspector',
63 | bind: {
64 | checked: '{inspector}'
65 | }
66 | }]
67 | });
--------------------------------------------------------------------------------
/app/view/main/MainViewController.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.view.main.MainViewController', {
2 | extend: 'Ext.app.ViewController',
3 | alias: 'controller.main',
4 |
5 | onFilterMenuButtonTap: function() {
6 | var filtersMenu = this.lookup('filters');
7 | filtersMenu.show();
8 | },
9 |
10 | onFilterMenuCloseButtonTap: function() {
11 | var filtersMenu = this.lookup('filters');
12 | filtersMenu.hide();
13 | },
14 |
15 | onGetStarted: function() {
16 | this.getView().setActiveItem(1);
17 | },
18 |
19 | // when a developer item is tapped in the developer List
20 | // 1) set the record of the developer tapped on the View Model
21 | // 2) show the developer details view
22 | onDevTap: function(list, i, el, rec) {
23 | this.getViewModel().set('dev', rec);
24 | var active = this.lookup('devcards').animateActiveItem(1, 'slide');
25 | if (active.rec !== rec) {
26 | active.down('tabpanel').setActiveItem(0);
27 | }
28 | active.rec = rec;
29 | },
30 |
31 | // return to the developers list from the details view
32 | showDevList: function () {
33 | this.lookup('devcards').animateActiveItem(0, {type: 'slide', direction: 'right'});
34 | },
35 |
36 | // any change to the filter checkboxes will update the filtering
37 | // applied to the developers List store using the checked skills
38 | // we've used the Ext.function.createBuffered method to handle
39 | // rapidly fired checkbox change events in a controlled manner
40 | // - a byproduct of having two filter forms operating in sync
41 | onFilterChange: Ext.Function.createBuffered(function() {
42 | var devsStore = this.lookup('devslist').getStore(),
43 | vm = this.getViewModel(),
44 | allFilters = ['extjs', 'touch', 'architect', 'themer', 'inspector'],
45 | filters = [];
46 |
47 | // collect up an array of checked checkboxes
48 | Ext.each(allFilters, function(item) {
49 | if (vm.get(item)) {
50 | filters.push(item);
51 | }
52 | });
53 |
54 | // clear any filtering on the Store
55 | devsStore.clearFilter();
56 | // if there are any checkboxes checked
57 | if (filters.length) {
58 | // filter the developers Store using only the checked filters
59 | devsStore.filterBy(function(rec) {
60 | var skills = Ext.Array.map(rec.get('skills'), function(item) {
61 | return item.toLowerCase().replace(/ /g, '');
62 | });
63 |
64 | return Ext.Array.intersect(filters, skills).length;
65 | });
66 | }
67 | }, 10),
68 |
69 | // when the developers Store loads update the 'devsCount' value on the
70 | // View Model in order to update the developers count on the Hero page
71 | onDevsLoad: function(store) {
72 | this.getViewModel().set('devsCount', store.getCount());
73 | }
74 | });
--------------------------------------------------------------------------------
/app/view/main/Hero.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.view.main.Hero', {
2 | extend: 'Ext.container.Container',
3 | // the component reference name used when instantiating our hero component in the top-level carousel
4 | xtype: 'hero',
5 |
6 | // not needed out of the box, but helpful when it comes to styling the hero component
7 | cls: 'hero-card',
8 | // vertical / centered container layout for all child items
9 | layout: {
10 | type: 'vbox',
11 | align: 'center'
12 | },
13 | items: [{
14 | // a transparent container used to help with layout allowing the user Login button
15 | // to float to the right of the app while the remaining content is centered
16 | xtype: 'container',
17 | layout: 'hbox',
18 | width: '100%',
19 | padding: '12 16',
20 | items: [{
21 | // in an hbox layout the flex: 1 configuration forces additional components
22 | // to the right by taking up all available space
23 | xtype: 'component',
24 | flex: 1
25 | }, {
26 | // our button used for login
27 | xtype: 'button',
28 | // here we'll set the data binding for the button text and icon
29 | // (covered later in the guide)
30 | bind: {
31 | text: '{loginText}',
32 | iconCls: '{userCls}'
33 | },
34 | // a CSS class used for custom styling of the button
35 | cls: 'clear-white',
36 | // we'll go ahead and set a handler on the button for when it's tapped. The logic
37 | // used to handle the button tap will come later when we set up the main view's View Controller
38 | handler: 'onLoginPress'
39 | }]
40 | }, {
41 | // in a vbox layout the flex: 1 configuration forces additional components
42 | // down by taking up all available space
43 | xtype: 'component',
44 | flex: 1
45 | }, {
46 | // our hero page title
47 | xtype: 'component',
48 | html: 'Sencha Devs',
49 | cls: 'hero-card-title'
50 | }, {
51 | // our hero page description / tagline
52 | xtype: 'component',
53 | html: 'Worldwide Sencha developers database. Find your developer here.',
54 | padding: 10,
55 | cls: 'hero-card-sub-title'
56 | }, {
57 | // the button used to navigate to the developers list
58 | xtype: 'button',
59 | text: 'Get Started',
60 | iconCls: 'x-fa fa-arrow-circle-o-down',
61 | cls: 'get-started',
62 | margin: '60 0 0 0',
63 | handler: 'onGetStarted'
64 | }, {
65 | xtype: 'component',
66 | flex: 1
67 | }, {
68 | // display a count of all available developers. We'll set up the logic that
69 | // displays this count further in the guide
70 | xtype: 'component',
71 | bind: {
72 | html: 'Devs: {devsCount}'
73 | },
74 | cls: 'dev-count',
75 | padding: 12
76 | }]
77 | });
--------------------------------------------------------------------------------
/sass/src/Application.scss:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Raleway:400,600,500,300,700|Lato:400,700");
2 |
3 | /* VP Modal Mask */
4 | #ext-viewport > .x-body > .x-mask {
5 | opacity: .4;
6 | background-color: #fff;
7 | }
8 |
9 | /* Buttons */
10 | .clear-white {
11 | background-color: transparent;
12 | border-color: transparent;
13 | color: white;
14 | }
15 |
16 | .clear-white .x-button-icon {
17 | color: white;
18 | }
19 |
20 | .clear-white.x-button.x-button-pressing,
21 | .clear-white.x-button.x-button-pressed {
22 | color: #919191;
23 | background-color: transparent;
24 | border-color: transparent;
25 | }
26 |
27 | .clear-white.x-button.x-button-pressing .x-button-icon,
28 | .clear-white.x-button.x-button-pressed .x-button-icon {
29 | color: #919191;
30 | }
31 |
32 | /* Hero Card */
33 | .hero-card {
34 | background: #3e536d url(https://s3.amazonaws.com/uploads.hipchat.com/9804/276555/WpAlblU22yspraZ/hero-bg3.jpg) no-repeat center bottom;
35 | background-size: cover;
36 | }
37 |
38 | .hero-card-title {
39 | text-align: center;
40 | color: white;
41 | font-size: 80px;
42 | line-height: 80px;
43 | font-family: Raleway;
44 | font-weight: 500;
45 | }
46 |
47 | .hero-card-sub-title {
48 | text-align: center;
49 | color: white;
50 | font-size: 36px;
51 | font-family: Raleway;
52 | font-weight: 300;
53 | }
54 |
55 | .get-started {
56 | font-size: 2em;
57 | opacity: .3;
58 | border-radius: 32px;
59 | background: #1d1d1d;
60 | color: #bdbdbd;
61 | }
62 |
63 | .get-started .x-button-icon {
64 | color: #777777;
65 | }
66 |
67 | .dev-count {
68 | color: white;
69 | font-size: 16px;
70 | }
71 |
72 | .dev-count-label {
73 | color: #bdbdbd;
74 | text-transform: uppercase;
75 | letter-spacing: 2px;
76 | font-size: 13px;
77 | }
78 |
79 | /* Filter Form */
80 | .filter-form {
81 | z-index: 10;
82 | }
83 |
84 | .filter-form-left {
85 | border-right: 1px solid #e6e6e6 !important;
86 | }
87 |
88 | /* Devs List */
89 |
90 | .list-item-dev {
91 | display: -webkit-box;
92 | display: flex;
93 | -webkit-flex-direction: row;
94 | flex-direction: row;
95 |
96 | }
97 | .list-item-image {
98 | border: 3px solid #efefef;
99 | float: left;
100 | height: 48px;
101 | width: 48px;
102 | border-radius: 50%;
103 | margin: 10px 20px 0 0;
104 | }
105 |
106 | .list-item-name {
107 | font-size: 24px;
108 | line-height: 32px;
109 | color: #404040;
110 | }
111 |
112 | .list-item-skill-tag,
113 | .dev-card-skill-tag {
114 | display: inline-block;
115 | padding: 3px 6px;
116 | border-radius: 3px;
117 | background-color: #ef359a;
118 | color: #f5f5f5;
119 | margin: 6px 6px 0 0;
120 | font-family: Lato;
121 | }
122 |
123 | /* Dev Card */
124 | .dev-card-image {
125 | border-radius: 50%;
126 | width: 128px;
127 | height: 128px;
128 | border: 6px solid #bfbfbf;
129 | }
130 |
131 | .dev-card-name {
132 | font-size: 24px;
133 | line-height: 32px;
134 | color: #8a8a8a;
135 | }
136 |
137 | .dev-card-info,
138 | .dev-card-contact {
139 | font-size: 16px;
140 | color: #4a4a4a;
141 | }
142 |
143 | .dev-card-divider {
144 | background-image: repeating-linear-gradient(45deg,#fafafa,#fafafa 5px,#dcdcdc 5px,#dcdcdc 7px);
145 | }
146 |
147 | .dev-card-skills-ct {
148 | background-color: #efefef;
149 | padding: 8px 4px;
150 | margin-top: 16px;
151 | }
152 | /* .dev-card-skill-tag see above */
153 |
154 |
--------------------------------------------------------------------------------
/app/view/main/Devcards.js:
--------------------------------------------------------------------------------
1 | Ext.define('MyApp.view.main.Devcards', {
2 | extend: 'Ext.container.Container',
3 | xtype: 'devcards',
4 |
5 | // list the classes required by this class
6 | requires: ['MyApp.view.main.FilterForm'],
7 |
8 | // the card layout displays one view at a time from the items array. Think of a tab
9 | // panel where the views are shown programmatically -vs- using tabs in a tab bar
10 | layout: {
11 | type: 'card',
12 | animation: 'slide'
13 | },
14 | // we'll set a reference config for easy access to this container from within our
15 | // view controller logic we'll define further on in the guide
16 | reference: 'devcards',
17 | items: [{
18 | // a container to horizontally lay out the developers list and filter
19 | // form in landscape mode and just the list (with its child filter form)
20 | // when oriented in portrait
21 | xtype: 'container',
22 | layout: {
23 | type: 'hbox',
24 | align: 'stretch'
25 | },
26 | items: [{
27 | xtype: 'titlebar',
28 | title: 'Developers',
29 | docked: 'top',
30 | items: {
31 | iconCls: 'md-icon-filter-list',
32 | align: 'right',
33 | platformConfig: {
34 | '!phone': {
35 | hidden: true
36 | }
37 | },
38 | listeners: {
39 | tap: 'onFilterMenuButtonTap'
40 | }
41 | }
42 | }, {
43 | // 'filterform' is the xtype of a custom component we'll
44 | // define in the next part of the guide
45 | xtype: 'filterform',
46 | reference: 'filters',
47 | platformConfig: {
48 | phone: {
49 | floated: true,
50 | width: '100%',
51 | height: '100%',
52 | showAnimation: {
53 | type: 'slide',
54 | direction: 'down'
55 | },
56 | hideAnimation: {
57 | type: 'slideOut',
58 | direction: 'up'
59 | }
60 | },
61 | '!phone': {
62 | width: 150,
63 | cls: 'filter-form-left'
64 | }
65 | }
66 | }, {
67 | // List components are great ways to show a column of data using a
68 | // user-define HTML template
69 | xtype: 'list',
70 | reference: 'devslist',
71 | striped: true, // striped to tint every other row
72 | disableSelection: true, // disable row selection for this app
73 | flex: 1, // take up available horizontal space
74 | minWidth: 300,
75 | itemTpl: '' +
76 | '

' +
77 | '
' +
78 | '
{name.first:capitalize} {name.last:capitalize}
' +
79 | '
' +
80 | '{.}
' +
81 | '' +
82 | '
' +
83 | '
',
84 | // we'll get the data Store for the List component from the
85 | // ancestor container's View Model. We'll set that up a bit
86 | // later in the guide.
87 | bind: {
88 | store: '{devs}'
89 | },
90 | // When we set up the tap event handler logic this listener
91 | // will cause tapping on a developer to show its details view
92 | listeners: {
93 | itemtap: 'onDevTap'
94 | }
95 | }]
96 | }, {
97 | xtype: 'container',
98 | // vertically lay out all child items and center them
99 | layout: {
100 | type: 'vbox',
101 | align: 'center'
102 | },
103 | items: [{
104 | xtype: 'toolbar',
105 | // docked positions a component above or below all other items
106 | docked: 'top',
107 | items: [{
108 | // button to navigate back to the developers list
109 | // note that toolbars’ default child item type is button
110 | // so we didn’t have to specify the xtype
111 | text: 'Dev List',
112 | handler: 'showDevList'
113 | }]
114 | }, {
115 | // a larger developer avatar image
116 | xtype: 'component',
117 | bind: {
118 | html: '
'
119 | },
120 | margin: 20
121 | }, {
122 | // the developer's full name
123 | xtype: 'component',
124 | bind: {
125 | html: '{dev.name.first:capitalize} {dev.name.last:capitalize}
'
126 | },
127 | margin: '0 0 20 0'
128 | }, {
129 | // a Tab Panel displaying:
130 | // 1) a developer bio and Sencha skills
131 | // 2) contact information
132 | xtype: 'tabpanel',
133 | width: '100%', // take up all available width
134 | flex: 1,
135 | items: [{
136 | // the developer bio and skills tab
137 | title: 'Info',
138 | scrollable: 'vertical',
139 | padding: 20,
140 | cls: 'dev-card-info',
141 | defaults: {
142 | xtype: 'component',
143 | margin: '0 0 10 0'
144 | },
145 | items: [{
146 | html: 'Registered since: July 12, 2013',
147 | margin: '0 0 29 0'
148 | }, {
149 | // dummy bio
150 | html: 'Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts.
Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.
A small river named Duden flows by their place and supplies it with the necessary regelialia. It is a paradisematic country, in which roasted parts of sentences fly into your mouth.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to
'
151 | }, {
152 | bind: {
153 | data: '{dev.skills}'
154 | },
155 | tpl: '{.}
'
156 | }]
157 | }, {
158 | // the contact tab using data from the developer record
159 | title: 'Contact',
160 | padding: 20,
161 | scrollable: 'vertical',
162 | cls: 'dev-card-contact',
163 | bind: {
164 | html: 'e-mail: {dev.email}
phone: {dev.cell}
Loc: {dev.location.city:capitalize}, {dev.location.state:capitalize} {dev.nat:uppercase}'
165 | }
166 | }]
167 | }]
168 | }]
169 | });
170 |
--------------------------------------------------------------------------------
/sass/example/render.js:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is generated by Sencha Cmd and should NOT be edited. It will be replaced
3 | * during an upgrade.
4 | */
5 |
6 | // This flag is checked by many Components to avoid compatibility warnings when
7 | // the code is running under the slicer
8 | Ext.slicer = true;
9 |
10 | Ext.require([
11 | 'Ext.layout.Context'
12 | ]);
13 |
14 | Ext.theme = Ext.apply(Ext.theme || {}, {
15 | /**
16 | * The array of all component manifests. These objects have the following set of
17 | * properties recognized by the slicer:
18 | * @private
19 | */
20 | _manifest: [],
21 |
22 | /**
23 | * The collection of shortcuts for a given alias (e.g., 'widget.panel'). This is an
24 | * object keyed by alias whose values are arrays of shortcut definitions.
25 | * @private
26 | */
27 | _shortcuts: {},
28 |
29 | doRequire : function(xtype) {
30 | if(xtype.indexOf("widget.") != 0) {
31 | xtype = "widget." + xtype;
32 | }
33 | Ext.require([xtype]);
34 | },
35 |
36 | /**
37 | * Adds one ore more component entries to the theme manifest. These entries will be
38 | * instantiated by the `Ext.theme.render` method when the page is ready.
39 | *
40 | * Usage:
41 | *
42 | * Ext.theme.addManifest({
43 | * xtype: 'widget.menu',
44 | * folder: 'menu',
45 | * delegate: '.x-menu-item-link',
46 | * filename: 'menu-item-active',
47 | * config: {
48 | * floating: false,
49 | * width: 200,
50 | * items: [{
51 | * text: 'test',
52 | * cls: 'x-menu-item-active'
53 | * }]
54 | * }
55 | * },{
56 | * //...
57 | * });
58 | *
59 | * @param manifest {Object} An object with type of component, slicing information and
60 | * component configuration. If this parameter is an array, each element is treated as
61 | * a manifest entry. Otherwise, each argument passed is treated as a manifest entry.
62 | *
63 | * @param manifest.xtype {String} The xtype ('grid') or alias ('widget.grid'). This
64 | * is used to specify the type of component to create as well as a potential key to
65 | * any `shortcuts` defined for the xtype.
66 | *
67 | * @param manifest.config {Object} The component configuration object. The properties
68 | * of this depend on the `xtype` of the component.
69 | *
70 | * @param [manifest.delegate] {String} The DOM query to use to select the element to
71 | * slice. The default is to slice the primary element of the component.
72 | *
73 | * @param [manifest.parentCls] An optional CSS class to add to the parent of the
74 | * component.
75 | *
76 | * @param [manifest.setup] {Function} An optional function to be called to initialize
77 | * the component.
78 | * @param manifest.setup.component {Ext.Component} The component instance
79 | * @param manifest.setup.container {Element} The component's container.
80 | *
81 | * @param [manifest.folder] {String} The folder in to which to produce image slices.
82 | * Only applies to Ext JS 4.1 (removed in 4.2).
83 | *
84 | * @param [manifest.filename] {String} The base filename for slices.
85 | * Only applies to Ext JS 4.1 (removed in 4.2).
86 | *
87 | * @param [manifest.reverse] {Boolean} True to position the slices for linear gradient
88 | * background at then opposite "end" (right or bottom) and apply the stretch to the
89 | * area before it (left or top). Only applies to Ext JS 4.1 (removed in 4.2).
90 | */
91 | addManifest: function (manifest) {
92 | var all = Ext.theme._manifest;
93 | var add = Ext.isArray(manifest) ? manifest : arguments;
94 |
95 | if(manifest.xtype) {
96 | Ext.theme.doRequire(manifest.xtype);
97 | }
98 |
99 | for (var i = 0, n = add.length; i < n; ++i) {
100 | if(add[i].xtype) {
101 | Ext.theme.doRequire(add[i].xtype);
102 | }
103 | all.push(add[i]);
104 | }
105 | },
106 |
107 | /**
108 | * Adds one or more shortcuts to the rendering process. A `shortcut` is an object that
109 | * looks the same as a `manifest` entry. These are combined by copying the properties
110 | * from the shortcut over those of the manifest entry. In basic terms:
111 | *
112 | * var config = Ext.apply(Ext.apply({}, manfiest.config), shortcut.config);
113 | * var entry = Ext.apply(Ext.apply({}, manfiest), shortcut);
114 | * entry.config = config;
115 | *
116 | * This is not exactly the process, but the idea is the same. The difference is that
117 | * the `ui` of the manifest entry is used to replace any `"{ui}"` substrings found in
118 | * any string properties of the shortcut or its `config` object.
119 | *
120 | * Usage:
121 | *
122 | * Ext.theme.addShortcuts({
123 | * 'widget.foo': [{
124 | * config: {
125 | * }
126 | * },{
127 | * config: {
128 | * }
129 | * }],
130 | *
131 | * 'widget.bar': [ ... ]
132 | * });
133 | */
134 | addShortcuts: function (shortcuts) {
135 | var all = Ext.theme._shortcuts;
136 |
137 | for (var key in shortcuts) {
138 |
139 | var add = shortcuts[key];
140 | var xtype = Ext.theme.addWidget(key);
141 | var existing = all[xtype];
142 |
143 | Ext.theme.doRequire(xtype);
144 | for(var i=0; i < add.length; i++) {
145 | var config = add[i];
146 | if(config.xtype) {
147 | Ext.theme.doRequire(config.xtype);
148 | }
149 | }
150 |
151 | if (!existing) {
152 | all[xtype] = existing = [];
153 | }
154 |
155 | existing.push.apply(existing, add);
156 | }
157 | },
158 |
159 | /**
160 | * This method ensures that a given string has the specified prefix (e.g., "widget.").
161 | * @private
162 | */
163 | addPrefix: function (prefix, s) {
164 | if (!s || (s.length > prefix.length && s.substring(0,prefix.length) === prefix)) {
165 | return s;
166 | }
167 | return prefix + s;
168 | },
169 |
170 | /**
171 | * This method returns the given string with "widget." added to the front if that is
172 | * not already present.
173 | * @private
174 | */
175 | addWidget: function (str) {
176 | return Ext.theme.addPrefix('widget.', str);
177 | },
178 |
179 | /**
180 | * This method accepts an manifest entry and a shortcut entry and returns the merged
181 | * version.
182 | * @private
183 | */
184 | applyShortcut: function (manifestEntry, shortcut) {
185 | var ui = manifestEntry.ui;
186 | var config = Ext.theme.copyProps({}, manifestEntry.config);
187 | var entry = Ext.theme.copyProps({}, manifestEntry);
188 |
189 | if (ui && !config.ui) {
190 | config.ui = ui;
191 | }
192 | if (shortcut) {
193 | var tpl = { ui: ui };
194 | Ext.theme.copyProps(entry, shortcut, tpl);
195 | Ext.theme.copyProps(config, shortcut.config, tpl);
196 | }
197 |
198 | entry.xtype = Ext.theme.addWidget(entry.xtype);
199 | entry.config = config; // both guys have "config" so smash merged one on now...
200 | return entry;
201 | },
202 |
203 | /**
204 | * This method copies property from a `src` object to a `dest` object and reaplces
205 | * `"{foo}"` fragments of any string properties as defined in the `tpl` object.
206 | *
207 | * var obj = Ext.theme.copyProps({}, {
208 | * foo: 'Hello-{ui}'
209 | * }, {
210 | * ui: 'World'
211 | * });
212 | *
213 | * console.log('obj.foo: ' + obj.foo); // logs "Hello-World"
214 | *
215 | * @return {Object} The `dest` object or a new object (if `dest` was null).
216 | * @private
217 | */
218 | copyProps: function (dest, src, tpl) {
219 | var out = dest || {};
220 | var replacements = [];
221 | var token;
222 |
223 | if (src) {
224 | if (tpl) {
225 | for (token in tpl) {
226 | replacements.push({
227 | re: new RegExp('\\{' + token + '\\}', 'g'),
228 | value: tpl[token]
229 | });
230 | }
231 | }
232 |
233 | for (var key in src) {
234 | var val = src[key];
235 | if (tpl && typeof val === 'string') {
236 | for (var i = 0; i < replacements.length; ++ i) {
237 | val = val.replace(replacements[i].re, replacements[i].value);
238 | }
239 | }
240 | out[key] = val;
241 | }
242 | }
243 |
244 | return out;
245 | },
246 |
247 | /**
248 | * Renders a component given its manifest and shortcut entries.
249 | * @private
250 | */
251 | renderWidget: function (manifestEntry, shortcut) {
252 | var entry = Ext.theme.applyShortcut(manifestEntry, shortcut);
253 | var config = entry.config;
254 | var widget = Ext.create(entry.xtype, config);
255 | var ct = Ext.fly(document.body).createChild({ cls: 'widget-container' });
256 |
257 | Ext.theme.currentWidget = widget;
258 |
259 | if (widget.floating === true) {
260 | widget.floating = { shadow: false };
261 | }
262 | if (widget.floating) {
263 | widget.focusOnToFront = false;
264 | }
265 |
266 | if (entry.setup) {
267 | entry.setup.call(widget, widget, ct);
268 | } else {
269 | widget.render(ct);
270 | if (widget.floating) {
271 | widget.showAt(0, 0);
272 | ct.setHeight(widget.getHeight());
273 | }
274 | }
275 |
276 | var el = widget.el;
277 | if (entry.delegate) {
278 | el = el.down(entry.delegate);
279 | }
280 |
281 | el.addCls('x-slicer-target'); // this is what generateSlicerManifest looks for
282 |
283 | if (entry.over) {
284 | widget.addOverCls();
285 | }
286 | if (config.parentCls) {
287 | el.parent().addCls(config.parentCls);
288 | }
289 |
290 | if (Ext.theme.legacy) {
291 | // The 4.1 approach has some interesting extra pieces
292 | //
293 | var data = {};
294 | if (entry.reverse) {
295 | data.reverse = true;
296 | }
297 | if (entry.filename) {
298 | data.filename = entry.filename;
299 | }
300 | if (entry.folder) {
301 | data.folder = entry.folder;
302 | }
303 | if (entry.offsets) {
304 | data.offsets = entry.offsets;
305 | }
306 |
307 | Ext.theme.setData(el.dom, data);
308 | }
309 |
310 | Ext.theme.currentWidget = null;
311 | },
312 |
313 | /**
314 | * Renders all of the components that have been added to the manifest.
315 | * @private
316 | */
317 | render: function () {
318 | console.log("rendering widgets...")
319 | var manifest = Ext.theme._manifest;
320 | var shortcuts = Ext.theme._shortcuts;
321 |
322 | for (var k = 0, n = manifest ? manifest.length : 0; k < n; ++k) {
323 | var manifestEntry = manifest[k];
324 | var xtype = Ext.theme.addWidget(manifestEntry.xtype);
325 | var widgetShortcuts = xtype ? shortcuts[xtype] : null;
326 |
327 | if (xtype && manifestEntry.ui && widgetShortcuts) {
328 | for (var i = 0; i < widgetShortcuts.length; i++) {
329 | Ext.theme.renderWidget(manifestEntry, widgetShortcuts[i]);
330 | }
331 | } else {
332 | Ext.theme.renderWidget(manifestEntry);
333 | }
334 | }
335 | },
336 |
337 | /**
338 | * Renders all components (see `render`) and notifies the Slicer that things are ready.
339 | * @private
340 | */
341 | run: function () {
342 | var extjsVer = Ext.versions.extjs;
343 | var globalData = {};
344 |
345 | if (Ext.layout.Context) {
346 | Ext.override(Ext.layout.Context, {
347 | run: function () {
348 | var ok = this.callParent(),
349 | widget = Ext.theme.currentWidget;
350 | if (!ok && widget) {
351 | Ext.Error.raise("Layout run failed: " + widget.id);
352 | }
353 | return ok;
354 | }
355 | });
356 | }
357 |
358 | console.log("loading widget definitions...");
359 |
360 | // Previous to Ext JS 4.2, themes and their manifests where defined differently.
361 | // So pass this along if we are hosting a pre-4.2 theme.
362 | //
363 | if (extjsVer && extjsVer.isLessThan(new Ext.Version("4.2"))) {
364 | globalData.format = "1.0"; // tell the Slicer tool
365 | Ext.theme.legacy = true; // not for our own data collection
366 |
367 | // Check for the Cmd3.0/ExtJS4.1 variables:
368 | //
369 | if (Ext.manifest && Ext.manifest.widgets) {
370 | Ext.theme.addManifest(Ext.manifest.widgets);
371 | }
372 | if (Ext.shortcuts) {
373 | Ext.theme.addShortcuts(Ext.shortcuts);
374 | }
375 | if (Ext.userManifest && Ext.userManifest.widgets) {
376 | Ext.theme.addManifest(Ext.userManifest.widgets);
377 | }
378 | }
379 |
380 | Ext.theme.setData(document.body, globalData);
381 | Ext.theme.render();
382 | Ext.theme.generateSlicerManifest();
383 | },
384 |
385 | generateSlicerManifest: function() {
386 | var now = new Date().getTime(),
387 | me = Ext.theme,
388 | // This function is defined by slicer.js (the framework-independent piece)
389 | gsm = window && window['generateSlicerManifest'],
390 | delta;
391 |
392 | me.generateStart = me.generateStart || now;
393 | delta = now - me.generateStart;
394 |
395 | if(gsm) {
396 | gsm();
397 | } else if(delta < (10 * 1000)){
398 | // allow the outer script wrapper a chance to inject the capture function
399 | // but stop trying after 10 seconds
400 | Ext.defer(Ext.theme.generateSlicerManifest, 100);
401 | }
402 | },
403 |
404 | /**
405 | * Sets the `data-slicer` attribute to the JSON-encoded value of the provided data.
406 | * @private
407 | */
408 | setData: function (el, data) {
409 | if (data) {
410 | var json = Ext.encode(data);
411 | if (json !== '{}') {
412 | el.setAttribute('data-slicer', json);
413 | }
414 | }
415 | },
416 |
417 | /**
418 | * This used to be `loadExtStylesheet`.
419 | * @private
420 | */
421 | loadCss: function (src, callback) {
422 | var xhr = new XMLHttpRequest();
423 |
424 | xhr.open('GET', src);
425 |
426 | xhr.onload = function() {
427 | var css = xhr.responseText,
428 | head = document.getElementsByTagName('head')[0],
429 | style = document.createElement('style');
430 |
431 | // There's bugginess in the next gradient syntax in WebKit r84622
432 | // This might be fixed in a later WebKit, but for now we're going to
433 | // strip it out here since compass generates it.
434 | //
435 | // TODO: Upgrade to later WebKit revision
436 | css = css.replace(/background(-image)?: ?-webkit-linear-gradient(?:.*?);/g, '');
437 |
438 | style.type = 'text/css';
439 | style.innerText = css;
440 |
441 | head.appendChild(style);
442 | callback();
443 | };
444 |
445 | xhr.send(null);
446 | }
447 | });
448 |
449 | console.log("registering ready listener...");
450 | Ext.onReady(Ext.theme.run, Ext.theme);
451 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * The application's namespace.
4 | */
5 | "name": "MyApp",
6 |
7 | /**
8 | * The version of the application.
9 | */
10 | "version": "1.0.0.0",
11 |
12 | /**
13 | * The relative path to the application's markup file (html, jsp, asp, etc.).
14 | */
15 | "indexHtmlPath": "index.html",
16 |
17 | /**
18 | * Comma-separated string with the paths of directories or files to search. Any classes
19 | * declared in these locations will be available in your class "requires" or in calls
20 | * to "Ext.require". The "app.dir" variable below is expanded to the path where the
21 | * application resides (the same folder in which this file is located).
22 | */
23 | "classpath": [
24 | "app"
25 | ],
26 |
27 | /**
28 | * Comma-separated string with the paths of directories or files to search. Any classes
29 | * declared in these locations will be automatically required and included in the build.
30 | * If any file defines an Ext JS override (using Ext.define with an "override" property),
31 | * that override will in fact only be included in the build if the target class specified
32 | * in the "override" property is also included.
33 | */
34 | "overrides": [
35 | "overrides"
36 | ],
37 |
38 | /**
39 | * The Sencha Framework for this application: "ext" or "touch".
40 | */
41 | "framework": "ext",
42 |
43 |
44 | /**
45 | * The toolkit to use. Select either "classic" or "modern".
46 | */
47 | "toolkit": "modern",
48 |
49 |
50 |
51 | /**
52 | * The name of the theme for this application.
53 | */
54 |
55 | "theme": "theme-material",
56 |
57 |
58 | /**
59 | * The list of required packages (with optional versions; default is "latest").
60 | *
61 | * For example,
62 | *
63 | * "requires": [
64 | * "charts"
65 | * ]
66 | */
67 | "requires": [],
68 |
69 | /**
70 | * Fashion build configuration properties.
71 | */
72 | "fashion": {
73 | "inliner": {
74 | /**
75 | * Disable resource inliner. Production builds enable this by default.
76 | */
77 | "enable": false
78 | }
79 | },
80 |
81 | /**
82 | * Sass configuration properties.
83 | */
84 | "sass": {
85 | /**
86 | * The root namespace to use when mapping *.scss files to classes in the
87 | * sass/src and sass/var directories. For example, "MyApp.view.Foo" would
88 | * map to "sass/src/view/Foo.scss". If we changed this to "MyApp.view" then
89 | * it would map to "sass/src/Foo.scss". To style classes outside the app's
90 | * root namespace, change this to "". Doing so would change the mapping of
91 | * "MyApp.view.Foo" to "sass/src/MyApp/view/Foo.scss".
92 | */
93 | "namespace": "MyApp",
94 |
95 | /**
96 | * Generated sass source settings
97 | *
98 | * "generated": {
99 | * // The file used to save sass variables edited via Sencha Inspector and Sencha Themer.
100 | * // This file will automatically be applied to the end of the scss build.
101 | * "var": "sass/save.scss",
102 | *
103 | * // The directory used to save generated sass sources.
104 | * // This directory will automatically be applied to the end of the scss build.
105 | * "src": "sass/save"
106 | * }
107 | *
108 | */
109 |
110 | "generated": {
111 | "var": "sass/save.scss",
112 | "src": "sass/save"
113 | },
114 |
115 |
116 | /**
117 | * Comma-separated list of files or folders containing extra Sass. These
118 | * files are automatically included in the Sass compilation. By default this
119 | * is just "etc/all.scss" to allow import directives to control the order
120 | * other files are included.
121 | *
122 | * All "etc" files are included at the top of the Sass compilation in their
123 | * dependency order:
124 | *
125 | * +-------+---------+
126 | * | | base |
127 | * | theme +---------+
128 | * | | derived |
129 | * +-------+---------+
130 | * | packages | (in package dependency order)
131 | * +-----------------+
132 | * | application |
133 | * +-----------------+
134 | */
135 | "etc": [
136 | "sass/etc/all.scss"
137 | ],
138 |
139 | /**
140 | * Comma-separated list of folders containing Sass variable definitions
141 | * files. These file can also define Sass mixins for use by components.
142 | *
143 | * All "var" files are included after "etc" files in the Sass compilation in
144 | * dependency order:
145 | *
146 | * +-------+---------+
147 | * | | base |
148 | * | theme +---------+
149 | * | | derived |
150 | * +-------+---------+
151 | * | packages | (in package dependency order)
152 | * +-----------------+
153 | * | application |
154 | * +-----------------+
155 | *
156 | * The "sass/var/all.scss" file is always included at the start of the var
157 | * block before any files associated with JavaScript classes.
158 | */
159 | "var": [
160 | "sass/var/all.scss",
161 | "sass/var"
162 | ],
163 |
164 | /**
165 | * Comma-separated list of folders containing Sass rule files.
166 | *
167 | * All "src" files are included after "var" files in the Sass compilation in
168 | * dependency order (the same order as "etc"):
169 | *
170 | * +-------+---------+
171 | * | | base |
172 | * | theme +---------+
173 | * | | derived |
174 | * +-------+---------+
175 | * | packages | (in package dependency order)
176 | * +-----------------+
177 | * | application |
178 | * +-----------------+
179 | */
180 | "src": [
181 | "sass/src"
182 | ]
183 | },
184 |
185 | /**
186 | * List of all JavaScript assets in the right execution order.
187 | *
188 | * Each item is an object with the following format:
189 | *
190 | * {
191 | * // Path to file. If the file is local this must be a relative path from
192 | * // this app.json file.
193 | * //
194 | * "path": "path/to/script.js", // REQUIRED
195 | *
196 | * // Set to true on one file to indicate that it should become the container
197 | * // for the concatenated classes.
198 | * //
199 | * "bundle": false, // OPTIONAL
200 | *
201 | * // Set to true to include this file in the concatenated classes.
202 | * //
203 | * "includeInBundle": false, // OPTIONAL
204 | *
205 | * // Specify as true if this file is remote and should not be copied into the
206 | * // build folder. Defaults to false for a local file which will be copied.
207 | * //
208 | * "remote": false, // OPTIONAL
209 | *
210 | * // If not specified, this file will only be loaded once, and cached inside
211 | * // localStorage until this value is changed. You can specify:
212 | * //
213 | * // - "delta" to enable over-the-air delta update for this file
214 | * // - "full" means full update will be made when this file changes
215 | * //
216 | * "update": "", // OPTIONAL
217 | *
218 | * // A value of true indicates that is a development mode only dependency.
219 | * // These files will not be copied into the build directory or referenced
220 | * // in the generate app.json manifest for the micro loader.
221 | * //
222 | * "bootstrap": false // OPTIONAL
223 | * }
224 | *
225 | */
226 | "js": [
227 | {
228 | "path": "${framework.dir}/build/ext-modern-all-debug.js"
229 | },
230 | {
231 | "path": "app.js",
232 | "bundle": true
233 | }
234 | ],
235 |
236 |
237 |
238 | /**
239 | * List of all CSS assets in the right inclusion order.
240 | *
241 | * Each item is an object with the following format:
242 | *
243 | * {
244 | * // Path to file. If the file is local this must be a relative path from
245 | * // this app.json file.
246 | * //
247 | * "path": "path/to/stylesheet.css", // REQUIRED
248 | *
249 | * // Specify as true if this file is remote and should not be copied into the
250 | * // build folder. Defaults to false for a local file which will be copied.
251 | * //
252 | * "remote": false, // OPTIONAL
253 | *
254 | * // If not specified, this file will only be loaded once, and cached inside
255 | * // localStorage until this value is changed. You can specify:
256 | * //
257 | * // - "delta" to enable over-the-air delta update for this file
258 | * // - "full" means full update will be made when this file changes
259 | * //
260 | * "update": "" // OPTIONAL
261 | * }
262 | */
263 | "css": [
264 | {
265 | // this entry uses an ant variable that is the calculated
266 | // value of the generated output css file for the app,
267 | // defined in .sencha/app/defaults.properties
268 | "path": "${build.out.css.path}",
269 | "bundle": true,
270 | "exclude": ["fashion"]
271 | }
272 | ],
273 |
274 | /**
275 | * This option is used to configure the dynamic loader. At present these options
276 | * are supported.
277 | *
278 | */
279 | "loader": {
280 | // This property controls how the loader manages caching for requests:
281 | //
282 | // - true: allows requests to receive cached responses
283 | // - false: disable cached responses by adding a random "cache buster"
284 | // - other: a string (such as the build.timestamp shown here) to allow
285 | // requests to be cached for this build.
286 | //
287 | "cache": false,
288 |
289 | // When "cache" is not true, this value is the request parameter used
290 | // to control caching.
291 | //
292 | "cacheParam": "_dc"
293 | },
294 |
295 | /**
296 | * Settings specific to production builds.
297 | */
298 | "production": {
299 | "output": {
300 | "appCache": {
301 | "enable": true,
302 | "path": "cache.appcache"
303 | }
304 | },
305 | "loader": {
306 | "cache": "${build.timestamp}"
307 | },
308 | "cache": {
309 | "enable": true
310 | },
311 | "compressor": {
312 | "type": "yui"
313 | }
314 | },
315 |
316 | /**
317 | * Settings specific to testing builds.
318 | */
319 | "testing": {
320 | },
321 |
322 | /**
323 | * Settings specific to development builds.
324 | */
325 | "development": {
326 | "watch": {
327 | "delay": 250
328 | }
329 | },
330 |
331 | /**
332 | * Controls the output structure of development-mode (bootstrap) artifacts. May
333 | * be specified by a string:
334 | *
335 | * "bootstrap": "${app.dir}"
336 | *
337 | * This will adjust the base path for all bootstrap objects, or expanded into object
338 | * form:
339 | *
340 | * "bootstrap": {
341 | * "base": "${app.dir},
342 | * "manifest": "bootstrap.json",
343 | * "microloader": "bootstrap.js",
344 | * "css": "bootstrap.css"
345 | * }
346 | *
347 | * You can optionally exclude entries from the manifest. For example, to exclude
348 | * the "loadOrder" (to help development load approximate a build) you can add:
349 | *
350 | * "bootstrap": {
351 | * "manifest": {
352 | * "path": "bootstrap.json",
353 | * "exclude": "loadOrder"
354 | * }
355 | * }
356 | *
357 | */
358 | "bootstrap": {
359 | "base": "${app.dir}",
360 |
361 | "microloader": "bootstrap.js",
362 | "css": "bootstrap.css"
363 | },
364 |
365 | /**
366 | * Controls the output directory for build resources. May be set with
367 | * either a string:
368 | *
369 | * "${workspace.build.dir}/${build.environment}/${app.name}"
370 | *
371 | * or an object containing values for various types of build artifacts:
372 | *
373 | * {
374 | * "base": "${workspace.build.dir}/${build.environment}/${app.name}",
375 | * "page": {
376 | * "path": "../index.html",
377 | * "enable": false
378 | * },
379 | * "css": "${app.output.resources}/${app.name}-all.css",
380 | * "js": "app.js",
381 | * "microloader": {
382 | * "path": "microloader.js",
383 | * "embed": true,
384 | * "enable": true
385 | * },
386 | * "manifest": {
387 | * "path": "app.json",
388 | * "embed": false,
389 | * "enable": "${app.output.microloader.enable}"
390 | * },
391 | * "resources": "resources",
392 | * "slicer": {
393 | * "path": "${app.output.resources}/images",
394 | * "enable": false
395 | * },
396 | * // Setting the "enable" property of this object to a Truthy value will cause a Application Cache
397 | * // manifest file to be generated based on this files appCache object. This file will then be injected
398 | * // into the index.html file of the built application
399 | * "appCache":{
400 | * "enable": false"
401 | * }
402 | * }
403 | *
404 | */
405 |
406 | "output": {
407 | "base": "${workspace.build.dir}/${build.environment}/${app.name}",
408 | "appCache": {
409 | "enable": false
410 | }
411 | },
412 |
413 |
414 | /**
415 | * Controls for localStorage caching
416 | * "cache": {
417 | * // This property controls whether localStorage caching of this manifest file is on or off.
418 | * // if disabled no deltas will be generated during a build and full updates will be disabled
419 | * "enable": false,
420 | *
421 | * // This property allows for global toggle of deltas.
422 | * // If set to a string the value will be used as the path to where deltas will be generated relative to you build.
423 | * // If set to a Truthy Value the default path ok "deltas" will be used
424 | * // If set to a Falsey value or if this property is not present deltas will be disabled and not generated.
425 | *
426 | * "deltas": "deltas"
427 | * }
428 | */
429 |
430 | "cache": {
431 | "enable": false,
432 | "deltas": true
433 | },
434 |
435 |
436 | /**
437 | * Used to automatically generate cache.manifest (HTML 5 application cache manifest)
438 | * file when you build.
439 | */
440 | "appCache": {
441 | /**
442 | * List of items in the CACHE MANIFEST section
443 | */
444 | "cache": [
445 | "index.html"
446 | ],
447 | /**
448 | * List of items in the NETWORK section
449 | */
450 | "network": [
451 | "*"
452 | ],
453 | /**
454 | * List of items in the FALLBACK section
455 | */
456 | "fallback": []
457 | },
458 |
459 | /**
460 | * Extra resources to be copied into the resource folder as specified in the "resources"
461 | * property of the "output" object. Folders specified in this list will be deeply copied.
462 | */
463 | "resources": [
464 | {
465 | "path": "resources",
466 | "output": "shared"
467 | }
468 | ],
469 |
470 | /**
471 | * Directory path to store all previous production builds. Note that the content
472 | * generated inside this directory must be kept intact for proper generation of
473 | * deltas between updates.
474 | */
475 |
476 | "archivePath": "archive",
477 |
478 |
479 |
480 | "slicer": null,
481 |
482 |
483 | /**
484 | * Build Profiles. This object's properties are each a "build profile". You can
485 | * add as many as you need to produce optimized builds for devices, themes, locales
486 | * or other criteria. Your "Ext.beforeLoad" hook (see index.html) is responsible for
487 | * selecting the desired build profile by setting "Ext.manifest" to one of these
488 | * names.
489 | *
490 | */
491 |
492 |
493 | /**
494 | * File / directory name patttern to ignore when copying to the builds. Must be a
495 | * valid regular expression.
496 | */
497 | "ignore": [
498 | "(^|/)CVS(/?$|/.*?$)"
499 | ],
500 |
501 | /**
502 | * Uniquely generated id for this application, used as prefix for localStorage keys.
503 | * Normally you should never change this value.
504 | */
505 | "id": "26085d72-4f91-4fa2-8ae4-6a52d73f4fa6"
506 | }
507 |
--------------------------------------------------------------------------------
/resources/devs.json:
--------------------------------------------------------------------------------
1 | {
2 | "results": [{
3 | "gender": "female",
4 | "name": {
5 | "title": "mrs",
6 | "first": "آنیتا",
7 | "last": "مرادی"
8 | },
9 | "location": {
10 | "street": "2233 یادگار امام",
11 | "city": "مشهد",
12 | "state": "ایلام",
13 | "postcode": 72013
14 | },
15 | "email": "آنیتا.مرادی@example.com",
16 | "registered": 981937960,
17 | "phone": "000-95867341",
18 | "cell": "0990-625-8270",
19 | "picture": {
20 | "large": "https://randomuser.me/api/portraits/women/4.jpg",
21 | "medium": "https://randomuser.me/api/portraits/med/women/4.jpg",
22 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/4.jpg"
23 | },
24 | "nat": "IR",
25 | "skills": ["Ext JS", "Touch", "Architect"]
26 | }, {
27 | "gender": "female",
28 | "name": {
29 | "title": "miss",
30 | "first": "clara",
31 | "last": "rasmussen"
32 | },
33 | "location": {
34 | "street": "9595 sandagervej",
35 | "city": "gjern",
36 | "state": "sjælland",
37 | "postcode": 47809
38 | },
39 | "email": "clara.rasmussen@example.com",
40 | "registered": 1435970894,
41 | "phone": "83667618",
42 | "cell": "14386226",
43 | "picture": {
44 | "large": "https://randomuser.me/api/portraits/women/63.jpg",
45 | "medium": "https://randomuser.me/api/portraits/med/women/63.jpg",
46 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/63.jpg"
47 | },
48 | "nat": "DK",
49 | "skills": ["Ext JS"]
50 | }, {
51 | "gender": "male",
52 | "name": {
53 | "title": "mr",
54 | "first": "scott",
55 | "last": "daniels"
56 | },
57 | "location": {
58 | "street": "3191 lakeview st",
59 | "city": "mackay",
60 | "state": "victoria",
61 | "postcode": 4216
62 | },
63 | "email": "scott.daniels@example.com",
64 | "registered": 1100913238,
65 | "phone": "03-0976-0137",
66 | "cell": "0476-727-335",
67 | "picture": {
68 | "large": "https://randomuser.me/api/portraits/men/63.jpg",
69 | "medium": "https://randomuser.me/api/portraits/med/men/63.jpg",
70 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/63.jpg"
71 | },
72 | "nat": "AU",
73 | "skills": ["Ext JS", "Themer", "Inspector"]
74 | }, {
75 | "gender": "female",
76 | "name": {
77 | "title": "ms",
78 | "first": "laura",
79 | "last": "kelley"
80 | },
81 | "location": {
82 | "street": "5030 the grove",
83 | "city": "gorey",
84 | "state": "meath",
85 | "postcode": 61294
86 | },
87 | "email": "laura.kelley@example.com",
88 | "registered": 1086131809,
89 | "phone": "071-756-7136",
90 | "cell": "081-245-7966",
91 | "picture": {
92 | "large": "https://randomuser.me/api/portraits/women/34.jpg",
93 | "medium": "https://randomuser.me/api/portraits/med/women/34.jpg",
94 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/34.jpg"
95 | },
96 | "nat": "IE",
97 | "skills": ["Touch", "Architect", "Themer", "Inspector"]
98 | }, {
99 | "gender": "female",
100 | "name": {
101 | "title": "mrs",
102 | "first": "josefa",
103 | "last": "moya"
104 | },
105 | "location": {
106 | "street": "2678 calle de atocha",
107 | "city": "pontevedra",
108 | "state": "canarias",
109 | "postcode": 20297
110 | },
111 | "email": "josefa.moya@example.com",
112 | "registered": 1262826756,
113 | "phone": "992-764-676",
114 | "cell": "683-944-461",
115 | "picture": {
116 | "large": "https://randomuser.me/api/portraits/women/51.jpg",
117 | "medium": "https://randomuser.me/api/portraits/med/women/51.jpg",
118 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/51.jpg"
119 | },
120 | "nat": "ES",
121 | "skills": ["Touch", "Architect"]
122 | }, {
123 | "gender": "female",
124 | "name": {
125 | "title": "ms",
126 | "first": "nalan",
127 | "last": "orbay"
128 | },
129 | "location": {
130 | "street": "5955 necatibey cd",
131 | "city": "denizli",
132 | "state": "mardin",
133 | "postcode": 15900
134 | },
135 | "email": "nalan.orbay@example.com",
136 | "registered": 1110543022,
137 | "phone": "(168)-619-9533",
138 | "cell": "(565)-775-7094",
139 | "picture": {
140 | "large": "https://randomuser.me/api/portraits/women/43.jpg",
141 | "medium": "https://randomuser.me/api/portraits/med/women/43.jpg",
142 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/43.jpg"
143 | },
144 | "nat": "TR",
145 | "skills": ["Ext JS", "Inspector"]
146 | }, {
147 | "gender": "female",
148 | "name": {
149 | "title": "mrs",
150 | "first": "alexis",
151 | "last": "williams"
152 | },
153 | "location": {
154 | "street": "6776 balmoral st",
155 | "city": "fauquier",
156 | "state": "nunavut",
157 | "postcode": 44317
158 | },
159 | "email": "alexis.williams@example.com",
160 | "registered": 1242547554,
161 | "phone": "468-827-8351",
162 | "cell": "081-301-8166",
163 | "picture": {
164 | "large": "https://randomuser.me/api/portraits/women/64.jpg",
165 | "medium": "https://randomuser.me/api/portraits/med/women/64.jpg",
166 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/64.jpg"
167 | },
168 | "nat": "CA",
169 | "skills": ["Architect", "Themer"]
170 | }, {
171 | "gender": "male",
172 | "name": {
173 | "title": "mr",
174 | "first": "wesley",
175 | "last": "dunn"
176 | },
177 | "location": {
178 | "street": "1103 victoria road",
179 | "city": "chester",
180 | "state": "buckinghamshire",
181 | "postcode": "C76 7LN"
182 | },
183 | "email": "wesley.dunn@example.com",
184 | "registered": 1257651371,
185 | "phone": "017683 47210",
186 | "cell": "0726-622-046",
187 | "picture": {
188 | "large": "https://randomuser.me/api/portraits/men/13.jpg",
189 | "medium": "https://randomuser.me/api/portraits/med/men/13.jpg",
190 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/13.jpg"
191 | },
192 | "nat": "GB",
193 | "skills": ["Touch", "Architect"]
194 | }, {
195 | "gender": "male",
196 | "name": {
197 | "title": "mr",
198 | "first": "byron",
199 | "last": "elliott"
200 | },
201 | "location": {
202 | "street": "7020 richmond park",
203 | "city": "cobh",
204 | "state": "mayo",
205 | "postcode": 61467
206 | },
207 | "email": "byron.elliott@example.com",
208 | "registered": 1017793969,
209 | "phone": "071-757-5851",
210 | "cell": "081-480-9062",
211 | "picture": {
212 | "large": "https://randomuser.me/api/portraits/men/14.jpg",
213 | "medium": "https://randomuser.me/api/portraits/med/men/14.jpg",
214 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/14.jpg"
215 | },
216 | "nat": "IE",
217 | "skills": ["Ext JS"]
218 | }, {
219 | "gender": "female",
220 | "name": {
221 | "title": "mrs",
222 | "first": "rhonda",
223 | "last": "fuller"
224 | },
225 | "location": {
226 | "street": "9007 lovers ln",
227 | "city": "pomona",
228 | "state": "mississippi",
229 | "postcode": 28255
230 | },
231 | "email": "rhonda.fuller@example.com",
232 | "registered": 1040528620,
233 | "phone": "(779)-624-9233",
234 | "cell": "(233)-598-9804",
235 | "picture": {
236 | "large": "https://randomuser.me/api/portraits/women/51.jpg",
237 | "medium": "https://randomuser.me/api/portraits/med/women/51.jpg",
238 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/51.jpg"
239 | },
240 | "nat": "US",
241 | "skills": ["Touch", "Architect", "Inspector"]
242 | }, {
243 | "gender": "male",
244 | "name": {
245 | "title": "mr",
246 | "first": "edwin",
247 | "last": "mitchell"
248 | },
249 | "location": {
250 | "street": "9740 herbert road",
251 | "city": "laytown-bettystown-mornington",
252 | "state": "mayo",
253 | "postcode": 68255
254 | },
255 | "email": "edwin.mitchell@example.com",
256 | "registered": 1149677403,
257 | "phone": "021-496-8244",
258 | "cell": "081-917-4018",
259 | "picture": {
260 | "large": "https://randomuser.me/api/portraits/men/81.jpg",
261 | "medium": "https://randomuser.me/api/portraits/med/men/81.jpg",
262 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/81.jpg"
263 | },
264 | "nat": "IE",
265 | "skills": ["Ext JS", "Inspector"]
266 | }, {
267 | "gender": "male",
268 | "name": {
269 | "title": "mr",
270 | "first": "alfonso",
271 | "last": "jimenez"
272 | },
273 | "location": {
274 | "street": "6066 calle de la almudena",
275 | "city": "granada",
276 | "state": "aragón",
277 | "postcode": 12933
278 | },
279 | "email": "alfonso.jimenez@example.com",
280 | "registered": 1363696315,
281 | "phone": "984-928-051",
282 | "cell": "624-175-398",
283 | "picture": {
284 | "large": "https://randomuser.me/api/portraits/men/45.jpg",
285 | "medium": "https://randomuser.me/api/portraits/med/men/45.jpg",
286 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/45.jpg"
287 | },
288 | "nat": "ES",
289 | "skills": ["Architect", "Inspector"]
290 | }, {
291 | "gender": "male",
292 | "name": {
293 | "title": "monsieur",
294 | "first": "dorian",
295 | "last": "dumas"
296 | },
297 | "location": {
298 | "street": "4294 rue louis-garrand",
299 | "city": "renens vd 1",
300 | "state": "genève",
301 | "postcode": 9377
302 | },
303 | "email": "dorian.dumas@example.com",
304 | "registered": 1134806701,
305 | "phone": "(217)-574-0234",
306 | "cell": "(988)-834-3149",
307 | "picture": {
308 | "large": "https://randomuser.me/api/portraits/men/18.jpg",
309 | "medium": "https://randomuser.me/api/portraits/med/men/18.jpg",
310 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/18.jpg"
311 | },
312 | "nat": "CH",
313 | "skills": ["Ext JS", "Touch", "Architect", "Themer", "Inspector"]
314 | }, {
315 | "gender": "female",
316 | "name": {
317 | "title": "ms",
318 | "first": "celia",
319 | "last": "herrero"
320 | },
321 | "location": {
322 | "street": "9667 calle de argumosa",
323 | "city": "gandía",
324 | "state": "comunidad valenciana",
325 | "postcode": 59398
326 | },
327 | "email": "celia.herrero@example.com",
328 | "registered": 1165737413,
329 | "phone": "931-253-643",
330 | "cell": "622-270-157",
331 | "picture": {
332 | "large": "https://randomuser.me/api/portraits/women/79.jpg",
333 | "medium": "https://randomuser.me/api/portraits/med/women/79.jpg",
334 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/79.jpg"
335 | },
336 | "nat": "ES",
337 | "skills": ["Ext JS", "Touch", "Architect", "Themer"]
338 | }, {
339 | "gender": "male",
340 | "name": {
341 | "title": "mr",
342 | "first": "eugenio",
343 | "last": "campos"
344 | },
345 | "location": {
346 | "street": "5709 calle de pedro bosch",
347 | "city": "toledo",
348 | "state": "comunidad valenciana",
349 | "postcode": 54790
350 | },
351 | "email": "eugenio.campos@example.com",
352 | "registered": 1087042761,
353 | "phone": "956-230-182",
354 | "cell": "607-314-519",
355 | "picture": {
356 | "large": "https://randomuser.me/api/portraits/men/60.jpg",
357 | "medium": "https://randomuser.me/api/portraits/med/men/60.jpg",
358 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/60.jpg"
359 | },
360 | "nat": "ES",
361 | "skills": ["Ext JS", "Architect"]
362 | }, {
363 | "gender": "male",
364 | "name": {
365 | "title": "mr",
366 | "first": "eren",
367 | "last": "kuday"
368 | },
369 | "location": {
370 | "street": "9387 doktorlar cd",
371 | "city": "sivas",
372 | "state": "çorum",
373 | "postcode": 50819
374 | },
375 | "email": "eren.kuday@example.com",
376 | "registered": 938918387,
377 | "phone": "(464)-012-2573",
378 | "cell": "(688)-357-6758",
379 | "picture": {
380 | "large": "https://randomuser.me/api/portraits/men/81.jpg",
381 | "medium": "https://randomuser.me/api/portraits/med/men/81.jpg",
382 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/81.jpg"
383 | },
384 | "nat": "TR",
385 | "skills": ["Architect", "Inspector"]
386 | }, {
387 | "gender": "female",
388 | "name": {
389 | "title": "ms",
390 | "first": "maria",
391 | "last": "müller"
392 | },
393 | "location": {
394 | "street": "4367 birkenstraße",
395 | "city": "mönchengladbach",
396 | "state": "niedersachsen",
397 | "postcode": 49067
398 | },
399 | "email": "maria.müller@example.com",
400 | "registered": 1134863750,
401 | "phone": "0219-5654567",
402 | "cell": "0178-8084884",
403 | "picture": {
404 | "large": "https://randomuser.me/api/portraits/women/86.jpg",
405 | "medium": "https://randomuser.me/api/portraits/med/women/86.jpg",
406 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/86.jpg"
407 | },
408 | "nat": "DE",
409 | "skills": ["Touch"]
410 | }, {
411 | "gender": "female",
412 | "name": {
413 | "title": "madame",
414 | "first": "leana",
415 | "last": "legrand"
416 | },
417 | "location": {
418 | "street": "2084 rue de l'abbé-patureau",
419 | "city": "romanel-sur-morges",
420 | "state": "bern",
421 | "postcode": 9094
422 | },
423 | "email": "leana.legrand@example.com",
424 | "registered": 1017709518,
425 | "phone": "(857)-939-6129",
426 | "cell": "(719)-002-9483",
427 | "picture": {
428 | "large": "https://randomuser.me/api/portraits/women/20.jpg",
429 | "medium": "https://randomuser.me/api/portraits/med/women/20.jpg",
430 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/20.jpg"
431 | },
432 | "nat": "CH",
433 | "skills": ["Ext JS", "Themer", "Inspector"]
434 | }, {
435 | "gender": "male",
436 | "name": {
437 | "title": "mr",
438 | "first": "william",
439 | "last": "rasmussen"
440 | },
441 | "location": {
442 | "street": "7244 ridderhatten",
443 | "city": "ulsted, hals",
444 | "state": "danmark",
445 | "postcode": 88846
446 | },
447 | "email": "william.rasmussen@example.com",
448 | "registered": 1312994805,
449 | "phone": "60305590",
450 | "cell": "08044701",
451 | "picture": {
452 | "large": "https://randomuser.me/api/portraits/men/93.jpg",
453 | "medium": "https://randomuser.me/api/portraits/med/men/93.jpg",
454 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/93.jpg"
455 | },
456 | "nat": "DK",
457 | "skills": ["Architect"]
458 | }, {
459 | "gender": "male",
460 | "name": {
461 | "title": "mr",
462 | "first": "udo",
463 | "last": "fogaça"
464 | },
465 | "location": {
466 | "street": "5418 rua são paulo ",
467 | "city": "paranaguá",
468 | "state": "distrito federal",
469 | "postcode": 66556
470 | },
471 | "email": "udo.fogaça@example.com",
472 | "registered": 1304514894,
473 | "phone": "(95) 1080-6180",
474 | "cell": "(92) 5634-1998",
475 | "picture": {
476 | "large": "https://randomuser.me/api/portraits/men/83.jpg",
477 | "medium": "https://randomuser.me/api/portraits/med/men/83.jpg",
478 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/83.jpg"
479 | },
480 | "nat": "BR",
481 | "skills": ["Touch"]
482 | }, {
483 | "gender": "male",
484 | "name": {
485 | "title": "mr",
486 | "first": "umit",
487 | "last": "polderman"
488 | },
489 | "location": {
490 | "street": "8406 neude",
491 | "city": "deurne",
492 | "state": "utrecht",
493 | "postcode": 42964
494 | },
495 | "email": "umit.polderman@example.com",
496 | "registered": 1369329139,
497 | "phone": "(566)-652-4345",
498 | "cell": "(329)-436-2686",
499 | "picture": {
500 | "large": "https://randomuser.me/api/portraits/men/23.jpg",
501 | "medium": "https://randomuser.me/api/portraits/med/men/23.jpg",
502 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/23.jpg"
503 | },
504 | "nat": "NL",
505 | "skills": ["Ext JS"]
506 | }, {
507 | "gender": "male",
508 | "name": {
509 | "title": "mr",
510 | "first": "derrick",
511 | "last": "simmmons"
512 | },
513 | "location": {
514 | "street": "1913 karen dr",
515 | "city": "chicago",
516 | "state": "rhode island",
517 | "postcode": 68934
518 | },
519 | "email": "derrick.simmmons@example.com",
520 | "registered": 1220029946,
521 | "phone": "(752)-864-3066",
522 | "cell": "(663)-031-2805",
523 | "picture": {
524 | "large": "https://randomuser.me/api/portraits/men/98.jpg",
525 | "medium": "https://randomuser.me/api/portraits/med/men/98.jpg",
526 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/98.jpg"
527 | },
528 | "nat": "US",
529 | "skills": ["Ext JS", "Inspector"]
530 | }, {
531 | "gender": "male",
532 | "name": {
533 | "title": "mr",
534 | "first": "thiago",
535 | "last": "fabre"
536 | },
537 | "location": {
538 | "street": "8318 rue dubois",
539 | "city": "avignon",
540 | "state": "alpes-maritimes",
541 | "postcode": 48154
542 | },
543 | "email": "thiago.fabre@example.com",
544 | "registered": 1036032941,
545 | "phone": "04-13-58-24-57",
546 | "cell": "06-46-53-98-99",
547 | "picture": {
548 | "large": "https://randomuser.me/api/portraits/men/97.jpg",
549 | "medium": "https://randomuser.me/api/portraits/med/men/97.jpg",
550 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/97.jpg"
551 | },
552 | "nat": "FR",
553 | "skills": ["Ext JS", "Themer", "Inspector"]
554 | }, {
555 | "gender": "female",
556 | "name": {
557 | "title": "miss",
558 | "first": "maria",
559 | "last": "johansen"
560 | },
561 | "location": {
562 | "street": "2001 landlystvej",
563 | "city": "aarhus n",
564 | "state": "syddanmark",
565 | "postcode": 24118
566 | },
567 | "email": "maria.johansen@example.com",
568 | "registered": 1173317526,
569 | "phone": "07431093",
570 | "cell": "19247420",
571 | "picture": {
572 | "large": "https://randomuser.me/api/portraits/women/86.jpg",
573 | "medium": "https://randomuser.me/api/portraits/med/women/86.jpg",
574 | "thumbnail": "https://randomuser.me/api/portraits/thumb/women/86.jpg"
575 | },
576 | "nat": "DK",
577 | "skills": ["Ext JS", "Themer"]
578 | }, {
579 | "gender": "male",
580 | "name": {
581 | "title": "mr",
582 | "first": "benjamin",
583 | "last": "christiansen"
584 | },
585 | "location": {
586 | "street": "5831 baldersvej",
587 | "city": "hornbæk",
588 | "state": "hovedstaden",
589 | "postcode": 68948
590 | },
591 | "email": "benjamin.christiansen@example.com",
592 | "registered": 1124892789,
593 | "phone": "00803519",
594 | "cell": "75830042",
595 | "picture": {
596 | "large": "https://randomuser.me/api/portraits/men/55.jpg",
597 | "medium": "https://randomuser.me/api/portraits/med/men/55.jpg",
598 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/55.jpg"
599 | },
600 | "nat": "DK",
601 | "skills": ["Ext JS", "Inspector"]
602 | }, {
603 | "gender": "male",
604 | "name": {
605 | "title": "mr",
606 | "first": "elliot",
607 | "last": "grewal"
608 | },
609 | "location": {
610 | "street": "7334 richmond ave",
611 | "city": "bath",
612 | "state": "british columbia",
613 | "postcode": 66850
614 | },
615 | "email": "elliot.grewal@example.com",
616 | "registered": 945339428,
617 | "phone": "743-264-6236",
618 | "cell": "765-113-6571",
619 | "picture": {
620 | "large": "https://randomuser.me/api/portraits/men/75.jpg",
621 | "medium": "https://randomuser.me/api/portraits/med/men/75.jpg",
622 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/75.jpg"
623 | },
624 | "nat": "CA",
625 | "skills": ["Touch"]
626 | }, {
627 | "gender": "male",
628 | "name": {
629 | "title": "mr",
630 | "first": "محمدطاها",
631 | "last": "نجاتی"
632 | },
633 | "location": {
634 | "street": "3366 دستغیب",
635 | "city": "قرچک",
636 | "state": "مازندران",
637 | "postcode": 64211
638 | },
639 | "email": "محمدطاها.نجاتی@example.com",
640 | "registered": 1093712781,
641 | "phone": "053-20321869",
642 | "cell": "0973-855-0667",
643 | "picture": {
644 | "large": "https://randomuser.me/api/portraits/men/47.jpg",
645 | "medium": "https://randomuser.me/api/portraits/med/men/47.jpg",
646 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/47.jpg"
647 | },
648 | "nat": "IR",
649 | "skills": ["Ext JS", "Themer", "Inspector"]
650 | }, {
651 | "gender": "male",
652 | "name": {
653 | "title": "mr",
654 | "first": "vedat",
655 | "last": "abanuz"
656 | },
657 | "location": {
658 | "street": "4319 abanoz sk",
659 | "city": "konya",
660 | "state": "kilis",
661 | "postcode": 27947
662 | },
663 | "email": "vedat.abanuz@example.com",
664 | "registered": 935174224,
665 | "phone": "(830)-683-9397",
666 | "cell": "(665)-483-0603",
667 | "picture": {
668 | "large": "https://randomuser.me/api/portraits/men/62.jpg",
669 | "medium": "https://randomuser.me/api/portraits/med/men/62.jpg",
670 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/62.jpg"
671 | },
672 | "nat": "TR",
673 | "skills": ["Touch", "Architect"]
674 | }, {
675 | "gender": "male",
676 | "name": {
677 | "title": "mr",
678 | "first": "elmer",
679 | "last": "cavalcanti"
680 | },
681 | "location": {
682 | "street": "2287 rua castro alves ",
683 | "city": "florianópolis",
684 | "state": "roraima",
685 | "postcode": 39910
686 | },
687 | "email": "elmer.cavalcanti@example.com",
688 | "registered": 915306551,
689 | "phone": "(62) 9460-6223",
690 | "cell": "(78) 7966-7481",
691 | "picture": {
692 | "large": "https://randomuser.me/api/portraits/men/14.jpg",
693 | "medium": "https://randomuser.me/api/portraits/med/men/14.jpg",
694 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/14.jpg"
695 | },
696 | "nat": "BR",
697 | "skills": ["Ext JS", "Architect"]
698 | }, {
699 | "gender": "male",
700 | "name": {
701 | "title": "mr",
702 | "first": "valentin",
703 | "last": "sanchez"
704 | },
705 | "location": {
706 | "street": "4434 avenida del planetario",
707 | "city": "logroño",
708 | "state": "extremadura",
709 | "postcode": 58385
710 | },
711 | "email": "valentin.sanchez@example.com",
712 | "registered": 1161473236,
713 | "phone": "926-471-696",
714 | "cell": "648-748-237",
715 | "picture": {
716 | "large": "https://randomuser.me/api/portraits/men/96.jpg",
717 | "medium": "https://randomuser.me/api/portraits/med/men/96.jpg",
718 | "thumbnail": "https://randomuser.me/api/portraits/thumb/men/96.jpg"
719 | },
720 | "nat": "ES",
721 | "skills": ["Ext JS"]
722 | }],
723 | "info": {
724 | "seed": "rwc",
725 | "results": 30,
726 | "page": 1,
727 | "version": "1.0"
728 | }
729 | }
--------------------------------------------------------------------------------