Widgets 101: Customizing and Creating Widgets with the ... · Naming conventions Ordering/grouping of CSS rules Help dealing with specificity Flavors Block-Element-Modifier(BEM)

Post on 30-Jun-2020

8 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

Widgets 101: Customizing and Creating

Widgets with the ArcGIS API for JavaScript

JC Franco – @arfncode

Matt Driscoll – @driskull

Welcome

AgendaShort URL: bit.ly/widgets101

About widgets

Building blocks

Building a widget

3.x

4.x

Tips & best practices

Resources

Q & A

WidgetsWhat?

Encapsulated

Cohesive

Single-purpose pieces of functionality

User interface

Why?

Reusable

Interchangeable

Modular

How?

Different frameworks are available

Focusing on Dijit

Dojo toolkitFoundation of ArcGIS JavaScript API

AMD support

Class-based inheritance

Internationalization

DijitDojo’s UI Library

Separate namespace (dijit)

Built on top of Dojo

Has themes

Asynchronous Module Definition (AMD)Asynchronous loading

Web-based solution

Lazy loading

Fewer globals

Dependency handling

AMD exampledefine

require

// moduleA.js

define(["moduleB"], function (moduleB) {

// module API

return {

_data: 100,

calculate: function () {

moduleB.calculate(this._data);

}

};

});

// main.js

require(["moduleA"], function (moduleA) {

moduleA.calculate();

});

AMD Plugins

text

"dojo/text!./templates/WikiWidget.html"

i18n

"dojo/i18n!./nls/WikiWidget",

Building blocks

dijit/_WidgetBase

What you get

Lifecycle

constructor

postMixInProperties

buildRendering

postCreate

startup

destroy

Events

Getters/Setters

Property watching

constructor

Called immediately when widget is created

Can be used for initialization

Can be used to manipulate widget parameters

