http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/basic-table/basic-table-component.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/basic-table/basic-table-component.js b/tez-ui/src/main/webapp/app/scripts/components/basic-table/basic-table-component.js deleted file mode 100644 index 2ea9cc5..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/basic-table/basic-table-component.js +++ /dev/null @@ -1,252 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.BasicTableComponent = Em.Component.extend({ - layoutName: 'components/basic-table', - - sortColumnId: '', - sortOrder: '', - - searchText: '', - searchRegEx: null, - searchColumnNames: null, - - statusMessage: null, - - isSorting: false, - isSearching: false, - - pageNum: 1, - rowCount: 10, - rowCountOptions: [5, 10, 25, 50, 100], - pageNavOnFooterAt: 25, - - _sortedRows: null, - - init: function () { - this._super(); - if(this.get('searchText')) { - this._searchObserver(); - } - this._sortObserver(); - }, - - totalPages: function () { - return Math.ceil(this.get('_searchedRows.length') / this.get('rowCount')); - }.property('_searchedRows.length', 'rowCount'), - - hasPageNavOnFooter: function () { - return this.get('enablePagination') && this.get('_rows.length') >= this.get('pageNavOnFooterAt'); - }.property('enablePagination', '_rows.length', 'pageNavOnFooterAt'), - - _showHeader: function () { - return this.get('enableSearch') || - this.get('enablePagination') || - this.get('extraHeaderItem') || - this.get('_statusMessage'); - }.property('enableSearch', 'enablePagination', 'extraHeaderItem', '_statusMessage'), - - _statusMessage: function() { - if(this.get('enableStatus') == false) { - return null; - } - if(this.get('isSorting')) { - return "Sorting..."; - } - else if(this.get('isSearching')) { - return "Searching..."; - } - return this.get('statusMessage'); - }.property('isSearching', 'isSorting', 'statusMessage', 'enableStatus'), - - _pageNumResetObserver: function () { - this.set('pageNum', 1); - }.observes('searchRegEx', 'rowCount'), - - _searchedRows: function () { - var regex = this.get('searchRegEx'), - rows = this.get('_sortedRows') || [], - searchColumnNames, - columns; - - function checkRow(column) { - var value; - if(!column.get('searchAndSortable')) { - return false; - } - value = column.getSearchValue(this); - return (typeof value == 'string') ? value.match(regex) : false; - } - - this.set('isSearching', false); - - if(!regex) { - return rows; - } - else { - searchColumnNames = this.get('searchColumnNames'), - columns = searchColumnNames ? this.get('columns').filter(function (column) { - return searchColumnNames.indexOf(column.get('headerCellName')) != -1; - }) : this.get('columns'); - - return rows.filter(function (row) { - return columns.some(checkRow, row); - }); - } - }.property('columns.@each', '_sortedRows.@each', 'searchRegEx'), - - _columns: function () { - var columns = this.get('columns'), - widthPercentageToFit = 100 / columns.length; - - columns.map(function (column) { - var templateName = column.get('templateName'), - cellOptions = { - column: column - }; - - if(templateName) { - cellOptions.templateName = templateName; - } - - column.setProperties({ - width: widthPercentageToFit + "%", - cellView: App.BasicTableComponent.CellView.extend(cellOptions), - headerCellView: App.BasicTableComponent.HeaderCellView.extend({ - column: column, - table: this - }) - }); - }); - - return columns; - }.property('columns'), - - _rows: function () { - var startIndex = (this.get('pageNum') - 1) * this.get('rowCount'), - rows = this.get('_searchedRows').slice(startIndex, startIndex + this.get('rowCount')); - this.sendAction('rowsChanged', rows); - return rows; - }.property('_searchedRows.@each', 'rowCount', 'pageNum'), - - _searchObserver: function () { - var searchText = this.get('searchText'), - columnNames = [], - delimIndex, - rowsCount, - that = this; - - if(searchText) { - delimIndex = searchText.indexOf(':'); - if(delimIndex != -1) { - columnNames = searchText.substr(0, delimIndex). - split(","). - reduce(function (arr, columnName) { - columnName = columnName.trim(); - if(columnName) { - arr.push(columnName); - } - return arr; - }, []); - searchText = searchText.substr(delimIndex + 1); - } - searchText = searchText.trim(); - } - - rowsCount = this.get('rows.length'); - - if(rowsCount) { - this.set('isSearching', true); - - Ember.run.later(function () { - that.setProperties({ - searchRegEx: searchText ? new RegExp(searchText, 'im') : null, - searchColumnNames: columnNames.length ? columnNames : null - }); - }, 400); - } - }.observes('searchText'), - - _sortObserver: function () { - var rows = this.get('rows'), - column = this.get('columns').findBy('id', this.get('sortColumnId')), - ascending = this.get('sortOrder') == 'asc', - that = this; - - if(rows && rows.get('length') > 0 && column) { - this.set('isSorting', true); - - Ember.run.later(function () { - /* - * Creating sortArray as calling getSortValue form inside the - * sort function would be more costly. - */ - var sortArray = rows.map(function (row) { - return { - value: column.getSortValue(row), - row: row - }; - }); - - sortArray.sort(function (a, b){ - if(ascending ^ (a.value > b.value)) { - return -1; - } - else if(ascending ^ (a.value < b.value)) { - return 1; - } - return 0; - }); - - that.setProperties({ - _sortedRows: sortArray.map(function (record) { - return record.row; - }), - isSorting: false - }); - - }, 400); - } - else { - this.set('_sortedRows', rows); - } - }.observes('sortColumnId', 'sortOrder', 'rows.@each'), - - actions: { - search: function (searchText) { - this.set('searchText', searchText); - }, - sort: function (columnId) { - if(this.get('sortColumnId') != columnId) { - this.setProperties({ - sortColumnId: columnId, - sortOrder: 'asc' - }); - } - else { - this.set('sortOrder', this.get('sortOrder') == 'asc' ? 'desc' : 'asc'); - } - }, - - changePage: function (pageNum) { - this.set('pageNum', pageNum); - } - } -}); - -Em.Handlebars.helper('basic-table-component', App.BasicTableComponent);
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/basic-table/cell-view.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/basic-table/cell-view.js b/tez-ui/src/main/webapp/app/scripts/components/basic-table/cell-view.js deleted file mode 100644 index fa8d1f7..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/basic-table/cell-view.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin); - -function stringifyNumbers(content) { - var displayText = content.displayText; - if(typeof displayText == 'number') { - content.displayText = displayText.toString(); - } - return content; -} - -App.BasicTableComponent.CellView = Ember.View.extend({ - templateName: function () { - var template = this.get('column.observePath') ? 'bounded-basic-cell' : 'basic-cell'; - return 'components/basic-table/' + template; - }.property('column.observePath'), - - classNames: ['cell-content'], - - value: null, - observedPath: null, - - _addObserver: function (path) { - this._removeObserver(); - this.get('row').addObserver(path, this, this._onValueChange); - this.set('observedPath', path); - }, - - _removeObserver: function (path) { - var path = this.get('observedPath'); - if(path) { - this.get('row').removeObserver(path, this, this._onValueChange); - this.set('observedPath', null); - } - }, - - _normalizeContent: function (content) { - return stringifyNumbers(content && typeof content == 'object' ? content : { - displayText: content - }); - }, - - _pathObserver: function () { - var path = this.get('column.contentPath'); - if(path && this.get('column.observePath')) { - this._addObserver(path); - } - }.observes('row', 'column.contentPath', 'column.observePath').on('init'), - - _onValueChange: function (row, path) { - this.set('value', row.get(path)); - }, - - cellContent: function () { - var cellContent = this.get('column').getCellContent(this.get('row')); - - if(cellContent && $.isFunction(cellContent.then)) { - return ObjectPromiseController.create({ - promise: cellContent.then(this._normalizeContent) - }); - } - - return this._normalizeContent(cellContent); - }.property('row', 'column', 'value'), - - willDestroy: function () { - this._removeObserver(); - } -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/basic-table/column-definition.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/basic-table/column-definition.js b/tez-ui/src/main/webapp/app/scripts/components/basic-table/column-definition.js deleted file mode 100644 index 27e6a9f..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/basic-table/column-definition.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.BasicTableComponent.ColumnDefinition = (function () { - function getContentAtPath(row) { - var contentPath = this.get('contentPath'); - - if(contentPath) { - return row.get(contentPath); - } - else { - throw new Error("contentPath not set!"); - } - } - - return Em.Object.extend({ - contentPath: null, - headerCellName: "Not Available!", - searchAndSortable: true, - - onSort: null, - - width: "", - - customStyle: function () { - return 'width:%@'.fmt(this.get('width')); - }.property('width'), - - getSearchValue: getContentAtPath, - getSortValue: getContentAtPath, - getCellContent: getContentAtPath - }); -})(); - http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/basic-table/header-cell-view.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/basic-table/header-cell-view.js b/tez-ui/src/main/webapp/app/scripts/components/basic-table/header-cell-view.js deleted file mode 100644 index 4cfe6e8..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/basic-table/header-cell-view.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.BasicTableComponent.HeaderCellView = Ember.View.extend({ - templateName: 'components/basic-table/header-cell', - - sortIconCSS: function () { - var css = 'sort-icon '; - if(this.get('column.searchAndSortable') == false) { - css = 'no-display'; - } - else if(this.get('parentView.sortColumnId') == this.get('column.id')) { - css += this.get('parentView.sortOrder'); - } - - return css; - }.property('parentView.sortOrder', 'parentView.sortColumnId', 'column.searchAndSortable'), - - _onColResize: function (event) { - var data = event.data; - - if(!data.startEvent) { - data.startEvent = event; - } - - data.thisHeader.set( - 'column.width', - (data.startWidth + event.clientX - data.startEvent.clientX) + 'px' - ); - }, - - _endColResize: function (event) { - var thisHeader = event.data.thisHeader; - $(document).off('mousemove', thisHeader._onColResize); - $(document).off('mouseup', thisHeader._endColResize); - }, - - actions: { - sort: function () { - var column = this.get('column'), - onSort = column.get('onSort'); - - if(!onSort || onSort.call(column, column)) { - this.get('parentView').send('sort', this.get('column.id')); - } - }, - startColResize: function () { - var mouseTracker = { - thisHeader: this, - startWidth: $(this.get('element')).width(), - startEvent: null - }; - $(document).on('mousemove', mouseTracker, this._onColResize); - $(document).on('mouseup', mouseTracker, this._endColResize); - } - } -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/basic-table/pagination-view.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/basic-table/pagination-view.js b/tez-ui/src/main/webapp/app/scripts/components/basic-table/pagination-view.js deleted file mode 100644 index 4f136b1..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/basic-table/pagination-view.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.BasicTableComponent.PaginationView = Ember.View.extend({ - templateName: 'components/basic-table/pagination-view', - - classNames: ['pagination-view'], - - atFirst: function () { - return this.get('pageNum') == 1; - }.property('pageNum'), - - atLast: function () { - return this.get('pageNum') == this.get('totalPages'); - }.property('pageNum', 'totalPages'), - - _possiblePages: function () { - var pageNum = this.get('pageNum'), - totalPages = this.get('totalPages'), - possiblePages = [], - startPage = 1, - endPage = totalPages, - delta = 0; - - if(totalPages > 5) { - startPage = pageNum - 2, endPage = pageNum + 2; - - if(startPage < 1) { - delta = 1 - startPage; - } - else if(endPage > totalPages) { - delta = totalPages - endPage; - } - - startPage += delta, endPage += delta; - } - - while(startPage <= endPage) { - possiblePages.push({ - isCurrent: startPage == pageNum, - pageNum: startPage++ - }); - } - - return possiblePages; - }.property('pageNum', 'totalPages'), -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/basic-table/search-view.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/basic-table/search-view.js b/tez-ui/src/main/webapp/app/scripts/components/basic-table/search-view.js deleted file mode 100644 index 36a2d4f..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/basic-table/search-view.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.BasicTableComponent.SearchView = Ember.View.extend({ - templateName: 'components/basic-table/search-view', - - classNames: ['search-view'], - - text: '', - _boundText: function () { - return this.get('text') || ''; - }.property(), - - _validRegEx: function () { - var regExText = this.get('_boundText'); - regExText = regExText.substr(regExText.indexOf(':') + 1); - try { - new RegExp(regExText, 'im'); - } - catch(e) { - return false; - } - return true; - }.property('_boundText'), - - actions: { - search: function () { - if(this.get('_validRegEx')) { - this.get('parentView').send('search', this.get('_boundText')); - } - } - } -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/bs-progress-animated-component.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/bs-progress-animated-component.js b/tez-ui/src/main/webapp/app/scripts/components/bs-progress-animated-component.js deleted file mode 100644 index 6a260ea..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/bs-progress-animated-component.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to you 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. - */ - -Bootstrap.BsProgressAnimatedComponent = Bootstrap.BsProgressComponent.extend({ - progressDecimal: null, - - init: function () { - this._super.call(this, arguments); - this.progressDecimalObserver(); - this.progressObserver(); - }, - - progressDecimalObserver: function () { - var progress = parseFloat(this.get('progressDecimal')); - progress = (typeof progress == 'number' && !isNaN(progress)) ? progress : 0; - this.set('progress', parseInt(progress * 100).toString()); - }.observes('progressDecimal'), - - progressObserver: function () { - var progressing = this.get('progress') < 100; - this.setProperties({ - stripped: progressing, - animated: progressing - }); - }.observes('progress') -}); - -Ember["TEMPLATES"]["components/bs-progressbar"] = Ember.Handlebars. - template(function anonymous(Handlebars,depth0,helpers,partials,data) { - var buffer = '', escapeExpression=this.escapeExpression; - - this.compilerInfo = [4,'>= 1.0.0']; - helpers = this.merge(helpers, Ember.Handlebars.helpers); - data = data || {}; - - data.buffer.push("<span class=\"sr-only\">"); - data.buffer.push(escapeExpression(helpers._triageMustache.call( - depth0, - "progress", - {hash:{},contexts:[depth0],types:["ID"],hashContexts:{},hashTypes:{},data:data} - ))); - data.buffer.push("%</span>"); - return buffer; -}); - -Ember.Handlebars.helper('bs-progress-animated', Bootstrap.BsProgressAnimatedComponent); http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/code-mirror.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/code-mirror.js b/tez-ui/src/main/webapp/app/scripts/components/code-mirror.js deleted file mode 100644 index 24d8f76..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/code-mirror.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to you 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. - */ - -App.CodeMirrorComponent = Em.Component.extend({ - tagName: 'textarea', - - value: null, - - mode: 'text/x-hive', - theme: 'default', - indentUnit: 2, - smartIndent: true, - tabSize: 4, - electricChars: true, - lineWrapping: true, - lineNumbers: true, - readOnly: true, - autofocus: false, - dragDrop: false, - - _init: Em.on('didInsertElement', function() { - var codeMirror = CodeMirror.fromTextArea(this.get('element')); - - this.set('codeMirror', codeMirror); - - // Set up bindings for CodeMirror options. - this._bindCodeMirrorOption('mode'); - this._bindCodeMirrorOption('theme'); - this._bindCodeMirrorOption('indentUnit'); - this._bindCodeMirrorOption('smartIndent'); - this._bindCodeMirrorOption('tabSize'); - this._bindCodeMirrorOption('electricChars'); - this._bindCodeMirrorOption('lineWrapping'); - this._bindCodeMirrorOption('lineNumbers'); - this._bindCodeMirrorOption('readOnly'); - this._bindCodeMirrorOption('autofocus'); - this._bindCodeMirrorOption('dragDrop'); - - this._bindProperty('value', this, '_valueDidChange'); - this._valueDidChange(); - - this.on('becameVisible', codeMirror, 'refresh'); - }), - - _bindCodeMirrorOption: function(key) { - this._bindProperty(key, this, '_optionDidChange'); - - // Set the initial option synchronously. - this._optionDidChange(this, key); - }, - - _bindProperty: function(key, target, method) { - this.addObserver(key, target, method); - - this.on('willDestroyElement', function() { - this.removeObserver(key, target, method); - }) - }, - - _optionDidChange: function(sender, key) { - this.get('codeMirror').setOption(key, this.get(key)); - }, - - _valueDidChange: function() { - var codeMirror = this.get('codeMirror'), - value = this.get('value') || ''; - - if (this.get('codeMirror').getValue() != value) { - codeMirror.setValue(value); - } - } -}); http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/counter-table.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/counter-table.js b/tez-ui/src/main/webapp/app/scripts/components/counter-table.js deleted file mode 100644 index 260f68d..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/counter-table.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.CounterTableComponent = Em.Component.extend({ - layoutName: 'components/counter-table', - nameFilter: null, - - validFilter: function () { - try { - new RegExp(this.get('nameFilter'), 'i'); - return true; - } - catch(e){} - return false; - }.property('nameFilter'), - - filteredData: function() { - var rawData = this.get('data') || []; - if (Em.isEmpty(this.nameFilter) || !this.get('validFilter')) { - return rawData; - } - - var filtered = [], - filterStringRegex = new RegExp(this.nameFilter, 'i'); - - rawData.forEach(function(cg) { - var tmpcg = { - counterGroupName: cg['counterGroupName'], - counterGroupDisplayName: cg['counterGroupDisplayName'] || cg['counterGroupName'], - counters: [] - }; - - var counters = cg['counters'] || []; - counters.forEach(function(counter) { - if (filterStringRegex.test(counter['counterDisplayName'] || counter['counterName'])) { - tmpcg.counters.push(counter); - } - }); - - // show counter groups only if filter match is not empty. - if (tmpcg.counters.length > 0) { - filtered.push(tmpcg); - } - }) - - return filtered; - }.property('data', 'nameFilter', 'timeStamp') -}); - -Em.Handlebars.helper('counter-table-component', App.CounterTableComponent); http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/dag-view-component.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/dag-view-component.js b/tez-ui/src/main/webapp/app/scripts/components/dag-view-component.js deleted file mode 100644 index 72eb0ed..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/dag-view-component.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -App.DagViewComponent = Em.Component.extend({ - layoutName: 'components/dag-view', - - classNames: ['dag-view-container'], - - errMessage: null, - - isHorizontal: false, - hideAdditionals: false, - isFullscreen: false, - - _onOrientationChange: function () { - }.observes('isHorizontal'), - - _onTglAdditionals: function () { - App.DagViewComponent.graphView.additionalDisplay(this.get('hideAdditionals')); - }.observes('hideAdditionals'), - - _onTglFullScreen: function () { - App.Helpers.fullscreen.toggle(this.get('element')); - }.observes('isFullscreen'), - - actions: { - tglOrientation: function() { - var isTopBottom = App.DagViewComponent.graphView.toggleLayouts(); - this.set('isHorizontal', !isTopBottom); - }, - tglAdditionals: function() { - this.set('hideAdditionals', !this.get('hideAdditionals')); - }, - fullscreen: function () { - this.set('isFullscreen', !this.get('isFullscreen')); - }, - fitGraph: function () { - App.DagViewComponent.graphView.fitGraph(); - }, - configure: function () { - this.sendAction('configure'); - } - }, - - didInsertElement: function () { - var result = App.DagViewComponent.dataProcessor.graphifyData(this.get('data')), - maxBreadth = 0; - - if(typeof result === "string") { - this.set('errMessage', result); - } - else { - App.DagViewComponent.graphView.create( - this, - this.get('element'), - result - ); - } - } - -}); - -Em.Handlebars.helper('dag-view-component', App.DagViewComponent); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/dag-view/data-processor.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/dag-view/data-processor.js b/tez-ui/src/main/webapp/app/scripts/components/dag-view/data-processor.js deleted file mode 100644 index 58a72de..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/dag-view/data-processor.js +++ /dev/null @@ -1,751 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -/** - * The data processing part of Dag View. - * - * Converts raw DAG-plan into an internal data representation as shown below. - * Data processor exposes just a functions and an enum to the outside world, everything else - * happens inside the main closure: - * - types (Enum of node types) - * - graphifyData - * - * Links, Edges: - * -------------- - * d3 layout & graph-view uses the term links, and dag-plan uses edges. Hence you would - * see both getting used in this file. - * - * Graphify Data - * ------------- - * graphifyData function is a translator that translates the dagPlan object send by timeline server - * into another object that graph-view and in turn d3.layout.tree can digest. - * - * Input object(dag-plan as it is from the timeline server): - * { - * dagName, version, - * vertices: [ // Array of vertex objects with following properties - * { - * vertexName, processorClass, outEdgeIds {Array}, additionalInputs {Array} - * } - * ], - * edges: [ // Array of edge objects with following properties - * { - * edgeId, inputVertexName, outputVertexName, dataMovementType, dataSourceType - * schedulingType, edgeSourceClass, edgeDestinationClass - * } - * ], - * vertexGroups: [ // Array of vectorGroups objects with following properties - * { - * groupName, groupMembers {Array}, edgeMergedInputs {Array} - * } - * ] - * } - * - * Output object: - * We are having a graph that must be displayed like a tree. Hence data processor was created - * to make a tree structure out of the available data. The tree structure is made by creating - * DataNodes instances and populating their children array with respective child DataNodes - * - tree: Represents the tree structure with each node being a DataNodes instance - * - links: Represents the connections between the nodes to create the graph - * { - * tree: { // This object points to the RootDataNode instance - * children {Array} // Array of DataNodes under the node, as expected by d3.layout.tree - * + Other custom properties including data that needs to be displayed - * } - * links: [ // An array of all links in the tree - * { - * sourceId // Source vertex name - * targetId // Target vertex name - * + Other custom properties including data to be displayed - * } - * ] - * maxDepth, leafCount - * } - * - * Data Nodes: - * ----------- - * To make the implementation simpler each node in the graph will be represented as an - * instance of any of the 4 inherited classes of Data Node abstract class. - * DataNode - * |-- RootDataNode - * |-- VertexDataNode - * |-- InputDataNode - * +-- OutputDataNode - * - * Extra Nodes: - * ------------ - * Root Node (Invisible): - * Dag view support very complex DAGs, even those without interconnections and backward links. - * Hence to fit it into a tree layout I have inserted an invisible root node. - * - * Dummy Node (Invisible): - * Sinks of a vertex are added at the same level of its parent node, Hence to ensure that all - * nodes come under the root, a dummy node was added as the child of the root. The visible tree - * would be added as child of dummy node. - * Dummy also ensures the view symmetry when multiple outputs are present at the dummy level. - * - * Sample Structure, inverted tree representation: - * - * As in the view - * - * Source_m1 - * | - * Source_m2 M1----------+ - * | | | - * +-----------M2 Sink_M1 - * | - * +-----------R1----------+ - * | | - * Sink1_R1 Sink2_R1 - * - * - * Internal representation - * - * Source_m1 - * | - * Source_m2 M1 - * | | - * +-----------M2 Sink_M1 - * | | - * R1----------+ - * | - * Sink1_R1 Dummy Sink2_R1 - * | | | - * +-----------+-----------+ - * | - * Root - * - * Internal data representation - * - * Root - * | - * +-- children[Sink1_R1, Dummy, Sink2_R1] - * | - * +-- children[R1] - * | - * +-- children[M2, Sink_M1] - * | - * +-- children[Source_m2, M1] - * | - * +-- children[Source_m1] - * - * Steps: - * ------ - * The job is done in 4 steps, and is modularized using 4 separate recursive functions. - * 1. _treefyData : Get the tree structure in place with vertices and inputs/sources - * 2. _addOutputs : Add outputs/sinks. A separate step had to be created as outputs - * are represented in the opposite direction of inputs. - * 3. _cacheChildren : Make a cache of children in allChildren property for later use - * 4. _getGraphDetails : Get a graph object with all the required details - * - */ -App.DagViewComponent.dataProcessor = (function (){ - /** - * Enum of various node types - */ - var types = { - ROOT: 'root', - DUMMY: 'dummy', - VERTEX: 'vertex', - INPUT: 'input', - OUTPUT: 'output' - }; - - /** - * Iterates the array in a symmetric order, from middle to outwards - * @param array {Array} Array to be iterated - * @param callback {Function} Function to be called for each item - * @return A new array created with value returned by callback - */ - function centericMap(array, callback) { - var retArray = [], - length, - left, right; - - if(array) { - length = array.length - 1, - left = length >> 1; - - while(left >= 0) { - retArray[left] = callback(array[left]); - right = length - left; - if(right != left) { - retArray[right] = callback(array[right]); - } - left--; - } - } - return retArray; - } - - /** - * Abstract class for all types of data nodes - */ - var DataNode = Em.Object.extend({ - init: function (data) { - this._super(data); - this._init(data); - }, - _init: function () { - // Initialize data members - this.setProperties({ - /** - * Children that would be displayed in the view, to hide a child it would be removed from this array. - * Not making this a computed property because - No d3 support, low performance. - */ - children: null, - allChildren: null, // All children under this node - treeParent: null, // Direct parent DataNode in our tree structure - }); - }, - - /** - * Private function. - * Set the child array as it is. Created because of performance reasons. - * @param children {Array} Array to be set - */ - _setChildren: function (children) { - this.set('children', children && children.length > 0 ? children : null); - }, - /** - * Public function. - * Set the child array after filtering - * @param children {Array} Array of DataNodes to be set - */ - setChildren: function (children) { - var allChildren = this.get('allChildren'); - if(allChildren) { - this._setChildren(allChildren.filter(function (child) { - return children.indexOf(child) != -1; // true if child is in children - })); - } - }, - /** - * Filter out the given children from the children array. - * @param childrenToRemove {Array} Array of DataNodes to be removed - */ - removeChildren: function (childrenToRemove) { - var children = this.get('children'); - if(children) { - children = children.filter(function (child) { - return childrenToRemove.indexOf(child) == -1; // false if child is in children - }); - this._setChildren(children); - } - }, - - /** - * Return true if this DataNode is same as or the ancestor of vertex - * @param vertex {DataNode} - */ - isSelfOrAncestor: function (vertex) { - while(vertex) { - if(vertex === this) return true; - vertex = vertex.treeParent; - } - return false; - }, - - /** - * If the property is available, expects it to be an array and iterate over - * its elements using the callback. - * @param vertex {DataNode} - * @param callback {Function} - * @param thisArg {} Will be value of this inside the callback - */ - ifForEach: function (property, callback, thisArg) { - if(this.get(property)) { - this.get(property).forEach(callback, thisArg); - } - }, - /** - * Recursively call the function specified in all children - * its elements using the callback. - * @param functionName {String} Name of the function to be called - */ - recursivelyCall: function (functionName) { - if(this[functionName]) { - this[functionName](); - } - this.ifForEach('children', function (child) { - child.recursivelyCall(functionName); - }); - } - }), - RootDataNode = DataNode.extend({ - type: types.ROOT, - vertexName: 'root', - dummy: null, // Dummy node used in the tree, check top comments for explanation - depth: 0, // Depth of the node in the tree structure - - _init: function () { - this._setChildren([this.get('dummy')]); - } - }), - VertexDataNode = DataNode.extend({ - type: types.VERTEX, - - _additionalsIncluded: true, - - _init: function () { - this._super(); - - // Initialize data members - this.setProperties({ - id: this.get('vertexName'), - inputs: [], // Array of sources - outputs: [] // Array of sinks - }); - - this.ifForEach('additionalInputs', function (input) { - this.inputs.push(InputDataNode.instantiate(this, input)); - }, this); - - this.ifForEach('additionalOutputs', function (output) { - this.outputs.push(OutputDataNode.instantiate(this, output)); - }, this); - }, - - /** - * Sets depth of the vertex and all its input children - * @param depth {Number} - */ - setDepth: function (depth) { - this.set('depth', depth); - - depth++; - this.get('inputs').forEach(function (input) { - input.set('depth', depth); - }); - }, - - /** - * Sets vertex tree parents - * @param parent {DataNode} - */ - setParent: function (parent) { - this.set('treeParent', parent); - }, - - /** - * Include sources and sinks in the children list, so that they are displayed - */ - includeAdditionals: function() { - this.setChildren(this.get('inputs').concat(this.get('children') || [])); - - var ancestor = this.get('parent.parent'); - if(ancestor) { - ancestor.setChildren(this.get('outputs').concat(ancestor.get('children') || [])); - } - this.set('_additionalsIncluded', true); - }, - /** - * Exclude sources and sinks in the children list, so that they are hidden - */ - excludeAdditionals: function() { - this.removeChildren(this.get('inputs')); - - var ancestor = this.get('parent.parent'); - if(ancestor) { - ancestor.removeChildren(this.get('outputs')); - } - this.set('_additionalsIncluded', false); - }, - /** - * Toggle inclusion/display of sources and sinks. - */ - toggleAdditionalInclusion: function () { - var include = !this.get('_additionalsIncluded'); - this.set('_additionalsIncluded', include); - - if(include) { - this.includeAdditionals(); - } - else { - this.excludeAdditionals(); - } - } - }), - InputDataNode = $.extend(DataNode.extend({ - type: types.INPUT, - vertex: null, // The vertex DataNode to which this node is linked - - _init: function () { - var vertex = this.get('vertex'); - this._super(); - - // Initialize data members - this.setProperties({ - id: vertex.get('vertexName') + this.get('name'), - depth: vertex.get('depth') + 1 - }); - } - }), { - /** - * Initiate an InputDataNode - * @param vertex {DataNode} - * @param data {Object} - */ - instantiate: function (vertex, data) { - return InputDataNode.create($.extend(data, { - treeParent: vertex, - vertex: vertex - })); - } - }), - OutputDataNode = $.extend(DataNode.extend({ - type: types.OUTPUT, - vertex: null, // The vertex DataNode to which this node is linked - - _init: function (data) { - this._super(); - - // Initialize data members - this.setProperties({ - id: this.get('vertex.vertexName') + this.get('name') - }); - } - }), { - /** - * Initiate an OutputDataNode - * @param vertex {DataNode} - * @param data {Object} - */ - instantiate: function (vertex, data) { - /** - * We will have an idea about the treeParent & depth only after creating the - * tree structure. - */ - return OutputDataNode.create($.extend(data, { - vertex: vertex - })); - } - }); - - var _data = null; // Raw dag plan data - - /** - * Step 1: Recursive - * Creates primary skeletal structure with vertices and inputs as nodes, - * All child vertices & inputs will be added to an array property named children - * As we are trying to treefy graph data, nodes might reoccur. Reject if its in - * the ancestral chain, and if the new depth is lower (Higher value) than the old - * reposition the node. - * - * @param vertex {VertexDataNode} Root vertex of current sub tree - * @param depth {Number} Depth of the passed vertex - * @param vertex {VertexDataNode} - */ - function _treefyData(vertex, depth) { - var children, - parentChildren; - - depth++; - - children = centericMap(vertex.get('inEdgeIds'), function (edgeId) { - var child = _data.vertices.get(_data.edges.get(edgeId).get('inputVertexName')); - if(!child.isSelfOrAncestor(vertex)) { - if(child.depth) { - if(child.depth < depth) { - parentChildren = child.get('treeParent.children'); - if(parentChildren) { - parentChildren.removeObject(child); - } - } - else { - return; - } - } - child.setParent(vertex); - return _treefyData(child, depth); - } - }); - - // Remove undefined entries - children = children.filter(function (child) { - return child; - }); - - vertex.setDepth(depth); - - // Adds a dummy child to intermediate inputs so that they - // gets equal relevance as adjacent nodes on plotting the tree! - if(children.length) { - vertex.ifForEach('inputs', function (input) { - input._setChildren([DataNode.create()]); - }); - } - - children.push.apply(children, vertex.get('inputs')); - - vertex._setChildren(children); - return vertex; - } - - /** - * Part of step 1 - * To remove recurring vertices in the tree - * @param vertex {Object} root vertex - */ - function _normalizeVertexTree(vertex) { - var children = vertex.get('children'); - - if(children) { - children = children.filter(function (child) { - _normalizeVertexTree(child); - return child.get('type') != 'vertex' || child.get('treeParent') == vertex; - }); - - vertex._setChildren(children); - } - - return vertex; - } - - /** - * Step 2: Recursive awesomeness - * Attaches outputs into the primary structure created in step 1. As outputs must be represented - * in the same level of the vertex's parent. They are added as children of its parent's parent. - * - * The algorithm is designed to get a symmetric display of output nodes. - * A call to the function will iterate through all its children, and inserts output nodes at the - * position that best fits the expected symmetry. - * - * @param vertex {VertexDataNode} - * @return {Object} Nodes that would come to the left and right of the vertex. - */ - function _addOutputs(vertex) { - var childVertices = vertex.get('children'), - childrenWithOutputs = [], - - midIndex, - tree, - - left = [], - right = []; - - // For a symmetric display of output nodes - if(childVertices && childVertices.length) { - midIndex = Math.floor(childVertices.length / 2); - if(childVertices.length % 2 == 0) { - midIndex--; - } - - childVertices.forEach(function (child, index) { - var additionals = _addOutputs(child), - outputs, - mid; - - childrenWithOutputs.push.apply(childrenWithOutputs, additionals.left); - childrenWithOutputs.push(child); - childrenWithOutputs.push.apply(childrenWithOutputs, additionals.right); - - outputs = child.get('outputs'); - if(outputs && outputs.length) { - mid = outputs.length / 2; - - outputs.forEach(function (output) { - output.depth = vertex.depth; - }); - - if(index < midIndex) { - left.push.apply(left, outputs); - } - else if(index > midIndex) { - right.push.apply(right, outputs); - } - else { - left.push.apply(left, outputs.slice(mid)); - right.push.apply(right, outputs.slice(0, mid)); - } - } - }); - - vertex._setChildren(childrenWithOutputs); - } - - return { - left: left, - right: right - }; - } - - /** - * Step 3: Recursive - * Create a copy of all possible children in allChildren for later use - * @param node {DataNode} - */ - function _cacheChildren(node) { - var children = node.get('children'); - if(children) { - node.set('allChildren', children); - children.forEach(_cacheChildren); - } - } - - /** - * Return an array of the incoming edges/links and input-output source-sink edges of the node. - * @param node {DataNode} - * @return links {Array} Array of all incoming and input-output edges of the node - */ - function _getLinks(node) { - var links = []; - - node.ifForEach('inEdgeIds', function (inEdge) { - var edge = _data.edges.get(inEdge); - edge.setProperties({ - sourceId: edge.get('inputVertexName'), - targetId: edge.get('outputVertexName') - }); - links.push(edge); - }); - - if(node.type == types.INPUT) { - links.push(Em.Object.create({ - sourceId: node.get('id'), - targetId: node.get('vertex.id') - })); - } - else if(node.type == types.OUTPUT) { - links.push(Em.Object.create({ - sourceId: node.get('vertex.id'), - targetId: node.get('id') - })); - } - - return links; - } - - /** - * Step 4: Recursive - * Create a graph based on the given tree structure and edges in _data object. - * @param tree {DataNode} - * @param details {Object} Object with values tree, links, maxDepth & maxHeight - */ - function _getGraphDetails(tree) { - var maxDepth = 0, - leafCount = 0, - - links = _getLinks(tree); - - tree.ifForEach('children', function (child) { - var details = _getGraphDetails(child); - maxDepth = Math.max(maxDepth, details.maxDepth); - leafCount += details.leafCount; - - links.push.apply(links, details.links); - }); - - if(!tree.get('children')) { - leafCount++; - } - - return { - tree: tree, - links: links, - maxDepth: maxDepth + 1, - leafCount: leafCount - }; - } - - /** - * Converts vertices & edges into hashes for easy access. - * Makes vertexGroup a property of the respective vertices. - * @param data {Object} - * @return {Object} An object with vertices hash, edges hash and array of root vertices. - */ - function _normalizeRawData(data) { - var EmObj = Em.Object, - vertices, // Hash of vertices - edges, // Hash of edges - rootVertices = []; // Vertices without out-edges are considered root vertices - - vertices = data.vertices.reduce(function (obj, vertex) { - vertex = VertexDataNode.create(vertex); - if(!vertex.outEdgeIds) { - rootVertices.push(vertex); - } - obj[vertex.vertexName] = vertex; - return obj; - }, {}); - - edges = !data.edges ? [] : data.edges.reduce(function (obj, edge) { - obj[edge.edgeId] = EmObj.create(edge); - return obj; - }, {}); - - if(data.vertexGroups) { - data.vertexGroups.forEach(function (group) { - group.groupMembers.forEach(function (vertex) { - vertices[vertex].vertexGroup = EmObj.create(group); - }); - }); - } - - return { - vertices: EmObj.create(vertices), - edges: EmObj.create(edges), - rootVertices: rootVertices - }; - } - - return { - // Types enum - types: types, - - /** - * Converts raw DAG-plan into an internal data representation that graph-view, - * and in turn d3.layout.tree can digest. - * @param data {Object} Dag-plan data - * @return {Object/String} - * - Object with values tree, links, maxDepth & maxHeight - * - Error message if the data was not as expected. - */ - graphifyData: function (data) { - var dummy = DataNode.create({ - type: types.DUMMY, - vertexName: 'dummy', - depth: 1 - }), - root = RootDataNode.create({ - dummy: dummy - }); - - if(!data.vertices) { - return "Vertices not found!"; - } - - _data = _normalizeRawData(data); - - if(!_data.rootVertices.length) { - return "Sink vertex not found!"; - } - - dummy._setChildren(centericMap(_data.rootVertices, function (vertex) { - return _normalizeVertexTree(_treefyData(vertex, 2)); - })); - - _addOutputs(root); - - _cacheChildren(root); - - return _getGraphDetails(root); - } - }; - -})(); http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/scripts/components/dag-view/graph-view.js ---------------------------------------------------------------------- diff --git a/tez-ui/src/main/webapp/app/scripts/components/dag-view/graph-view.js b/tez-ui/src/main/webapp/app/scripts/components/dag-view/graph-view.js deleted file mode 100644 index 1210bd4..0000000 --- a/tez-ui/src/main/webapp/app/scripts/components/dag-view/graph-view.js +++ /dev/null @@ -1,993 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -/** - * The view part of Dag View. - * - * Displays TEZ DAG graph in a tree layout. (Uses d3.layout.tree) - * Graph view exposes just 4 functions to the outside world, everything else - * happens inside the main closure: - * 1. create - * 2. fitGraph - * 3. additionalDisplay - * 4. toggleLayouts - * - * Links, Paths: - * -------------- - * d3 layout uses the term links, and SVG uses path. Hence you would see both getting used - * in this file. You can consider link to be a JavaScript data object, and path to be a visible - * SVG DOM element on the screen. - * - * Extra Nodes: - * ------------ - * Root Node (Invisible): - * Dag view support very complex DAGs, even DAGs without interconnections and backward links. - * Hence to fit it into a tree layout I have inserted an invisible root node. - * - * Dummy Node (Invisible): - * Sinks of a vertex are added at the same level of its parent node, Hence to ensure that all - * nodes come under the root, a dummy node was added as the child of the root. The visible tree - * would be added as child of dummy node. - * Dummy also ensures the view symmetry when multiple outputs are present at the dummy level. - * - * Sample Structure, inverted tree representation: - * - * As in the view - * - * Source_m1 - * | - * Source_m2 M1----------+ - * | | | - * +-----------M2 Sink_M1 - * | - * +-----------R1----------+ - * | | - * Sink1_R1 Sink2_R1 - * - * - * Internal representation - * - * Source_m1 - * | - * Source_m2 M1 - * | | - * +-----------M2 Sink_M1 - * | | - * R1----------+ - * | - * Sink1_R1 Dummy Sink2_R1 - * | | | - * +-----------+-----------+ - * | - * Root - * - */ -App.DagViewComponent.graphView = (function (){ - - var PADDING = 30, // Adding to be applied on the svg view - - LAYOUTS = { // The view supports two layouts - left to right and top to bottom. - leftToRight: { - hSpacing: 180, // Horizontal spacing between nodes - vSpacing: 70, // Vertical spacing between nodes - depthSpacing: 180, // In leftToRight depthSpacing = hSpacing - linkDelta: 30, // Used for links starting and ending at the same point - projector: function (x, y) { // Converts coordinate based on current orientation - return {x: y, y: x}; - }, - // Defines how path between nodes are drawn - pathDataFormat: "M %@ %@ Q %@ %@ %@ %@ Q %@ %@ %@ %@" - }, - topToBottom: { - hSpacing: 120, - vSpacing: 100, - depthSpacing: 100, // In topToBottom depthSpacing = vSpacing - linkDelta: 15, - projector: function (x, y) { - return {x: x, y: y}; - }, - pathDataFormat: "M %@2 %@1 Q %@4 %@3 %@6 %@5 Q %@8 %@7 %@10 %@9" - } - }, - - DURATION = 750, // Animation duration - - HREF_TYPE_HASH = { // Used to assess the entity type from an event target - "#task-bubble": "task", - "#vertex-bg": "vertex", - "#input-bg": "input", - "#output-bg": "output", - "#io-bubble": "io", - "#group-bubble": "group" - }; - - var _width = 0, - _height = 0, - - _component = null, // The parent ember component - _data = null, // Data object created by data processor - _treeData = null, // Points to root data node of the tree structure - _treeLayout = null, // Instance of d3 tree layout helper - _layout = null, // Current layout, one of the values defined in LAYOUTS object - - _svg = null, // jQuery instance of svg DOM element - _g = null, // For pan and zoom: Svg DOM group element that encloses all the displayed items - - _idCounter = 0, // To create a fresh id for all displayed nodes - _scheduledClickId = 0, // Id of scheduled click, used for double click. - - _tip, // Instance of tip.js - - _panZoomValues, // Temporary storage of pan zoom values for fit toggle - _panZoom; // A closure returned by _attachPanZoom to reset/modify pan and zoom values - - function _getName(d) { - switch(d.get('type')) { - case 'vertex': - return d.get('vertexName'); - break; - default: - return d.get('name'); - } - } - function _getSub(d) { - switch(d.get('type')) { - case 'vertex': - return d.get('data.status'); - break; - default: - return d.get('class'); - } - } - /** - * Texts grater than maxLength will be trimmed. - * @param text {String} Text to trim - * @param maxLength {Number} - * @return Trimmed text - */ - function _trimText(text, maxLength) { - if(text) { - text = text.toString(); - if(text.length > maxLength) { - text = text.substr(0, maxLength - 1) + '..'; - } - } - return text; - } - - /** - * IE 11 does not support css transforms on svg elements. So manually set the same. - * please keep the transform parameters in sync with the ones in dag-view.less - * See https://connect.microsoft.com/IE/feedbackdetail/view/920928 - * - * This can be removed once the bug is fixed in all supported IE versions - * @param value - */ - function translateIfIE(element, x, y) { - if(App.env.isIE) { - element.attr('transform', 'translate(%@, %@)'.fmt(x, y)); - } - } - - /** - * Add task bubble to a vertex node - * @param node {SVG DOM element} Vertex node - * @param d {VertexDataNode} - */ - function _addTaskBubble(node, d) { - var group = node.append('g'); - group.attr('class', 'task-bubble'); - group.append('use').attr('xlink:href', '#task-bubble'); - translateIfIE(group.append('text') - .text(_trimText(d.get('data.numTasks'), 3)), 0, 4); - - translateIfIE(group, 38, -15); - } - /** - * Add IO(source/sink) bubble to a vertex node - * @param node {SVG DOM element} Vertex node - * @param d {VertexDataNode} - */ - function _addIOBubble(node, d) { - var group, - inputs = d.get('inputs.length'), - outputs = d.get('outputs.length'); - - if(inputs || outputs) { - group = node.append('g'); - group.attr('class', 'io-bubble'); - group.append('use').attr('xlink:href', '#io-bubble'); - translateIfIE(group.append('text') - .text(_trimText('%@/%@'.fmt(inputs, outputs), 3)), 0, 4); - - translateIfIE(group, -38, -15); - } - } - /** - * Add vertex group bubble to a vertex node - * @param node {SVG DOM element} Vertex node - * @param d {VertexDataNode} - */ - function _addVertexGroupBubble(node, d) { - var group; - - if(d.vertexGroup) { - group = node.append('g'); - group.attr('class', 'group-bubble'); - group.append('use').attr('xlink:href', '#group-bubble'); - translateIfIE(group.append('text') - .text(_trimText(d.get('vertexGroup.groupMembers.length'), 2)), 0, 4); - - translateIfIE(group, 38, 15); - } - } - /** - * Add status bar to a vertex node - * @param node {SVG DOM element} Vertex node - * @param d {VertexDataNode} - */ - function _addStatusBar(node, d) { - var group = node.append('g'), - statusIcon = App.Helpers.misc.getStatusClassForEntity(d.get('data.status'), - d.get('data.hasFailedTaskAttempts')); - group.attr('class', 'status-bar'); - - group.append('foreignObject') - .attr("class", "status") - .attr("width", 70) - .attr("height", 15) - .html('<span class="msg-container"><i class="task-status ' + - statusIcon + - '"></i> ' + - d.get('data.status') + - '</span>' - ); - } - /** - * Creates a base SVG DOM node, with bg and title based on the type of DataNode - * @param node {SVG DOM element} Vertex node - * @param d {DataNode} - * @param titleProperty {String} d's property who's value is the title to be displayed. - * By default 'name'. - * @param maxTitleLength {Number} Title would be trimmed beyond maxTitleLength. By default 3 chars - */ - function _addBasicContents(node, d, titleProperty, maxTitleLength) { - var className = d.type; - - node.attr('class', 'node %@'.fmt(className)); - node.append('use').attr('xlink:href', '#%@-bg'.fmt(className)); - translateIfIE(node.append('text') - .attr('class', 'title') - .text(_trimText(d.get(titleProperty || 'name'), maxTitleLength || 12)), 0, 4); - } - /** - * Populates the calling node with the required content. - * @param s {DataNode} - */ - function _addContent(d) { - var node = d3.select(this); - - switch(d.type) { - case 'vertex': - _addBasicContents(node, d, 'vertexName'); - _addStatusBar(node, d); - _addTaskBubble(node, d); - _addIOBubble(node, d); - _addVertexGroupBubble(node, d); - break; - case 'input': - case 'output': - _addBasicContents(node, d); - break; - } - } - - /** - * Create a list of all links connecting nodes in the given array. - * @param nodes {Array} A list of d3 nodes created by tree layout - * @return links {Array} All links between nodes in the current DAG - */ - function _getLinks(nodes) { - var links = [], - nodeHash; - - nodeHash = nodes.reduce(function (obj, node) { - obj[node.id] = node; - return obj; - }, {}); - - _data.links.forEach(function (link) { - var source = nodeHash[link.sourceId], - target = nodeHash[link.targetId]; - if(source && target) { - link.setProperties({ - source: source, - target: target, - isBackwardLink: source.isSelfOrAncestor(target) - }); - links.push(link); - } - }); - - return links; - } - - /** - * Apply proper depth spacing and remove the space occupied by dummy node - * if the number of other nodes are odd. - * @param nodes {Array} A list of d3 nodes created by tree layout - */ - function _normalize(nodes) { - // Set layout - var farthestY = 0; - nodes.forEach(function (d) { - d.y = d.depth * -_layout.depthSpacing; - if(d.y < farthestY) farthestY = d.y; - }); - farthestY -= PADDING; - nodes.forEach(function (d) { - d.y -= farthestY; - }); - - //Remove space occupied by dummy - var rootChildren = _treeData.get('children'), - rootChildCount = rootChildren.length, - dummyIndex; - - if(rootChildCount % 2 == 0) { - dummyIndex = rootChildren.indexOf(_treeData.get('dummy')); - if(dummyIndex >= rootChildCount / 2) { - for(var i = 0; i < dummyIndex; i++) { - rootChildren[i].x = rootChildren[i + 1].x, - rootChildren[i].y = rootChildren[i + 1].y; - } - } - else { - for(var i = rootChildCount - 1; i > dummyIndex; i--) { - rootChildren[i].x = rootChildren[i - 1].x, - rootChildren[i].y = rootChildren[i - 1].y; - } - } - } - - // Put all single vertex outputs in-line with the vertex node - // So that they are directly below the respective vertex in vertical layout - nodes.forEach(function (node) { - if(node.type == App.DagViewComponent.dataProcessor.types.OUTPUT && - node.get('vertex.outputs.length') == 1 && - node.get('treeParent.x') != node.get('x') - ) { - node.x = node.get('vertex.x'); - } - }); - } - - function _getType(node) { - if(node.tagName == 'path') { - return 'path'; - } - return HREF_TYPE_HASH[$(node).attr('href')]; - } - - /** - * Mouse over handler for all displayed SVG DOM elements. - * Later the implementation will be refactored and moved into the respective DataNode. - * d {DataNode} Contains data to be displayed - */ - function _onMouseOver(d) { - var event = d3.event, - node = event.target, - tooltipData = {}; // Will be populated with {title/text/kvList}. - - node = node.correspondingUseElement || node; - - switch(_getType(node)) { - case "vertex": - var list = {}; - - _component.get('vertexProperties').forEach(function (property) { - var value = {}; - - if(property.getCellContent && !property.tableCellViewClass) { - value = property.getCellContent(d.get('data')); - if(value && value.displayText != undefined) { - value = value.displayText; - } - } - else if(property.contentPath) { - value = d.get('data.' + property.contentPath); - } - - value = App.Helpers.number.formatNumThousands(value); - - if(typeof value != 'object') { - list[property.get('headerCellName')] = value; - } - }); - - tooltipData = { - title: d.get("vertexName"), - kvList: list - }; - break; - case "input": - var list = { - "Class": App.Helpers.misc.getClassName(d.get("class")), - "Initializer": App.Helpers.misc.getClassName(d.get("initializer")), - "Configurations": App.Helpers.number.formatNumThousands(d.get("configs.length")) - }; - tooltipData = { - title: d.get("name"), - kvList: list - }; - break; - case "output": - var list = { - "Class": App.Helpers.misc.getClassName(d.get("class")), - "Configurations": App.Helpers.number.formatNumThousands(d.get("configs.length")) - }; - tooltipData = { - title: d.get("name"), - kvList: list - }; - break; - case "task": - var numTasks = d.get('data.numTasks'); - tooltipData.title = (numTasks > 1 ? '%@ Tasks' : '%@ Task').fmt(numTasks); - - if(!App.env.isIE) { - node = d3.event.target; - } - break; - case "io": - var inputs = d.get('inputs.length'), - outputs = d.get('outputs.length'), - title = ""; - title += (inputs > 1 ? '%@ Sources' : '%@ Source').fmt(inputs); - title += " & "; - title += (outputs > 1 ? '%@ Sinks' : '%@ Sink').fmt(outputs); - tooltipData.title = title; - - if(!App.env.isIE) { - node = d3.event.target; - } - break; - case "group": - tooltipData = { - title: d.get("vertexGroup.groupName"), - text: d.get("vertexGroup.groupMembers").join(", ") - }; - break; - case "path": - tooltipData = { - position: { - x: event.clientX, - y: event.clientY - }, - title: '%@ - %@'.fmt( - d.get('source.name') || d.get('source.vertexName'), - d.get('target.name') || d.get('target.vertexName') - ) - }; - if(d.get("edgeId")) { - tooltipData.kvList = { - "Edge Id": d.get("edgeId"), - "Data Movement Type": d.get("dataMovementType"), - "Data Source Type": d.get("dataSourceType"), - "Scheduling Type": d.get("schedulingType"), - "Edge Source Class": App.Helpers.misc.getClassName(d.get("edgeSourceClass")), - "Edge Destination Class": App.Helpers.misc.getClassName(d.get("edgeDestinationClass")) - }; - } - else { - tooltipData.text = d.get('source.type') == "input" ? "Source link" : "Sink link"; - } - break; - } - - _tip.show(node, tooltipData, event); - } - - /** - * onclick handler scheduled using setTimeout - * @params d {DataNode} data of the clicked element - * @param node {D3 element} Element that was clicked - */ - function _scheduledClick(d, node) { - node = node.correspondingUseElement || node; - - _component.sendAction('entityClicked', { - type: _getType(node), - d: d - }); - - _tip.hide(); - _scheduledClickId = 0; - } - - /** - * Schedules an onclick handler. If double click event is not triggered the handler - * will be called in 200ms. - * @param d {DataNode} Data of the clicked element - */ - function _onClick(d) { - if(!_scheduledClickId) { - _scheduledClickId = setTimeout(_scheduledClick.bind(this, d, d3.event.target), 200); - } - } - - /** - * Callback for mousedown & mousemove interactions. To disable click on drag - * @param d {DataNode} Data of the clicked element - */ - function _onMouse(d) { - d3.select(this).on('click', d3.event.type == 'mousedown' ? _onClick : null); - } - - /** - * Double click event handler. - * @param d {DataNode} Data of the clicked element - */ - function _onDblclick(d) { - var event = d3.event, - node = event.target, - dataProcessor = App.DagViewComponent.dataProcessor; - - node = node.correspondingUseElement || node; - - if(_scheduledClickId) { - clearTimeout(_scheduledClickId); - _scheduledClickId = 0; - } - - switch(_getType(node)) { - case "io": - d.toggleAdditionalInclusion(); - _update(); - break; - } - } - - /** - * Creates a path data string for the given link. Google SVG path data to learn what it is. - * @param d {Object} Must contain source and target properties with the start and end positions. - * @return pathData {String} Path data string based on the current layout - */ - function _createPathData(d) { - var sX = d.source.y, - sY = d.source.x, - tX = d.target.y, - tY = d.target.x, - mX = (sX + tX)/2, - mY = (sY + tY)/2, - - sH = Math.abs(sX - tX) * 0.35, - sV = 0; // strength - - if(d.isBackwardLink) { - if(sY == tY) { - sV = 45, - mY -= 50; - if(sX == tX) { - sX += _layout.linkDelta, - tX -= _layout.linkDelta; - } - } - sH = Math.abs(sX - tX) * 1.1; - } - - return "".fmt.apply(_layout.pathDataFormat, [ - sX, sY, - - sX + sH, sY - sV, - mX, mY, - - tX - sH, tY - sV, - tX, tY - ]); - } - - /** - * Get the node from/to which the node must transition on enter/exit - * @param d {DataNode} - * @param property {String} Property to be checked for - * @return vertex node - */ - function _getVertexNode(d, property) { - if(d.get('vertex.' + property)) { - return d.get('vertex'); - } - } - /** - * Update position of all nodes in the list and preform required transitions. - * @param nodes {Array} Nodes to be updated - * @param source {d3 element} Node that trigged the update, in first update source will be root. - */ - function _updateNodes(nodes, source) { - // Enter any new nodes at the parent's previous position. - nodes.enter().append('g') - .attr('transform', function(d) { - var node = _getVertexNode(d, "x0") || source; - node = _layout.projector(node.x0, node.y0); - return 'translate(' + node.x + ',' + node.y + ')'; - }) - .on({ - mouseover: _onMouseOver, - mouseout: _tip.hide, - mousedown: _onMouse, - mousemove: _onMouse, - dblclick: _onDblclick - }) - .style('opacity', 1e-6) - .each(_addContent); - - // Transition nodes to their new position. - nodes.transition() - .duration(DURATION) - .attr('transform', function(d) { - d = _layout.projector(d.x, d.y); - return 'translate(' + d.x + ',' + d.y + ')'; - }) - .style('opacity', 1); - - // Transition exiting nodes to the parent's new position. - nodes.exit().transition() - .duration(DURATION) - .attr('transform', function(d) { - var node = _getVertexNode(d, "x") || source; - node = _layout.projector(node.x, node.y); - return 'translate(' + node.x + ',' + node.y + ')'; - }) - .style('opacity', 1e-6) - .remove(); - } - - /** - * Get the node from/to which the link must transition on enter/exit - * @param d {DataNode} - * @param property {String} Property to be checked for - * @return node - */ - function _getTargetNode(d, property) { - if(d.get('target.type') == App.DagViewComponent.dataProcessor.types.OUTPUT - && d.get('source.' + property)) { - return d.source; - } - if(d.get('target.' + property)) { - return d.target; - } - } - /** - * Update position of all links in the list and preform required transitions. - * @param links {Array} Links to be updated - * @param source {d3 element} Node that trigged the update, in first update source will be root. - */ - function _updateLinks(links, source) { - // Enter any new links at the parent's previous position. - links.enter().insert('path', 'g') - .attr('class', function (d) { - var type = d.get('dataMovementType') || ""; - return 'link ' + type.toLowerCase(); - }) - /** - * IE11 rendering does not work for svg path element with marker set. - * See https://connect.microsoft.com/IE/feedback/details/801938 - * This can be removed once the bug is fixed in all supported IE versions - */ - .attr("style", App.env.isIE ? "" : "marker-mid: url(#arrow-marker);") - .attr('d', function(d) { - var node = _getTargetNode(d, "x0") || source; - var o = {x: node.x0, y: node.y0}; - return _createPathData({source: o, target: o}); - }) - .on({ - mouseover: _onMouseOver, - mouseout: _tip.hide - }); - - // Transition links to their new position. - links.transition() - .duration(DURATION) - .attr('d', _createPathData); - - // Transition exiting nodes to the parent's new position. - links.exit().transition() - .duration(DURATION) - .attr('d', function(d) { - var node = _getTargetNode(d, "x") || source; - var o = {x: node.x, y: node.y}; - return _createPathData({source: o, target: o}); - }) - .remove(); - } - - function _getNodeId(d) { - return d.id || (d.id = ++_idCounter); - } - function _getLinkId(d) { - return d.source.id.toString() + d.target.id; - } - function _stashOldPositions(d) { - d.x0 = d.x, - d.y0 = d.y; - } - - /** - * Updates position of nodes and links based on changes in _treeData. - */ - function _update() { - var nodesData = _treeLayout.nodes(_treeData), - linksData = _getLinks(nodesData); - - _normalize(nodesData); - - var nodes = _g.selectAll('g.node') - .data(nodesData, _getNodeId); - _updateNodes(nodes, _treeData); - - var links = _g.selectAll('path.link') - .data(linksData, _getLinkId); - _updateLinks(links, _treeData); - - nodesData.forEach(_stashOldPositions); - } - - /** - * Attach pan and zoom events on to the container. - * @param container {DOM element} Element onto which events are attached. - * @param g {d3 DOM element} SVG(d3) element that will be moved or scaled - */ - function _attachPanZoom(container, g) { - var SCALE_TUNER = 1 / 700, - MIN_SCALE = .5, - MAX_SCALE = 2; - - var prevX = 0, - prevY = 0, - - panX = PADDING, - panY = PADDING, - scale = 1, - - scheduleId = 0; - - /** - * Transform g to current panX, panY and scale. - * @param animate {Boolean} Animate the transformation in DURATION time. - */ - function transform(animate) { - var base = animate ? g.transition().duration(DURATION) : g; - base.attr('transform', 'translate(%@, %@) scale(%@)'.fmt(panX, panY, scale)); - } - - /** - * Check if the item have moved out of the visible area, and reset if required - */ - function visibilityCheck() { - var graphBound = g.node().getBoundingClientRect(), - containerBound = container[0].getBoundingClientRect(); - - if(graphBound.right < containerBound.left || - graphBound.bottom < containerBound.top || - graphBound.left > containerBound.right || - graphBound.top > containerBound.bottom) { - panX = PADDING, panY = PADDING, scale = 1; - transform(true); - } - } - - /** - * Schedule a visibility check and reset if required - */ - function scheduleVisibilityCheck() { - if(scheduleId) { - clearTimeout(scheduleId); - scheduleId = 0; - } - scheduleId = setTimeout(visibilityCheck, 100); - } - - /** - * Set pan values - */ - function onMouseMove(event) { - panX += event.pageX - prevX, - panY += event.pageY - prevY; - - transform(); - - prevX = event.pageX, - prevY = event.pageY; - } - /** - * Set zoom values, pan also would change as we are zooming with mouse position as pivote. - */ - function onWheel(event) { - var prevScale = scale, - - offset = container.offset(), - mouseX = event.pageX - offset.left, - mouseY = event.pageY - offset.top, - factor = 0; - - scale += event.deltaY * SCALE_TUNER; - if(scale < MIN_SCALE) { - scale = MIN_SCALE; - } - else if(scale > MAX_SCALE) { - scale = MAX_SCALE; - } - - factor = 1 - scale / prevScale, - panX += (mouseX - panX) * factor, - panY += (mouseY - panY) * factor; - - transform(); - scheduleVisibilityCheck(); - - _tip.reposition(); - event.preventDefault(); - } - - container - .on('mousewheel', onWheel) - .mousedown(function (event){ - prevX = event.pageX, - prevY = event.pageY; - - container.on('mousemove', onMouseMove); - container.parent().addClass('panning'); - }) - .mouseup(function (event){ - container.off('mousemove', onMouseMove); - container.parent().removeClass('panning'); - - scheduleVisibilityCheck(); - }) - - /** - * A closure to reset/modify panZoom based on an external event - * @param newPanX {Number} - * @param newPanY {Number} - * @param newScale {Number} - */ - return function(newPanX, newPanY, newScale) { - var values = { - panX: panX, - panY: panY, - scale: scale - }; - - panX = newPanX == undefined ? panX : newPanX, - panY = newPanY == undefined ? panY : newPanY, - scale = newScale == undefined ? scale : newScale; - - transform(true); - - return values; - } - } - - /** - * Sets the layout and update the display. - * @param layout {Object} One of the values defined in LAYOUTS object - */ - function _setLayout(layout) { - var leafCount = _data.leafCount, - dimention; - - // If count is even dummy will be replaced by output, so output would no more be leaf - if(_data.tree.get('children.length') % 2 == 0) { - leafCount--; - } - dimention = layout.projector(leafCount, _data.maxDepth - 1); - - _layout = layout; - - _width = dimention.x *= _layout.hSpacing, - _height = dimention.y *= _layout.vSpacing; - - dimention = _layout.projector(dimention.x, dimention.y), // Because tree is always top to bottom - _treeLayout = d3.layout.tree().size([dimention.x, dimention.y]); - - _update(); - } - - return { - /** - * Creates a DAG view in the given element based on the data - * @param component {DagViewComponent} Parent ember component, to sendAction - * @param element {HTML DOM Element} HTML element in which the view will be created - * @param data {Object} Created by data processor - */ - create: function (component, element, data) { - var svg = d3.select(element).select('svg'); - - _component = component, - _data = data, - _g = svg.append('g').attr('transform', 'translate(%@,%@)'.fmt(PADDING, PADDING)); - _svg = $(svg.node()); - _tip = App.DagViewComponent.tip; - - _tip.init($(element).find('.tool-tip'), _svg); - - _treeData = data.tree, - _treeData.x0 = 0, - _treeData.y0 = 0; - - _panZoom = _attachPanZoom(_svg, _g); - - _setLayout(LAYOUTS.topToBottom); - }, - - /** - * Calling this function would fit the graph to the available space. - */ - fitGraph: function (){ - var scale = Math.min( - (_svg.width() - PADDING * 2) / _width, - (_svg.height() - PADDING * 2) / _height - ), - panZoomValues = _panZoom(); - - if( - panZoomValues.panX != PADDING || - panZoomValues.panY != PADDING || - panZoomValues.scale != scale - ) { - _panZoomValues = _panZoom(PADDING, PADDING, scale); - } - else { - _panZoomValues = _panZoom( - _panZoomValues.panX, - _panZoomValues.panY, - _panZoomValues.scale); - } - }, - - /** - * Control display of additionals or sources and sinks. - * @param hide {Boolean} If true the additionals will be excluded, else included in the display - */ - additionalDisplay: function (hide) { - var dataProcessor = App.DagViewComponent.dataProcessor, - filterTypes = null; - - if(hide) { - _g.attr('class', 'hide-io'); - _treeData.recursivelyCall('excludeAdditionals'); - } - else { - _treeData.recursivelyCall('includeAdditionals'); - _g.attr('class', null); - } - _update(); - }, - - /** - * Toggle graph layouts between the available options - */ - toggleLayouts: function () { - _setLayout(_layout == LAYOUTS.topToBottom ? - LAYOUTS.leftToRight : - LAYOUTS.topToBottom); - return _layout == LAYOUTS.topToBottom; - } - }; - -})();
