diff options
author | Benjamin Jones <bjones@galois.com> | 2013-07-16 15:58:14 -0700 |
---|---|---|
committer | Benjamin Jones <bjones@galois.com> | 2013-07-16 15:58:14 -0700 |
commit | 59a50f30adfa5bdd41109ff6df7d32ecd2672932 (patch) | |
tree | 062d33217cbfbfb52275730eab349566797c228e /src/js/fiveui/injected | |
parent | 54d73a015a05ded583723a3b204580ea66d79acf (diff) | |
parent | f1d4987e44a5ba3e66bf724d264ef2a57b82b775 (diff) |
Merge branch 'new-ui' into new-ui-severity
Diffstat (limited to 'src/js/fiveui/injected')
-rw-r--r-- | src/js/fiveui/injected/compute.js | 2 | ||||
-rw-r--r-- | src/js/fiveui/injected/jquery-plugins.js | 2 | ||||
-rw-r--r-- | src/js/fiveui/injected/prelude.js | 4 | ||||
-rw-r--r-- | src/js/fiveui/injected/ui.js | 528 |
4 files changed, 358 insertions, 178 deletions
diff --git a/src/js/fiveui/injected/compute.js b/src/js/fiveui/injected/compute.js index 2cfab53..d8ae9e8 100644 --- a/src/js/fiveui/injected/compute.js +++ b/src/js/fiveui/injected/compute.js @@ -291,7 +291,7 @@ * @param {DOMNode} elt */ var underFiveUI = function(elt) { - var ancestor = $(elt).parentsUntil('#fiveui-top', 'body'); + var ancestor = $(elt).parentsUntil('.fiveui', 'body'); return ancestor.length == 0; }; diff --git a/src/js/fiveui/injected/jquery-plugins.js b/src/js/fiveui/injected/jquery-plugins.js index 5a32031..a8c99f2 100644 --- a/src/js/fiveui/injected/jquery-plugins.js +++ b/src/js/fiveui/injected/jquery-plugins.js @@ -19,6 +19,8 @@ * limitations under the License. */ +var fiveui = fiveui || {}; + /** * This module provides several useful jQuery plugins related to checking and reporting * UI consistency issues. diff --git a/src/js/fiveui/injected/prelude.js b/src/js/fiveui/injected/prelude.js index db32d7f..cb1422a 100644 --- a/src/js/fiveui/injected/prelude.js +++ b/src/js/fiveui/injected/prelude.js @@ -81,8 +81,8 @@ fiveui.query = function (sel, context) { } ); - $filteredResults = $results.not('#fiveui-top') - .not('#fiveui-top *') + $filteredResults = $results.not('.fiveui') + .not('.fiveui *') .filter(':visible'); // update global stats diff --git a/src/js/fiveui/injected/ui.js b/src/js/fiveui/injected/ui.js index 1eecd93..8bedc46 100644 --- a/src/js/fiveui/injected/ui.js +++ b/src/js/fiveui/injected/ui.js @@ -20,13 +20,361 @@ */ (function(){ + /** * Storage namespace for in-browser logic */ var core = {}; core.port = obtainPort(); - core.ui = $('<div></div>'); + + /* User Interface **********************************************************/ + + core.UI = function() { + this._initialize.apply(this, arguments); + }; + + + _.extend(core.UI, { + + /** + * Template for the UI dialog + */ + uiTemplate:_.template( + [ '<div class="fiveui">' + , ' <div class="fiveui-titlebar">' + , ' FiveUI<div class="fiveui-close"><span class="icon-remove"></span></div>' + , ' </div>' + , ' <div class="fiveui-controls">' + , ' <div class="fiveui-control fiveui-clear" title="clear"><span class="icon-ok"></span></div>' + , ' <div class="fiveui-control fiveui-break" title="break"><span class="icon-pause"></span></div>' + , ' </div>' + , ' <div class="fiveui-problems"></div>' + , ' <div class="fiveui-stats"></div>' + , '</div>' + ].join('')), + + /** + * Template for the stats panel of the UI dialog. + */ + statsTemplate:_.template( + [ '<table class="fiveui-table">' + , ' <tr>' + , ' <td class="fiveui-table-text">rules checked:</td>' + , ' <td class="fiveui-table-number"><%= numRules %></td>' + , ' </tr>' + , ' <tr>' + , ' <td class="fiveui-table-text">elements checked:</td>' + , ' <td class="fiveui-table-number"><%= numElts %></td>' + , ' </tr>' + , ' <tr>' + , ' <td class="fiveui-table-text">elapsed time (ms):</td>' + , ' <td class="fiveui-table-number"><%= time %></td>' + , ' </tr>' + , '</table>' + ].join('')), + + }); + + _.extend(core.UI.prototype, { + + /** + * Create the UI, and attach all event handlers. + * @private + */ + _initialize:function(opts) { + + // apply options + var optNames = [ 'port' ]; + _.defaults(this, _.pick(opts, optNames)); + + this.$el = $(core.UI.uiTemplate()); + this.$problems = this.$el.find('.fiveui-problems'); + this.$stats = this.$el.find('.fiveui-stats'); + + this._setupButtons(); + this._setupDragDrop(); + + // force the resize event + this.height = 0; + this._pollResize(); + + this._registerBackendListeners(); + + // initially, keep the window hidden + this.$el.hide(); + }, + + /** + * Setup the functionality of the close button on the ui + * @private + */ + _setupButtons:function() { + + var close = this.$el.find('.fiveui-close'); + close.on('click.fiveui', _.bind(this.hide, this)); + + var clear = this.$el.find('.fiveui-clear'); + clear.on('click.fiveui', _.bind(this.clearProblems, this)); + + // note, this only works in chrome + var pause = this.$el.find('.fiveui-break'); + pause.on('click.fiveui', function() { + debugger; + }); + + }, + + /** + * Setup the drag and drop functionality for the problems window. + * @private + */ + _setupDragDrop:function() { + + var self = this; + var header = this.$el.find('.fiveui-titlebar'); + var offset = { x: 0, y: 0 }; + + // update the location of the ui + var mouseMove = function(e) { + self.$el.css({ + left: e.originalEvent.clientX + offset.x, + top: e.originalEvent.clientY + offset.y, + }); + }; + + var cancel = function(e) { + e.stopPropagation(); + }; + + // both of these will cause funny things to happen with the text of the title + // bar. + header.on('dragstart', cancel); + header.on('selectstart', cancel); + + // figure out how far the cursor is from the top-left of the ui + header.on('mousedown.fiveui', function(e) { + + // prevent the close button from being used as a drag handle + if(e.target != header[0]) { + return false; + } + + var pos = self.$el.position(); + offset.x = pos.left - e.originalEvent.clientX; + offset.y = pos.top - e.originalEvent.clientY; + + $(window).on('mousemove.fiveui', mouseMove); + header.one('mouseup.fiveui', function() { + $(window).off('mousemove.fiveui', mouseMove); + + // deliver the new position to teh backend + self.port.emit('Position', self.$el.position()); + }); + }); + + }, + + _pollResize:function() { + + var height = this.$el.height(); + + if(height != this.height) { + + console.log('changing height'); + + this.height = height; + + var ppos = this.$problems.position(); + var spos = this.$stats.position(); + + this.$problems.height(spos.top - ppos.top) + + // notify the backend about the new height + this.port.emit('Size', { + width: this.$el.width(), + height: this.$el.height() + }); + } + + setTimeout(_.bind(this._pollResize, this), 100); + }, + + /** + * Setup listeners to the backend. + */ + _registerBackendListeners:function() { + + var self = this; + + this.port.on('ShowUI', function(unused) { + self.show(); + }); + + this.port.on('ShowProblem', _.bind(this.addProblem, this)); + + this.port.on('ShowStats', _.bind(this.renderStats, this)); + + // initialize/create the ui, set its position and size + this.port.on('RestoreUI', function(state) { + + // set the position and size + self.$el.css({ + 'top': state.winState.y, + 'left': state.winState.x, + 'width': state.winState.width + 'px', + 'height': state.winState.height + 'px' + }); + + // optionally show the window + if(!state.winState.closed) { + self.show(); + } + + // add all problems + _.each(state.problems, _.bind(self.addProblem, self)); + + // render stats + self.renderStats(state.stats); + + }); + }, + + /** + * Clear the problems list + * @public + */ + clearProblems:function() { + this.$el.find('.fiveui-problems').children().remove(); + this.port.emit('ClearProblems'); + }, + + /** + * Add an entry in the problems list. + * @public + */ + addProblem:function(problem) { + + var p = new core.Problem(problem); + p.appendTo(this.$el.find('.fiveui-problems')); + + }, + + /** + * Attach the UI to a jquery selector. + * @public + */ + appendTo:function(el) { + el.append(this.$el); + }, + + /** + * Hide the UI + * @public + */ + hide:function() { + this.$el.hide(); + this.port.emit('CloseUI'); + }, + + /** + * Show the UI + * @public + */ + show:function() { + this.$el.show(); + }, + + /** + * Render statistics + */ + renderStats:function(stats) { + + stats = stats || {}; + _.defaults(stats, { + numRules: 0, + numElts: 0, + start: 0, + end: 0, + }); + + stats.time = stats.end - stats.start; + + this.$stats.html(core.UI.statsTemplate(stats)); + }, + + }); + + + /** + * Entries in the problem list. + */ + core.Problem = function() { + this._initialize.apply(this, arguments); + }; + + _.extend(core.Problem, { + + /** + * Template for entries in the problems list + */ + problemTemplate:_.template( + [ '<div class="fiveui-problem fiveui-severity-<%= severity %>">' + , ' <div class="fiveui-problem-header">' + , ' <div class="fiveui-problem-toggle"><span></span></div>' + , ' <%= name %>' + , ' </div>' + , ' <div class="fiveui-problem-body">' + , ' <p><%= msg %></p>' + , ' <p><span class="fiveui-xpath"><%= xpath %></span></p>' + , ' </div>' + , '</div>' + ].join('')), + + }); + + _.extend(core.Problem.prototype, { + + _initialize:function(problem) { + + this.problem = problem; + + this.$el = $(core.Problem.problemTemplate(problem)); + this.$toggle = this.$el.find('.fiveui-problem-toggle'); + this.$body = this.$el.find('.fiveui-problem-body'); + this.$header = this.$el.find('.fiveui-problem-header'); + + this.$body.hide(); + + this.close(); + }, + + appendTo:function(el) { + el.append(this.$el); + }, + + /** + * Close the context for a problem entry. + * @public + */ + close:function() { + this.$toggle.find('span').removeClass('icon-caret-down') + .addClass('icon-caret-right'); + + this.$el.one('click', _.bind(this.open, this)); + this.$body.slideUp(100); + }, + + open:function() { + this.$toggle.find('span').addClass('icon-caret-down') + .removeClass('icon-caret-right'); + + this.$el.one('click', _.bind(this.close, this)); + this.$body.slideDown(100); + }, + + }); + core.lockDepth = 0; @@ -72,7 +420,7 @@ } else { // add the rule to the list of highlighted elements, and change its style // to look obvious. - var elt = fiveui.query('.' + prob.hash); + var elt = core.query('.' + prob.hash); var oldStyle = elt.attr('style'); core.maskRules(function() { @@ -95,7 +443,7 @@ obj.highlighted = obj.highlighted - 1; if(obj.highlighted == 0) { - var elt = fiveui.query('.' + prob.hash); + var elt = core.query('.' + prob.hash); // remove the fiveui style core.maskRules(function() { @@ -113,33 +461,9 @@ } }; - core.renderStatsTemplate = _.template( - [ '<table class="fiveui-table">' - , ' <tr>' - , ' <td class="fiveui-table-text">rules checked:</td>' - , ' <td class="fiveui-table-number"><%= numRules %></td>' - , ' </tr>' - , ' <tr>' - , ' <td class="fiveui-table-text">elements checked:</td>' - , ' <td class="fiveui-table-number"><%= numElts %></td>' - , ' </tr>' - , ' <tr>' - , ' <td class="fiveui-table-text">elapsed time (ms):</td>' - , ' <td class="fiveui-table-number"><%= time %></td>' - , ' </tr>' - , '</table>' - ].join('')); - core.renderStats = function (stats) { // give stats some sane defaults. - stats = stats || {}; - _.defaults(stats, { - numRules: 0, - numElts: 0, - start: 0, - end: 0, - }); core.maskRules(function () { @@ -152,153 +476,7 @@ }); }; - core.renderProblem = function(prob) { - core.maskRules(function() { - var probDiv = $('<div class="pr"></div>'); - - - /** Problem Controls **/ - var prControls = $('<div class="prControls"></div>'); - probDiv.append(prControls); - - var prSeverity = $('<div class="prSeverity"></div>'); - prControls.append(prSeverity); - - if (1 == prob.severity) { - prSeverity.addClass('prSeverity-err'); - } else { - prSeverity.addClass('prSeverity-warn'); - } - - var prExpand = $('<div class="prExpand prExpand-right"></div>'); - prControls.append(prExpand); - - /** Problem Content **/ - var prMessage = $('<div class="prMessage"></div>'); - probDiv.append(prMessage); - - var prTitle = $('<div class="prTitle">'+prob.name+'</div>'); - prMessage.append(prTitle); - - var prDetails = $('<div class="prDetails"></div>'); - prMessage.append(prDetails); - - - var prDescr = $('<p>'+prob.descr+'</p>'); - var prPath = $('<p>'+prob.xpath+'</p>'); - prDetails.append(prDescr); - if (prob.msg) { - var reportMsg = $('<div class="prReportMessage">'+prob.msg+'</div>'); - prDetails.append(reportMsg); - } - prDetails.append(prPath); - prDetails.hide(); - - $('#problemList').append(probDiv); - - prExpand.click( - function() { - var elt = $(this); - if(elt.is('.prExpand-down')) { - elt.removeClass('prExpand-down') - .addClass('prExpand-right'); - prDetails.hide(); - core.maskProblem(prob); - } else { - elt.addClass('prExpand-down') - .removeClass('prExpand-right'); - prDetails.show(); - core.highlightProblem(prob); - } - - return false; - }); - }); - }; - - var dragStop = function(evt,e) { - core.port.emit('Position', core.ui.parent().position()); - }; - - var resizeStop = function(evt,e) { - core.port.emit('Size', { width: core.ui.width(), height: core.ui.height() }); - }; - - var beforeClose = function(evt,e) { - core.port.emit('CloseUI'); - }; - - var registerBackendListeners = function(port) { - - port.on('ShowUI', function(unused) { - core.ui.dialog('open'); - }); - - port.on('ShowProblem', function(problem) { - core.renderProblem(problem); - }); - - port.on('ShowStats', function(stats) { - core.renderStats(stats); - }); - - port.on('RestoreUI', function(state) { - core.ui.append($('<div id="controls"></div>')); - - core.ui.append($('<div id="problemList"></div>')); - - var newDialog = core.ui.dialog({ title: 'FiveUI', - dragStop: dragStop, - resizeStop: resizeStop, - beforeClose: beforeClose, - position: [state.winState.x, state.winState.y], - width: state.winState.width, - height: state.winState.height, - autoOpen: false, - zIndex: 50000 - }); - newDialog.parent().attr('id', 'fiveui-top'); - - $('#controls').append($('<div id="clearButton"></div>') - .button({ label: 'clear' })); - - $('#clearButton').click(function() { - $('#problemList').children().remove(); - port.emit('ClearProblems'); - - core.renderStats(); - $('prExpand-down').click(); - - // Just in case the click event on prExpand-down missde anything: - core.maskProblem(fiveui.query('.uic-problem'), undefined); - core.renderStats(); - }); - - /////////////////////////////////////////// - // Add a button that causes a debuger break. - // - // handy for playing with Jquery on the dom. - // Note: This only works in Google Chrome. - $('#controls').append($('<div id="breakButton"></div>') - .button({ label: 'break' })); - $('#breakButton').click(function() { - debugger; // - }); // - //////////////////////////////////////////// - - core.ui.append($('<div id="fiveui-stats"></div>')); - - if(!state.winState.closed) { - core.ui.dialog('open'); - } - - $(state.problems).each(function(ix,prob) { - core.renderProblem(prob); - }); - - core.renderStats(state.stats); - }); - }; + core.win = new core.UI({ port: core.port }); - registerBackendListeners(core.port); + core.win.appendTo($('body')); })(); |