constructor: function(params) {

// initialize private variables

this._activeTasks = [];

// manipulate user-provided params

if (params && params.oldProp {

params.newProp = params.oldProp;

delete params.oldProp;

}

}

postMixInProperties

Called after properties have been mixed into the instance

Can be used to access/alter properties after being mixed in, but before rendering

For example

postMixInProperties: function() {

this.get("inherited");

this._initialTitle = this.title;

}

var myWidget = new MyWidget({ title: "myTitle" }, "sample-node");

myWidget.toUppercase();

console.log(myWidget.title); // MYTITLE

console.log(myWidget._initialTitle); // myTitle

buildRendering

Widget template is parsed and its DOM is available

Not attached to the DOM tree

buildRendering: function() {

this.get("inherited");

if (this.editMode) {

// editor added before widget is displayed

this._attachEditor(this.domNode);

}

}

postCreate

Most widget DOM nodes are ready at this point

Widget not attached to the DOM yet

Most common point for adding custom logic

postCreate: function() {

this.get("inherited");

when destroyed

this._handleInput)

// set up event listeners

// `this.own` disposes handle

this.own(

on(this.inputNode, "input",

);

this._activeTasks.push(

this._initialize()

);

}

startup

Called manually or by dojo/parser, initializes all children

Recommended point for doing size calculations

Must always call when creating widgets programmatically

startup: function() {

this.get("inherited");

this._resize();

}

destroy

Used for teardown logic

By default, destroys top-level support widgets

Called manually to trigger widget disposal

All handles registered with this.own get removed

destroy: function() {

this.get("inherited");

this._activeTasks.forEach(function(process) {

process.cancel();

});

}

Events// widget function

startTimer: function() {

setInterval(function() {

this.emit("tick");

}.bind(this), 1000);

}

timerWidget.on("tick", function() {

console.log("timer ticked!");

});

timerWidget.startTimer();

// timer ticked!

// timer ticked!

// timer ticked!

Getters/Setterswidget.get("title"); // old

widget.set("title", "new");

widget.get("title"); // new

Watchwidget.watch("title", function(propName, oldValue, newValue) {

console.log(

propName + " changed from ", oldValue, " to ", newValue

);

});

widget.get("title"); // old

widget.set("title", "new"); // "title" changed from "old" to "new"

Code organizationKeep code modular and organized

Code organization: HTMLExtract HTML to separate file

Mix in dijit/_TemplatedMixin

Renders HTML based on a template string (use dojo/text plugin)

Create DOM node attachments

Code organization: CSSExtract widget-specific styles to separate stylesheet

@import widget stylesheet wherever applicable

Example: before/* ./MyWidget.js */

define([

"dijit/_WidgetBase",

"dijit/_TemplatedMixin"

],

function (

_WidgetBase, _TemplatedMixin

) {

return _WidgetBase.createSubclass([_TemplatedMixin], {

templateString: "<div style='background-color: chartreuse;'>" +

"<label style='font-weight: bolder;'>°˖✧◝(⁰▿⁰)◜✧"</div>";

});

});

Example: after

MyWidget.html

<div class="my-widget">

<label class="my-widget text">°˖✧◝(⁰▿⁰)◜✧˖°</label></div>

Example: after

MyWidget.css

.my-widget {

background-color: chartreuse

}

.my-widget text {

font-size: 1.5em;

}

Example: after

MyWidget.js

define([

"dijit/_WidgetBase",

"dijit/_TemplatedMixin",

"dojo/text!./templates/MyWidget.html"

],

function (

_WidgetBase, _TemplatedMixin,

template

) {

return _WidgetBase.createSubclass([_TemplatedMixin], {

templateString: template

});

});

CSSUse classes

<style>

.my-widget {

background-color: chartreuse;

}

</style>

<div class="my-widget">...</div>

and avoid inline styles

<div style="background-color: chartreuse">...</div>

Accessibility (a11y)Enable your application to be used by everyone

Consider other input devices besides the mouse

Keyboard

Touch

Screen reader

semantic markup, ARIA roles

dijit/a11yclick

Internationalization (i18n)Keep text separate from application logic

Support multiple languages

Helps ease translation

define({

root: ({

"button": "Home",

"title": "Default extent"

}),

"ar": 1,

...

"zh-cn": 1

});

DOM manipulationHere to help...

dojo/dom

dojo/dom-attr

dojo/dom-class

dojo/dom-construct

dojo/dom-style (used sparingly)

DOM manipulationHere to help...

// without `dojo/dom-class`

document.getElementById("container-id")

.classList.add("round-borders");

// with `dojo/dom-class`

domClass.add("container-id", "round-borders");

Let's build a widget!

WikiWidget (requirements)Use Wikipedia API to geosearch for entries

Display results in a list

List items should center on the map and display a popup

The popup should have a link for more info (wiki page)

Preview

That's all for 3.x

4.x WidgetsWidget Pattern

View – the face

ViewModel – the brain

ViewUses ViewModel APIs to render the UI

View-specific logic resides here

ViewModelCore logic of widget resides here

Provides necessary APIs for the view to do it's thing

No DOM/UI concerns (think data)

BenefitsReusable

Testable

Logic without UI concerns

Framework compatibility

Tips & best practices

Linting (code analysis)Highlight issues in your code based on predefined rules

JSLint

JSHint

ESLint

FormattingFormat your code based on predefined rules

ESLint

JS Beautifier

Task runnersAutomate all the things

Grunt

Gulp

CSS preprocessorsFeatures

Variables

Mixins

@import & @extend

Allow us to

Restyle quickly

Theme

Write less code

Flavors

Sass

Stylus

Less

Demo

CSS methodologiesEstablish guidelines/rules for maintainable CSS

CSS & HTML best practices

Naming conventions

Ordering/grouping of CSS rules

Help dealing with specificity

Flavors

Block-Element-Modifier (BEM)

Scalable and Modular Architecture for CSS (SMACSS)

Object Oriented CSS (OOCSS)

SUIT CSS

Atomic OOBEMITSCSS

No silver bullet - choose what's best for your project/team

Use the source, Luke.Use GitHub to browse code and learn more about existing projects

dojo

dijit

dojox

etc...

Wrapping up

Suggested sessions

Wednesday

Operations Dashboard: Extending with Custom Widgets

Thursday

Web AppBuilder for ArcGIS: Customizing and Extending

Web AppBuilder for ArcGIS: Build your First Widget in 15 mins

Extending the Operations Dashboard for ArcGIS

ArcGIS API 4.0 for JavaScript: Patterns and Best Practices

Get The Code

bit.ly/widgets101

Please take our survey

Your feedback allows us to help maintain high

standards and to help presenters

Q & AQuestions?

Bonus: Haikuuser conference—

attended widget session

satisfaction now

top related