/////////////////////////////////////////////////////////////////////////// // Copyright © 2014 - 2018 Esri. All Rights Reserved. // // Licensed under the Apache License Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /////////////////////////////////////////////////////////////////////////// define([ 'dojo/_base/declare', 'dojo/_base/lang', 'dojo/_base/array', 'dojo/_base/html', 'dojo/on', 'dojo/dom-construct', 'dojo/query', 'dijit/_WidgetBase', 'dijit/_TemplatedMixin', 'jimu/dijit/ViewStack', 'dojox/gesture/swipe', 'dojox/gesture/tap', 'jimu/utils' ], function ( declare, lang, array, html, on, domConstruct, query, _WidgetBase, _TemplatedMixin, ViewStack, swipe, tap, utils) { /* global jimuConfig */ //label is not visible if node width is less than 80px, and icon should be scaled. var NORMAL_MIN_WIDTH = 80, NORMAL_WIDTH = 120, //node width should not be larger than this value. MIN_MARGIN = 20, //minimux margin between this dom and the map box. MIN_NODE_WIDTH = 10, //If node width is less than 10px, the node will not be visible. MAX_ROWCOL = 4, MIN_ROWCOL = 3, CURRENT_PAGE = 0; //3*3 tile nodes, with a close button return declare([_WidgetBase, _TemplatedMixin], { baseClass: 'jimu-header-more-popup', templateString: '
' + '
', margin: 4, postCreate: function () { this.nodes = []; this.pages = []; this.createCloseBtn(); }, startup: function () { this.viewStack = new ViewStack({ views: [], viewType: 'dom' }, this.pagesNode); this.viewStack.startup(); //Change page on swipe end on(this.pagesNode, swipe.end, lang.hitch(this, function (e) { if (CURRENT_PAGE < this.maximumPages - 1 && e.dx && e.dx < 0) { CURRENT_PAGE++; this._selectPage(CURRENT_PAGE); } else { if (e.dx && e.dx > 0 && CURRENT_PAGE > 0) { CURRENT_PAGE--; this._selectPage(CURRENT_PAGE); } } })); this.resize(); }, resize: function () { var gridParam = this._calculateGridParam(), closeDiv; if (gridParam !== null) { html.setStyle(this.domNode, utils.getPositionStyle(gridParam.position)); this.nodeWidth = gridParam.cellSize - this.margin; if (!this.oldGridParam || this.oldGridParam.rows !== gridParam.rows || this.oldGridParam.cols !== gridParam.cols) { //grid changed, re-create the pages this.clearPages(); this.createPages(gridParam); } this.nodes.forEach(lang.hitch(this, function (node, i) { this.setItemNodePosition(node, i, gridParam); })); this.oldGridParam = gridParam; closeDiv = query('div.close', this.domNode)[0]; html.setStyle(closeDiv, { width: this.nodeWidth * 0.25 + 'px', height: this.nodeWidth * 0.25 + 'px' }); } else { this.oldGridParam = null; html.setStyle(this.domNode, utils.getPositionStyle({ left: 0, top: 0, width: 0, height: 0, zIndex: 111 })); this.nodeWidth = 0; } if (!window.appInfo.isRunInMobile && window.innerWidth > 760 && (this.numWidget && this.numWidget.length <= 8)) { this.hide(); } }, setItemNodePosition: function (node, i, gridParam) { var ml, mt, imgWidth = 48, fontSize = 16, imgNode, labelNode; //margin-left, margin-top if (i % gridParam.cols === 0) { ml = 0; } else { ml = this.margin / 2; } // If the node is in the first row of each page, margin-top is 0, else margin-top is 2 if ((i % (gridParam.rows * gridParam.cols)) < gridParam.cols) { mt = 0; } else { mt = this.margin / 2; } var nodeStyle = {}; if (typeof this.nodeWidth === "number") { nodeStyle.width = this.nodeWidth + 'px'; nodeStyle.height = this.nodeWidth + 'px'; } if (typeof ml === 'number') { if (window.isRTL) { nodeStyle.marginRight = ml + 'px'; } else { nodeStyle.marginLeft = ml + 'px'; } } if (typeof mt === 'number') { nodeStyle.marginTop = mt + 'px'; } imgNode = query('img', node)[0]; if (imgNode) { if (gridParam.iconScaled) { imgWidth = imgWidth * (this.nodeWidth / NORMAL_WIDTH); html.setStyle(imgNode, { width: imgWidth + 'px', height: imgWidth + 'px' }); } else { html.setStyle(imgNode, { width: imgWidth + 'px', height: imgWidth + 'px' }); } } labelNode = query('div.node-label', node)[0]; if (labelNode) { if (gridParam.showLabel) { if (gridParam.iconScaled) { fontSize = fontSize * (this.nodeWidth / NORMAL_WIDTH); html.setStyle(labelNode, { 'font-size': fontSize + 'px', display: 'block' }); } else { html.setStyle(labelNode, { 'font-size': fontSize + 'px', display: 'block' }); } } else { html.setStyle(labelNode, { 'font-size': fontSize + 'px', display: 'none' }); } } html.setStyle(node, nodeStyle); }, clearPages: function () { array.forEach(this.pages, function (page) { this.viewStack.removeView(page.pageNode); }, this); domConstruct.empty(this.pointsNode); this.pages = []; this.nodes = []; }, /** * Create node pages based on the gridParam object. * @param {object} gridParam include rows:number, cols:number, cellSize:number, * iconScaled:boolean, showLabel:boolean, * position:object(left, right, top, bottom, width, height) */ createPages: function (gridParam) { var count, pages, p, pageNode, pointNode; count = this.items.length; pages = Math.ceil(count / (gridParam.rows * gridParam.cols)); this.maximumPages = pages; for (p = 0; p < pages; p++) { pageNode = domConstruct.create('div', { 'class': 'page' }); this.createPageItems(p, pageNode, gridParam); this.viewStack.addView(pageNode); if (pages > 1) { pointNode = domConstruct.create('div', { 'class': 'point' }, this.pointsNode); this.own(on(pointNode, 'click', lang.hitch(this, this._onPageNodeClick, p))); } this.pages.push({ pageNode: pageNode, pointNode: pointNode }); } if (this.viewStack.views.length > 0) { this._selectPage(0); } }, _onPageNodeClick: function (p) { this._selectPage(p); }, _selectPage: function (p) { if (this.pages.length > 1) { query('.point', this.domNode).removeClass('point-selected jimu-main-background'); html.addClass(this.pages[p].pointNode, 'point-selected jimu-main-background'); } this.viewStack.switchView(this.pages[p].pageNode); }, createPageItems: function (page, pageNode, gridParam) { var count, pageSize, i, b, e, empty; count = this.items.length; pageSize = gridParam.rows * gridParam.cols; b = page * pageSize; e = (page + 1) * pageSize; empty = e - count; e = Math.min(e, count); for (i = b; i < e; i++) { this.createItemNode(i, pageNode); } for (i = count; i < count + empty; i++) { this.createEmptyItemNode(pageNode); } }, createItemNode: function (i, pageNode) { var node, item; item = this.items[i]; node = domConstruct.create('div', { 'class': 'icon-node jimu-float-leading jimu-main-background', title: item.label, settingId: item.id }, pageNode); domConstruct.create('img', { 'src': item.icon }, node); domConstruct.create('div', { 'class': 'node-label', 'title': item.label, 'innerHTML': utils.stripHTML(item.label) }, node); node.config = item; this.own(on(node, tap, lang.hitch(this, function () { this.onNodeClicked(node); }))); this.nodes.push(node); }, createEmptyItemNode: function (pageNode) { var node; node = domConstruct.create('div', { 'class': 'icon-node jimu-float-leading jimu-main-background' }, pageNode); this.nodes.push(node); return node; }, createCloseBtn: function () { var node; node = domConstruct.create('div', { 'class': 'close' }, this.domNode); domConstruct.create('div', { 'class': 'close-inner jimu-main-background' }, node); on(node, 'click', lang.hitch(this, function () { this.hide(); })); return node; }, hide: function () { CURRENT_PAGE = 0; html.setStyle(this.domNode, 'display', 'none'); }, show: function () { html.setStyle(this.domNode, 'display', 'block'); }, onNodeClicked: function (node) { /* jshint unused: false*/ this.hide(); }, _calculateGridParam: function () { var mapBox, minLen, position, rows, cols, cellSize, iconScaled = false, showLabel = true; mapBox = html.getContentBox(jimuConfig.mapId); minLen = Math.min(mapBox.w, mapBox.h) - MIN_MARGIN * 2; //calculate node width if (minLen >= NORMAL_WIDTH * MIN_ROWCOL) { cellSize = NORMAL_WIDTH; } else { cellSize = Math.floor(minLen / MIN_ROWCOL); if (cellSize < MIN_NODE_WIDTH) { return null; } iconScaled = true; if (cellSize < NORMAL_MIN_WIDTH) { showLabel = false; } } //calculate rows and columns rows = Math.floor((mapBox.h - MIN_MARGIN * 2) / cellSize); cols = Math.floor((mapBox.w - MIN_MARGIN * 2) / cellSize); rows = rows > MAX_ROWCOL ? MAX_ROWCOL : rows; cols = cols > MAX_ROWCOL ? MAX_ROWCOL : cols; rows = rows < MIN_ROWCOL ? MIN_ROWCOL : rows; cols = rows < MIN_ROWCOL ? MIN_ROWCOL : cols; //calculate position position = { top: (mapBox.h - cellSize * rows) / 2, bottom: (mapBox.h - cellSize * rows) / 2, left: (mapBox.w - cellSize * cols) / 2, right: (mapBox.w - cellSize * cols) / 2, width: cellSize * cols - this.margin * (cols - 1) / 2, height: cellSize * rows - this.margin * (rows - 1) / 2, zIndex: 111 }; return { rows: rows, cols: cols, cellSize: cellSize, iconScaled: iconScaled, showLabel: showLabel, position: position }; } }); });