Commit 973208c3 authored by Joshua Gould's avatar Joshua Gould

scroll lens

parent baa26b67
/*! /*!
* Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select) * Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select)
* *
* Copyright 2013-2016 bootstrap-select * Copyright 2013-2016 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\9}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px;z-index:1}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2}.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group.bs-container{position:absolute}.bootstrap-select.btn-group.bs-container .dropdown-menu{z-index:1060}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none} */select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\9}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px;z-index:1}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2}.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group.bs-container{position:absolute}.bootstrap-select.btn-group.bs-container .dropdown-menu{z-index:1060}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -72,7 +72,6 @@ ...@@ -72,7 +72,6 @@
.morpheus-tip-inline { .morpheus-tip-inline {
font-size: 12px; font-size: 12px;
max-width: 400px;
z-index: 10000; z-index: 10000;
position: absolute; position: absolute;
background-color: rgba(255, 255, 255, 0.9); background-color: rgba(255, 255, 255, 0.9);
......
/*! /*!
* Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select) * Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select)
* *
* Copyright 2013-2016 bootstrap-select * Copyright 2013-2016 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/ */
!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){!function(a){"use strict";function b(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b.replace(this.re,this.ch)}),b}function c(a){var b={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},c="(?:"+Object.keys(b).join("|")+")",d=new RegExp(c),e=new RegExp(c,"g"),f=null==a?"":""+a;return d.test(f)?f.replace(e,function(a){return b[a]}):f}function d(b,c){var d=arguments,f=b,g=c;[].shift.apply(d);var h,i=this.each(function(){var b=a(this);if(b.is("select")){var c=b.data("selectpicker"),i="object"==typeof f&&f;if(c){if(i)for(var j in i)i.hasOwnProperty(j)&&(c.options[j]=i[j])}else{var k=a.extend({},e.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),i);k.template=a.extend({},e.DEFAULTS.template,a.fn.selectpicker.defaults?a.fn.selectpicker.defaults.template:{},b.data().template,i.template),b.data("selectpicker",c=new e(this,k,g))}"string"==typeof f&&(h=c[f]instanceof Function?c[f].apply(c,d):c.options[f])}});return"undefined"!=typeof h?h:i}String.prototype.includes||!function(){var a={}.toString,b=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),c="".indexOf,d=function(b){if(null==this)throw new TypeError;var d=String(this);if(b&&"[object RegExp]"==a.call(b))throw new TypeError;var e=d.length,f=String(b),g=f.length,h=arguments.length>1?arguments[1]:void 0,i=h?Number(h):0;i!=i&&(i=0);var j=Math.min(Math.max(i,0),e);return g+j>e?!1:-1!=c.call(d,f,i)};b?b(String.prototype,"includes",{value:d,configurable:!0,writable:!0}):String.prototype.includes=d}(),String.prototype.startsWith||!function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),b={}.toString,c=function(a){if(null==this)throw new TypeError;var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw new TypeError;var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j<f;)if(c.charCodeAt(i+j)!=e.charCodeAt(j))return!1;return!0};a?a(String.prototype,"startsWith",{value:c,configurable:!0,writable:!0}):String.prototype.startsWith=c}(),Object.keys||(Object.keys=function(a,b,c){c=[];for(b in a)c.hasOwnProperty.call(a,b)&&c.push(b);return c}),a.fn.triggerNative=function(a){var b,c=this[0];c.dispatchEvent?("function"==typeof Event?b=new Event(a,{bubbles:!0}):(b=document.createEvent("Event"),b.initEvent(a,!0,!1)),c.dispatchEvent(b)):(c.fireEvent&&(b=document.createEventObject(),b.eventType=a,c.fireEvent("on"+a,b)),this.trigger(a))},a.expr[":"].icontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toUpperCase();return f.includes(d[3].toUpperCase())},a.expr[":"].ibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toUpperCase();return f.startsWith(d[3].toUpperCase())},a.expr[":"].aicontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toUpperCase();return f.includes(d[3].toUpperCase())},a.expr[":"].aibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toUpperCase();return f.startsWith(d[3].toUpperCase())};var e=function(b,c,d){d&&(d.stopPropagation(),d.preventDefault()),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.$lis=null,this.options=c,null===this.options.title&&(this.options.title=this.$element.attr("title")),this.val=e.prototype.val,this.render=e.prototype.render,this.refresh=e.prototype.refresh,this.setStyle=e.prototype.setStyle,this.selectAll=e.prototype.selectAll,this.deselectAll=e.prototype.deselectAll,this.destroy=e.prototype.destroy,this.remove=e.prototype.remove,this.show=e.prototype.show,this.hide=e.prototype.hide,this.init()};e.VERSION="1.10.0",e.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(a,b){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){return[1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==b?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)"]},selectAllText:"Select All",deselectAllText:"Deselect All",doneButton:!1,doneButtonText:"Close",multipleSeparator:", ",styleBase:"btn",style:"btn-default",size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,liveSearchPlaceholder:null,liveSearchNormalize:!1,liveSearchStyle:"contains",actionsBox:!1,iconBase:"glyphicon",tickIcon:"glyphicon-ok",showTick:!1,template:{caret:'<span class="caret"></span>'},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1},e.prototype={constructor:e,init:function(){var b=this,c=this.$element.attr("id");this.$element.addClass("bs-select-hidden"),this.liObj={},this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$newElement=this.createView(),this.$element.after(this.$newElement).appendTo(this.$newElement),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(".dropdown-menu"),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),this.$element.removeClass("bs-select-hidden"),this.options.dropdownAlignRight&&this.$menu.addClass("dropdown-menu-right"),"undefined"!=typeof c&&(this.$button.attr("data-id",c),a('label[for="'+c+'"]').click(function(a){a.preventDefault(),b.$button.focus()})),this.checkDisabled(),this.clickListener(),this.options.liveSearch&&this.liveSearchListener(),this.render(),this.setStyle(),this.setWidth(),this.options.container&&this.selectPosition(),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(a){b.$element.trigger("hide.bs.select",a)},"hidden.bs.dropdown":function(a){b.$element.trigger("hidden.bs.select",a)},"show.bs.dropdown":function(a){b.$element.trigger("show.bs.select",a)},"shown.bs.dropdown":function(a){b.$element.trigger("shown.bs.select",a)}}),b.$element[0].hasAttribute("required")&&this.$element.on("invalid",function(){b.$button.addClass("bs-invalid").focus(),b.$element.on({"focus.bs.select":function(){b.$button.focus(),b.$element.off("focus.bs.select")},"shown.bs.select":function(){b.$element.val(b.$element.val()).off("shown.bs.select")},"rendered.bs.select":function(){this.validity.valid&&b.$button.removeClass("bs-invalid"),b.$element.off("rendered.bs.select")}})}),setTimeout(function(){b.$element.trigger("loaded.bs.select")})},createDropdown:function(){var b=this.multiple||this.options.showTick?" show-tick":"",d=this.$element.parent().hasClass("input-group")?" input-group-btn":"",e=this.autofocus?" autofocus":"",f=this.options.header?'<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>'+this.options.header+"</div>":"",g=this.options.liveSearch?'<div class="bs-searchbox"><input type="text" class="form-control" autocomplete="off"'+(null===this.options.liveSearchPlaceholder?"":' placeholder="'+c(this.options.liveSearchPlaceholder)+'"')+"></div>":"",h=this.multiple&&this.options.actionsBox?'<div class="bs-actionsbox"><div class="btn-group btn-group-sm btn-block"><button type="button" class="actions-btn bs-select-all btn btn-default">'+this.options.selectAllText+'</button><button type="button" class="actions-btn bs-deselect-all btn btn-default">'+this.options.deselectAllText+"</button></div></div>":"",i=this.multiple&&this.options.doneButton?'<div class="bs-donebutton"><div class="btn-group btn-block"><button type="button" class="btn btn-sm btn-default">'+this.options.doneButtonText+"</button></div></div>":"",j='<div class="btn-group bootstrap-select'+b+d+'"><button type="button" class="'+this.options.styleBase+' dropdown-toggle" data-toggle="dropdown"'+e+'><span class="filter-option pull-left"></span>&nbsp;<span class="bs-caret">'+this.options.template.caret+'</span></button><div class="dropdown-menu open">'+f+g+h+'<ul class="dropdown-menu inner" role="menu"></ul>'+i+"</div></div>";return a(j)},createView:function(){var a=this.createDropdown(),b=this.createLi();return a.find("ul")[0].innerHTML=b,a},reloadLi:function(){this.destroyLi();var a=this.createLi();this.$menuInner[0].innerHTML=a},destroyLi:function(){this.$menu.find("li").remove()},createLi:function(){var d=this,e=[],f=0,g=document.createElement("option"),h=-1,i=function(a,b,c,d){return"<li"+("undefined"!=typeof c&""!==c?' class="'+c+'"':"")+("undefined"!=typeof b&null!==b?' data-original-index="'+b+'"':"")+("undefined"!=typeof d&null!==d?'data-optgroup="'+d+'"':"")+">"+a+"</li>"},j=function(a,e,f,g){return'<a tabindex="0"'+("undefined"!=typeof e?' class="'+e+'"':"")+("undefined"!=typeof f?' style="'+f+'"':"")+(d.options.liveSearchNormalize?' data-normalized-text="'+b(c(a))+'"':"")+("undefined"!=typeof g||null!==g?' data-tokens="'+g+'"':"")+">"+a+'<span class="'+d.options.iconBase+" "+d.options.tickIcon+' check-mark"></span></a>'};if(this.options.title&&!this.multiple&&(h--,!this.$element.find(".bs-title-option").length)){var k=this.$element[0];g.className="bs-title-option",g.appendChild(document.createTextNode(this.options.title)),g.value="",k.insertBefore(g,k.firstChild),void 0===a(k.options[k.selectedIndex]).attr("selected")&&(g.selected=!0)}return this.$element.find("option").each(function(b){var c=a(this);if(h++,!c.hasClass("bs-title-option")){var g=this.className||"",k=this.style.cssText,l=c.data("content")?c.data("content"):c.html(),m=c.data("tokens")?c.data("tokens"):null,n="undefined"!=typeof c.data("subtext")?'<small class="text-muted">'+c.data("subtext")+"</small>":"",o="undefined"!=typeof c.data("icon")?'<span class="'+d.options.iconBase+" "+c.data("icon")+'"></span> ':"",p="OPTGROUP"===this.parentNode.tagName,q=this.disabled||p&&this.parentNode.disabled;if(""!==o&&q&&(o="<span>"+o+"</span>"),d.options.hideDisabled&&q&&!p)return void h--;if(c.data("content")||(l=o+'<span class="text">'+l+n+"</span>"),p&&c.data("divider")!==!0){var r=" "+this.parentNode.className||"";if(0===c.index()){f+=1;var s=this.parentNode.label,t="undefined"!=typeof c.parent().data("subtext")?'<small class="text-muted">'+c.parent().data("subtext")+"</small>":"",u=c.parent().data("icon")?'<span class="'+d.options.iconBase+" "+c.parent().data("icon")+'"></span> ':"";s=u+'<span class="text">'+s+t+"</span>",0!==b&&e.length>0&&(h++,e.push(i("",null,"divider",f+"div"))),h++,e.push(i(s,null,"dropdown-header"+r,f))}if(d.options.hideDisabled&&q)return void h--;e.push(i(j(l,"opt "+g+r,k,m),b,"",f))}else c.data("divider")===!0?e.push(i("",b,"divider")):c.data("hidden")===!0?e.push(i(j(l,g,k,m),b,"hidden is-hidden")):(this.previousElementSibling&&"OPTGROUP"===this.previousElementSibling.tagName&&(h++,e.push(i("",null,"divider",f+"div"))),e.push(i(j(l,g,k,m),b)));d.liObj[b]=h}}),this.multiple||0!==this.$element.find("option:selected").length||this.options.title||this.$element.find("option").eq(0).prop("selected",!0).attr("selected","selected"),e.join("")},findLis:function(){return null==this.$lis&&(this.$lis=this.$menu.find("li")),this.$lis},render:function(b){var c,d=this;b!==!1&&this.$element.find("option").each(function(a){var b=d.findLis().eq(d.liObj[a]);d.setDisabled(a,this.disabled||"OPTGROUP"===this.parentNode.tagName&&this.parentNode.disabled,b),d.setSelected(a,this.selected,b)}),this.tabIndex();var e=this.$element.find("option").map(function(){if(this.selected){if(d.options.hideDisabled&&(this.disabled||"OPTGROUP"===this.parentNode.tagName&&this.parentNode.disabled))return;var b,c=a(this),e=c.data("icon")&&d.options.showIcon?'<i class="'+d.options.iconBase+" "+c.data("icon")+'"></i> ':"";return b=d.options.showSubtext&&c.data("subtext")&&!d.multiple?' <small class="text-muted">'+c.data("subtext")+"</small>":"","undefined"!=typeof c.attr("title")?c.attr("title"):c.data("content")&&d.options.showContent?c.data("content"):e+c.html()+b}}).toArray(),f=this.multiple?e.join(this.options.multipleSeparator):e[0];if(this.multiple&&this.options.selectedTextFormat.indexOf("count")>-1){var g=this.options.selectedTextFormat.split(">");if(g.length>1&&e.length>g[1]||1==g.length&&e.length>=2){c=this.options.hideDisabled?", [disabled]":"";var h=this.$element.find("option").not('[data-divider="true"], [data-hidden="true"]'+c).length,i="function"==typeof this.options.countSelectedText?this.options.countSelectedText(e.length,h):this.options.countSelectedText;f=i.replace("{0}",e.length.toString()).replace("{1}",h.toString())}}void 0==this.options.title&&(this.options.title=this.$element.attr("title")),"static"==this.options.selectedTextFormat&&(f=this.options.title),f||(f="undefined"!=typeof this.options.title?this.options.title:this.options.noneSelectedText),this.$button.attr("title",a.trim(f.replace(/<[^>]*>?/g,""))),this.$button.children(".filter-option").html(f),this.$element.trigger("rendered.bs.select")},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,""));var c=a?a:this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(b){if(b||this.options.size!==!1&&!this.sizeInfo){var c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("ul"),f=document.createElement("li"),g=document.createElement("li"),h=document.createElement("a"),i=document.createElement("span"),j=this.options.header&&this.$menu.find(".popover-title").length>0?this.$menu.find(".popover-title")[0].cloneNode(!0):null,k=this.options.liveSearch?document.createElement("div"):null,l=this.options.actionsBox&&this.multiple&&this.$menu.find(".bs-actionsbox").length>0?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,m=this.options.doneButton&&this.multiple&&this.$menu.find(".bs-donebutton").length>0?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null;if(i.className="text",c.className=this.$menu[0].parentNode.className+" open",d.className="dropdown-menu open",e.className="dropdown-menu inner",f.className="divider",i.appendChild(document.createTextNode("Inner text")),h.appendChild(i),g.appendChild(h),e.appendChild(g),e.appendChild(f),j&&d.appendChild(j),k){var n=document.createElement("span");k.className="bs-searchbox",n.className="form-control",k.appendChild(n),d.appendChild(k)}l&&d.appendChild(l),d.appendChild(e),m&&d.appendChild(m),c.appendChild(d),document.body.appendChild(c);var o=h.offsetHeight,p=j?j.offsetHeight:0,q=k?k.offsetHeight:0,r=l?l.offsetHeight:0,s=m?m.offsetHeight:0,t=a(f).outerHeight(!0),u="function"==typeof getComputedStyle?getComputedStyle(d):!1,v=u?null:a(d),w=parseInt(u?u.paddingTop:v.css("paddingTop"))+parseInt(u?u.paddingBottom:v.css("paddingBottom"))+parseInt(u?u.borderTopWidth:v.css("borderTopWidth"))+parseInt(u?u.borderBottomWidth:v.css("borderBottomWidth")),x=w+parseInt(u?u.marginTop:v.css("marginTop"))+parseInt(u?u.marginBottom:v.css("marginBottom"))+2;document.body.removeChild(c),this.sizeInfo={liHeight:o,headerHeight:p,searchHeight:q,actionsHeight:r,doneButtonHeight:s,dividerHeight:t,menuPadding:w,menuExtras:x}}},setSize:function(){if(this.findLis(),this.liHeight(),this.options.header&&this.$menu.css("padding-top",0),this.options.size!==!1){var b,c,d,e,f=this,g=this.$menu,h=this.$menuInner,i=a(window),j=this.$newElement[0].offsetHeight,k=this.sizeInfo.liHeight,l=this.sizeInfo.headerHeight,m=this.sizeInfo.searchHeight,n=this.sizeInfo.actionsHeight,o=this.sizeInfo.doneButtonHeight,p=this.sizeInfo.dividerHeight,q=this.sizeInfo.menuPadding,r=this.sizeInfo.menuExtras,s=this.options.hideDisabled?".disabled":"",t=function(){d=f.$newElement.offset().top-i.scrollTop(),e=i.height()-d-j};if(t(),"auto"===this.options.size){var u=function(){var i,j=function(b,c){return function(d){return c?d.classList?d.classList.contains(b):a(d).hasClass(b):!(d.classList?d.classList.contains(b):a(d).hasClass(b))}},p=f.$menuInner[0].getElementsByTagName("li"),s=Array.prototype.filter?Array.prototype.filter.call(p,j("hidden",!1)):f.$lis.not(".hidden"),u=Array.prototype.filter?Array.prototype.filter.call(s,j("dropdown-header",!0)):s.filter(".dropdown-header");t(),b=e-r,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&f.$newElement.toggleClass("dropup",d>e&&c>b-r),f.$newElement.hasClass("dropup")&&(b=d-r),i=s.length+u.length>3?3*k+r-2:0,g.css({"max-height":b+"px",overflow:"hidden","min-height":i+l+m+n+o+"px"}),h.css({"max-height":b-l-m-n-o-q+"px","overflow-y":"auto","min-height":Math.max(i-q,0)+"px"})};u(),this.$searchbox.off("input.getSize propertychange.getSize").on("input.getSize propertychange.getSize",u),i.off("resize.getSize scroll.getSize").on("resize.getSize scroll.getSize",u)}else if(this.options.size&&"auto"!=this.options.size&&this.$lis.not(s).length>this.options.size){var v=this.$lis.not(".divider").not(s).children().slice(0,this.options.size).last().parent().index(),w=this.$lis.slice(0,v+1).filter(".divider").length;b=k*this.options.size+w*p+q,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&this.$newElement.toggleClass("dropup",d>e&&c>b-r),g.css({"max-height":b+l+m+n+o+"px",overflow:"hidden","min-height":""}),h.css({"max-height":b-q+"px","overflow-y":"auto","min-height":""})}}},setWidth:function(){if("auto"===this.options.width){this.$menu.css("min-width","0");var a=this.$menu.parent().clone().appendTo("body"),b=this.options.container?this.$newElement.clone().appendTo("body"):a,c=a.children(".dropdown-menu").outerWidth(),d=b.css("width","auto").children("button").outerWidth();a.remove(),b.remove(),this.$newElement.css("width",Math.max(c,d)+"px")}else"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width",""));this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement.removeClass("fit-width")},selectPosition:function(){this.$bsContainer=a('<div class="bs-container" />');var b,c,d=this,e=function(a){d.$bsContainer.addClass(a.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass("dropup",a.hasClass("dropup")),b=a.offset(),c=a.hasClass("dropup")?0:a[0].offsetHeight,d.$bsContainer.css({top:b.top+c,left:b.left,width:a[0].offsetWidth})};this.$button.on("click",function(){var b=a(this);d.isDisabled()||(e(d.$newElement),d.$bsContainer.appendTo(d.options.container).toggleClass("open",!b.hasClass("open")).append(d.$menu))}),a(window).on("resize scroll",function(){e(d.$newElement)}),this.$element.on("hide.bs.select",function(){d.$menu.data("height",d.$menu.height()),d.$bsContainer.detach()})},setSelected:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),c.toggleClass("selected",b)},setDisabled:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),b?c.addClass("disabled").children("a").attr("href","#").attr("tabindex",-1):c.removeClass("disabled").children("a").removeAttr("href").attr("tabindex",0)},isDisabled:function(){return this.$element[0].disabled},checkDisabled:function(){var a=this;this.isDisabled()?(this.$newElement.addClass("disabled"),this.$button.addClass("disabled").attr("tabindex",-1)):(this.$button.hasClass("disabled")&&(this.$newElement.removeClass("disabled"),this.$button.removeClass("disabled")),-1!=this.$button.attr("tabindex")||this.$element.data("tabindex")||this.$button.removeAttr("tabindex")),this.$button.click(function(){return!a.isDisabled()})},tabIndex:function(){this.$element.data("tabindex")!==this.$element.attr("tabindex")&&-98!==this.$element.attr("tabindex")&&"-98"!==this.$element.attr("tabindex")&&(this.$element.data("tabindex",this.$element.attr("tabindex")),this.$button.attr("tabindex",this.$element.data("tabindex"))),this.$element.attr("tabindex",-98)},clickListener:function(){var b=this,c=a(document);this.$newElement.on("touchstart.dropdown",".dropdown-menu",function(a){a.stopPropagation()}),c.data("spaceSelect",!1),this.$button.on("keyup",function(a){/(32)/.test(a.keyCode.toString(10))&&c.data("spaceSelect")&&(a.preventDefault(),c.data("spaceSelect",!1))}),this.$button.on("click",function(){b.setSize()}),this.$element.on("shown.bs.select",function(){if(b.options.liveSearch||b.multiple){if(!b.multiple){var a=b.liObj[b.$element[0].selectedIndex];if("number"!=typeof a||b.options.size===!1)return;var c=b.$lis.eq(a)[0].offsetTop-b.$menuInner[0].offsetTop;c=c-b.$menuInner[0].offsetHeight/2+b.sizeInfo.liHeight/2,b.$menuInner[0].scrollTop=c}}else b.$menuInner.find(".selected a").focus()}),this.$menuInner.on("click","li a",function(c){var d=a(this),e=d.parent().data("originalIndex"),f=b.$element.val(),g=b.$element.prop("selectedIndex");if(b.multiple&&c.stopPropagation(),c.preventDefault(),!b.isDisabled()&&!d.parent().hasClass("disabled")){var h=b.$element.find("option"),i=h.eq(e),j=i.prop("selected"),k=i.parent("optgroup"),l=b.options.maxOptions,m=k.data("maxOptions")||!1;if(b.multiple){if(i.prop("selected",!j),b.setSelected(e,!j),d.blur(),l!==!1||m!==!1){var n=l<h.filter(":selected").length,o=m<k.find("option:selected").length;if(l&&n||m&&o)if(l&&1==l)h.prop("selected",!1),i.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected"),b.setSelected(e,!0);else if(m&&1==m){k.find("option:selected").prop("selected",!1),i.prop("selected",!0);var p=d.parent().data("optgroup");b.$menuInner.find('[data-optgroup="'+p+'"]').removeClass("selected"),b.setSelected(e,!0)}else{var q="function"==typeof b.options.maxOptionsText?b.options.maxOptionsText(l,m):b.options.maxOptionsText,r=q[0].replace("{n}",l),s=q[1].replace("{n}",m),t=a('<div class="notify"></div>');q[2]&&(r=r.replace("{var}",q[2][l>1?0:1]),s=s.replace("{var}",q[2][m>1?0:1])),i.prop("selected",!1),b.$menu.append(t),l&&n&&(t.append(a("<div>"+r+"</div>")),b.$element.trigger("maxReached.bs.select")),m&&o&&(t.append(a("<div>"+s+"</div>")),b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(e,!1)},10),t.delay(750).fadeOut(300,function(){a(this).remove()})}}}else h.prop("selected",!1),i.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected"),b.setSelected(e,!0);b.multiple?b.options.liveSearch&&b.$searchbox.focus():b.$button.focus(),(f!=b.$element.val()&&b.multiple||g!=b.$element.prop("selectedIndex")&&!b.multiple)&&b.$element.trigger("changed.bs.select",[e,i.prop("selected"),j]).triggerNative("change")}}),this.$menu.on("click","li.disabled a, .popover-title, .popover-title :not(.close)",function(c){c.currentTarget==this&&(c.preventDefault(),c.stopPropagation(),b.options.liveSearch&&!a(c.target).hasClass("close")?b.$searchbox.focus():b.$button.focus())}),this.$menuInner.on("click",".divider, .dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click",".popover-title .close",function(){b.$button.click()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).hasClass("bs-select-all")?b.selectAll():b.deselectAll()}),this.$element.change(function(){b.render(!1)})},liveSearchListener:function(){var d=this,e=a('<li class="no-results"></li>');this.$button.on("click.dropdown.data-api touchstart.dropdown.data-api",function(){d.$menuInner.find(".active").removeClass("active"),d.$searchbox.val()&&(d.$searchbox.val(""),d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove()),d.multiple||d.$menuInner.find(".selected").addClass("active"),setTimeout(function(){d.$searchbox.focus()},10)}),this.$searchbox.on("click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){if(d.$searchbox.val()){var f=d.$lis.not(".is-hidden").removeClass("hidden").children("a");f=d.options.liveSearchNormalize?f.not(":a"+d._searchStyle()+'("'+b(d.$searchbox.val())+'")'):f.not(":"+d._searchStyle()+'("'+d.$searchbox.val()+'")'),f.parent().addClass("hidden"),d.$lis.filter(".dropdown-header").each(function(){var b=a(this),c=b.data("optgroup");0===d.$lis.filter("[data-optgroup="+c+"]").not(b).not(".hidden").length&&(b.addClass("hidden"),d.$lis.filter("[data-optgroup="+c+"div]").addClass("hidden"))});var g=d.$lis.not(".hidden");g.each(function(b){var c=a(this);c.hasClass("divider")&&(c.index()===g.first().index()||c.index()===g.last().index()||g.eq(b+1).hasClass("divider"))&&c.addClass("hidden")}),d.$lis.not(".hidden, .no-results").length?e.parent().length&&e.remove():(e.parent().length&&e.remove(),e.html(d.options.noneResultsText.replace("{0}",'"'+c(d.$searchbox.val())+'"')).show(),d.$menuInner.append(e))}else d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove();d.$lis.filter(".active").removeClass("active"),d.$searchbox.val()&&d.$lis.not(".hidden, .divider, .dropdown-header").eq(0).addClass("active").children("a").focus(),a(this).focus()})},_searchStyle:function(){var a={begins:"ibegins",startsWith:"ibegins"};return a[this.options.liveSearchStyle]||"icontains"},val:function(a){return"undefined"!=typeof a?(this.$element.val(a),this.render(),this.$element):this.$element.val()},changeAll:function(b){"undefined"==typeof b&&(b=!0),this.findLis();for(var c=this.$element.find("option"),d=this.$lis.not(".divider, .dropdown-header, .disabled, .hidden").toggleClass("selected",b),e=d.length,f=[],g=0;e>g;g++){var h=d[g].getAttribute("data-original-index");f[f.length]=c.eq(h)[0]}a(f).prop("selected",b),this.render(!1),this.$element.trigger("changed.bs.select").triggerNative("change")},selectAll:function(){return this.changeAll(!0)},deselectAll:function(){return this.changeAll(!1)},toggle:function(a){a=a||window.event,a&&a.stopPropagation(),this.$button.trigger("click")},keydown:function(c){var d,e,f,g,h,i,j,k,l,m=a(this),n=m.is("input")?m.parent().parent():m.parent(),o=n.data("this"),p=":not(.disabled, .hidden, .dropdown-header, .divider)",q={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"};if(o.options.liveSearch&&(n=m.parent().parent()),o.options.container&&(n=o.$menu),d=a("[role=menu] li",n),l=o.$newElement.hasClass("open"),!l&&(c.keyCode>=48&&c.keyCode<=57||c.keyCode>=96&&c.keyCode<=105||c.keyCode>=65&&c.keyCode<=90)&&(o.options.container?o.$button.trigger("click"):(o.setSize(),o.$menu.parent().addClass("open"),l=!0),o.$searchbox.focus()),o.options.liveSearch&&(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&0===o.$menu.find(".active").length&&(c.preventDefault(),o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus()),d=a("[role=menu] li"+p,n),m.val()||/(38|40)/.test(c.keyCode.toString(10))||0===d.filter(".active").length&&(d=o.$menuInner.find("li"),d=o.options.liveSearchNormalize?d.filter(":a"+o._searchStyle()+"("+b(q[c.keyCode])+")"):d.filter(":"+o._searchStyle()+"("+q[c.keyCode]+")"))),d.length){if(/(38|40)/.test(c.keyCode.toString(10)))e=d.index(d.find("a").filter(":focus").parent()),g=d.filter(p).first().index(),h=d.filter(p).last().index(),f=d.eq(e).nextAll(p).eq(0).index(),i=d.eq(e).prevAll(p).eq(0).index(),j=d.eq(f).prevAll(p).eq(0).index(),o.options.liveSearch&&(d.each(function(b){a(this).hasClass("disabled")||a(this).data("index",b)}),e=d.index(d.filter(".active")),g=d.first().data("index"),h=d.last().data("index"),f=d.eq(e).nextAll().eq(0).data("index"),i=d.eq(e).prevAll().eq(0).data("index"),j=d.eq(f).prevAll().eq(0).data("index")),k=m.data("prevIndex"),38==c.keyCode?(o.options.liveSearch&&e--,e!=j&&e>i&&(e=i),g>e&&(e=g),e==k&&(e=h)):40==c.keyCode&&(o.options.liveSearch&&e++,-1==e&&(e=0),e!=j&&f>e&&(e=f),e>h&&(e=h),e==k&&(e=g)),m.data("prevIndex",e),o.options.liveSearch?(c.preventDefault(),m.hasClass("dropdown-toggle")||(d.removeClass("active").eq(e).addClass("active").children("a").focus(),m.focus())):d.eq(e).children("a").focus();else if(!m.is("input")){var r,s,t=[];d.each(function(){a(this).hasClass("disabled")||a.trim(a(this).children("a").text().toLowerCase()).substring(0,1)==q[c.keyCode]&&t.push(a(this).index())}),r=a(document).data("keycount"),r++,a(document).data("keycount",r),s=a.trim(a(":focus").text().toLowerCase()).substring(0,1),s!=q[c.keyCode]?(r=1,a(document).data("keycount",r)):r>=t.length&&(a(document).data("keycount",0),r>t.length&&(r=1)),d.eq(t[r-1]).children("a").focus()}if((/(13|32)/.test(c.keyCode.toString(10))||/(^9$)/.test(c.keyCode.toString(10))&&o.options.selectOnTab)&&l){if(/(32)/.test(c.keyCode.toString(10))||c.preventDefault(),o.options.liveSearch)/(32)/.test(c.keyCode.toString(10))||(o.$menuInner.find(".active a").click(),m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){this.$lis=null,this.liObj={},this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var f=a.fn.selectpicker;a.fn.selectpicker=d,a.fn.selectpicker.Constructor=e,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=f,this},a(document).data("keycount",0).on("keydown.bs.select",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',e.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);d.call(b,b.data())})})}(a)}); !function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){!function(a){"use strict";function b(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b.replace(this.re,this.ch)}),b}function c(a){var b={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},c="(?:"+Object.keys(b).join("|")+")",d=new RegExp(c),e=new RegExp(c,"g"),f=null==a?"":""+a;return d.test(f)?f.replace(e,function(a){return b[a]}):f}function d(b,c){var d=arguments,f=b,g=c;[].shift.apply(d);var h,i=this.each(function(){var b=a(this);if(b.is("select")){var c=b.data("selectpicker"),i="object"==typeof f&&f;if(c){if(i)for(var j in i)i.hasOwnProperty(j)&&(c.options[j]=i[j])}else{var k=a.extend({},e.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),i);k.template=a.extend({},e.DEFAULTS.template,a.fn.selectpicker.defaults?a.fn.selectpicker.defaults.template:{},b.data().template,i.template),b.data("selectpicker",c=new e(this,k,g))}"string"==typeof f&&(h=c[f]instanceof Function?c[f].apply(c,d):c.options[f])}});return"undefined"!=typeof h?h:i}String.prototype.includes||!function(){var a={}.toString,b=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),c="".indexOf,d=function(b){if(null==this)throw new TypeError;var d=String(this);if(b&&"[object RegExp]"==a.call(b))throw new TypeError;var e=d.length,f=String(b),g=f.length,h=arguments.length>1?arguments[1]:void 0,i=h?Number(h):0;i!=i&&(i=0);var j=Math.min(Math.max(i,0),e);return g+j>e?!1:-1!=c.call(d,f,i)};b?b(String.prototype,"includes",{value:d,configurable:!0,writable:!0}):String.prototype.includes=d}(),String.prototype.startsWith||!function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),b={}.toString,c=function(a){if(null==this)throw new TypeError;var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw new TypeError;var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j<f;)if(c.charCodeAt(i+j)!=e.charCodeAt(j))return!1;return!0};a?a(String.prototype,"startsWith",{value:c,configurable:!0,writable:!0}):String.prototype.startsWith=c}(),Object.keys||(Object.keys=function(a,b,c){c=[];for(b in a)c.hasOwnProperty.call(a,b)&&c.push(b);return c}),a.fn.triggerNative=function(a){var b,c=this[0];c.dispatchEvent?("function"==typeof Event?b=new Event(a,{bubbles:!0}):(b=document.createEvent("Event"),b.initEvent(a,!0,!1)),c.dispatchEvent(b)):(c.fireEvent&&(b=document.createEventObject(),b.eventType=a,c.fireEvent("on"+a,b)),this.trigger(a))},a.expr[":"].icontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toUpperCase();return f.includes(d[3].toUpperCase())},a.expr[":"].ibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toUpperCase();return f.startsWith(d[3].toUpperCase())},a.expr[":"].aicontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toUpperCase();return f.includes(d[3].toUpperCase())},a.expr[":"].aibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toUpperCase();return f.startsWith(d[3].toUpperCase())};var e=function(b,c,d){d&&(d.stopPropagation(),d.preventDefault()),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.$lis=null,this.options=c,null===this.options.title&&(this.options.title=this.$element.attr("title")),this.val=e.prototype.val,this.render=e.prototype.render,this.refresh=e.prototype.refresh,this.setStyle=e.prototype.setStyle,this.selectAll=e.prototype.selectAll,this.deselectAll=e.prototype.deselectAll,this.destroy=e.prototype.destroy,this.remove=e.prototype.remove,this.show=e.prototype.show,this.hide=e.prototype.hide,this.init()};e.VERSION="1.10.0",e.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(a,b){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){return[1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==b?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)"]},selectAllText:"Select All",deselectAllText:"Deselect All",doneButton:!1,doneButtonText:"Close",multipleSeparator:", ",styleBase:"btn",style:"btn-default",size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,liveSearchPlaceholder:null,liveSearchNormalize:!1,liveSearchStyle:"contains",actionsBox:!1,iconBase:"glyphicon",tickIcon:"glyphicon-ok",showTick:!1,template:{caret:'<span class="caret"></span>'},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1},e.prototype={constructor:e,init:function(){var b=this,c=this.$element.attr("id");this.$element.addClass("bs-select-hidden"),this.liObj={},this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$newElement=this.createView(),this.$element.after(this.$newElement).appendTo(this.$newElement),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(".dropdown-menu"),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),this.$element.removeClass("bs-select-hidden"),this.options.dropdownAlignRight&&this.$menu.addClass("dropdown-menu-right"),"undefined"!=typeof c&&(this.$button.attr("data-id",c),a('label[for="'+c+'"]').click(function(a){a.preventDefault(),b.$button.focus()})),this.checkDisabled(),this.clickListener(),this.options.liveSearch&&this.liveSearchListener(),this.render(),this.setStyle(),this.setWidth(),this.options.container&&this.selectPosition(),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(a){b.$element.trigger("hide.bs.select",a)},"hidden.bs.dropdown":function(a){b.$element.trigger("hidden.bs.select",a)},"show.bs.dropdown":function(a){b.$element.trigger("show.bs.select",a)},"shown.bs.dropdown":function(a){b.$element.trigger("shown.bs.select",a)}}),b.$element[0].hasAttribute("required")&&this.$element.on("invalid",function(){b.$button.addClass("bs-invalid").focus(),b.$element.on({"focus.bs.select":function(){b.$button.focus(),b.$element.off("focus.bs.select")},"shown.bs.select":function(){b.$element.val(b.$element.val()).off("shown.bs.select")},"rendered.bs.select":function(){this.validity.valid&&b.$button.removeClass("bs-invalid"),b.$element.off("rendered.bs.select")}})}),setTimeout(function(){b.$element.trigger("loaded.bs.select")})},createDropdown:function(){var b=this.multiple||this.options.showTick?" show-tick":"",d=this.$element.parent().hasClass("input-group")?" input-group-btn":"",e=this.autofocus?" autofocus":"",f=this.options.header?'<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>'+this.options.header+"</div>":"",g=this.options.liveSearch?'<div class="bs-searchbox"><input type="text" class="form-control" autocomplete="off"'+(null===this.options.liveSearchPlaceholder?"":' placeholder="'+c(this.options.liveSearchPlaceholder)+'"')+"></div>":"",h=this.multiple&&this.options.actionsBox?'<div class="bs-actionsbox"><div class="btn-group btn-group-sm btn-block"><button type="button" class="actions-btn bs-select-all btn btn-default">'+this.options.selectAllText+'</button><button type="button" class="actions-btn bs-deselect-all btn btn-default">'+this.options.deselectAllText+"</button></div></div>":"",i=this.multiple&&this.options.doneButton?'<div class="bs-donebutton"><div class="btn-group btn-block"><button type="button" class="btn btn-sm btn-default">'+this.options.doneButtonText+"</button></div></div>":"",j='<div class="btn-group bootstrap-select'+b+d+'"><button type="button" class="'+this.options.styleBase+' dropdown-toggle" data-toggle="dropdown"'+e+'><span class="filter-option pull-left"></span>&nbsp;<span class="bs-caret">'+this.options.template.caret+'</span></button><div class="dropdown-menu open">'+f+g+h+'<ul class="dropdown-menu inner" role="menu"></ul>'+i+"</div></div>";return a(j)},createView:function(){var a=this.createDropdown(),b=this.createLi();return a.find("ul")[0].innerHTML=b,a},reloadLi:function(){this.destroyLi();var a=this.createLi();this.$menuInner[0].innerHTML=a},destroyLi:function(){this.$menu.find("li").remove()},createLi:function(){var d=this,e=[],f=0,g=document.createElement("option"),h=-1,i=function(a,b,c,d){return"<li"+("undefined"!=typeof c&""!==c?' class="'+c+'"':"")+("undefined"!=typeof b&null!==b?' data-original-index="'+b+'"':"")+("undefined"!=typeof d&null!==d?'data-optgroup="'+d+'"':"")+">"+a+"</li>"},j=function(a,e,f,g){return'<a tabindex="0"'+("undefined"!=typeof e?' class="'+e+'"':"")+("undefined"!=typeof f?' style="'+f+'"':"")+(d.options.liveSearchNormalize?' data-normalized-text="'+b(c(a))+'"':"")+("undefined"!=typeof g||null!==g?' data-tokens="'+g+'"':"")+">"+a+'<span class="'+d.options.iconBase+" "+d.options.tickIcon+' check-mark"></span></a>'};if(this.options.title&&!this.multiple&&(h--,!this.$element.find(".bs-title-option").length)){var k=this.$element[0];g.className="bs-title-option",g.appendChild(document.createTextNode(this.options.title)),g.value="",k.insertBefore(g,k.firstChild),void 0===a(k.options[k.selectedIndex]).attr("selected")&&(g.selected=!0)}return this.$element.find("option").each(function(b){var c=a(this);if(h++,!c.hasClass("bs-title-option")){var g=this.className||"",k=this.style.cssText,l=c.data("content")?c.data("content"):c.html(),m=c.data("tokens")?c.data("tokens"):null,n="undefined"!=typeof c.data("subtext")?'<small class="text-muted">'+c.data("subtext")+"</small>":"",o="undefined"!=typeof c.data("icon")?'<span class="'+d.options.iconBase+" "+c.data("icon")+'"></span> ':"",p="OPTGROUP"===this.parentNode.tagName,q=this.disabled||p&&this.parentNode.disabled;if(""!==o&&q&&(o="<span>"+o+"</span>"),d.options.hideDisabled&&q&&!p)return void h--;if(c.data("content")||(l=o+'<span class="text">'+l+n+"</span>"),p&&c.data("divider")!==!0){var r=" "+this.parentNode.className||"";if(0===c.index()){f+=1;var s=this.parentNode.label,t="undefined"!=typeof c.parent().data("subtext")?'<small class="text-muted">'+c.parent().data("subtext")+"</small>":"",u=c.parent().data("icon")?'<span class="'+d.options.iconBase+" "+c.parent().data("icon")+'"></span> ':"";s=u+'<span class="text">'+s+t+"</span>",0!==b&&e.length>0&&(h++,e.push(i("",null,"divider",f+"div"))),h++,e.push(i(s,null,"dropdown-header"+r,f))}if(d.options.hideDisabled&&q)return void h--;e.push(i(j(l,"opt "+g+r,k,m),b,"",f))}else c.data("divider")===!0?e.push(i("",b,"divider")):c.data("hidden")===!0?e.push(i(j(l,g,k,m),b,"hidden is-hidden")):(this.previousElementSibling&&"OPTGROUP"===this.previousElementSibling.tagName&&(h++,e.push(i("",null,"divider",f+"div"))),e.push(i(j(l,g,k,m),b)));d.liObj[b]=h}}),this.multiple||0!==this.$element.find("option:selected").length||this.options.title||this.$element.find("option").eq(0).prop("selected",!0).attr("selected","selected"),e.join("")},findLis:function(){return null==this.$lis&&(this.$lis=this.$menu.find("li")),this.$lis},render:function(b){var c,d=this;b!==!1&&this.$element.find("option").each(function(a){var b=d.findLis().eq(d.liObj[a]);d.setDisabled(a,this.disabled||"OPTGROUP"===this.parentNode.tagName&&this.parentNode.disabled,b),d.setSelected(a,this.selected,b)}),this.tabIndex();var e=this.$element.find("option").map(function(){if(this.selected){if(d.options.hideDisabled&&(this.disabled||"OPTGROUP"===this.parentNode.tagName&&this.parentNode.disabled))return;var b,c=a(this),e=c.data("icon")&&d.options.showIcon?'<i class="'+d.options.iconBase+" "+c.data("icon")+'"></i> ':"";return b=d.options.showSubtext&&c.data("subtext")&&!d.multiple?' <small class="text-muted">'+c.data("subtext")+"</small>":"","undefined"!=typeof c.attr("title")?c.attr("title"):c.data("content")&&d.options.showContent?c.data("content"):e+c.html()+b}}).toArray(),f=this.multiple?e.join(this.options.multipleSeparator):e[0];if(this.multiple&&this.options.selectedTextFormat.indexOf("count")>-1){var g=this.options.selectedTextFormat.split(">");if(g.length>1&&e.length>g[1]||1==g.length&&e.length>=2){c=this.options.hideDisabled?", [disabled]":"";var h=this.$element.find("option").not('[data-divider="true"], [data-hidden="true"]'+c).length,i="function"==typeof this.options.countSelectedText?this.options.countSelectedText(e.length,h):this.options.countSelectedText;f=i.replace("{0}",e.length.toString()).replace("{1}",h.toString())}}void 0==this.options.title&&(this.options.title=this.$element.attr("title")),"static"==this.options.selectedTextFormat&&(f=this.options.title),f||(f="undefined"!=typeof this.options.title?this.options.title:this.options.noneSelectedText),this.$button.attr("title",a.trim(f.replace(/<[^>]*>?/g,""))),this.$button.children(".filter-option").html(f),this.$element.trigger("rendered.bs.select")},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,""));var c=a?a:this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(b){if(b||this.options.size!==!1&&!this.sizeInfo){var c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("ul"),f=document.createElement("li"),g=document.createElement("li"),h=document.createElement("a"),i=document.createElement("span"),j=this.options.header&&this.$menu.find(".popover-title").length>0?this.$menu.find(".popover-title")[0].cloneNode(!0):null,k=this.options.liveSearch?document.createElement("div"):null,l=this.options.actionsBox&&this.multiple&&this.$menu.find(".bs-actionsbox").length>0?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,m=this.options.doneButton&&this.multiple&&this.$menu.find(".bs-donebutton").length>0?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null;if(i.className="text",c.className=this.$menu[0].parentNode.className+" open",d.className="dropdown-menu open",e.className="dropdown-menu inner",f.className="divider",i.appendChild(document.createTextNode("Inner text")),h.appendChild(i),g.appendChild(h),e.appendChild(g),e.appendChild(f),j&&d.appendChild(j),k){var n=document.createElement("span");k.className="bs-searchbox",n.className="form-control",k.appendChild(n),d.appendChild(k)}l&&d.appendChild(l),d.appendChild(e),m&&d.appendChild(m),c.appendChild(d),document.body.appendChild(c);var o=h.offsetHeight,p=j?j.offsetHeight:0,q=k?k.offsetHeight:0,r=l?l.offsetHeight:0,s=m?m.offsetHeight:0,t=a(f).outerHeight(!0),u="function"==typeof getComputedStyle?getComputedStyle(d):!1,v=u?null:a(d),w=parseInt(u?u.paddingTop:v.css("paddingTop"))+parseInt(u?u.paddingBottom:v.css("paddingBottom"))+parseInt(u?u.borderTopWidth:v.css("borderTopWidth"))+parseInt(u?u.borderBottomWidth:v.css("borderBottomWidth")),x=w+parseInt(u?u.marginTop:v.css("marginTop"))+parseInt(u?u.marginBottom:v.css("marginBottom"))+2;document.body.removeChild(c),this.sizeInfo={liHeight:o,headerHeight:p,searchHeight:q,actionsHeight:r,doneButtonHeight:s,dividerHeight:t,menuPadding:w,menuExtras:x}}},setSize:function(){if(this.findLis(),this.liHeight(),this.options.header&&this.$menu.css("padding-top",0),this.options.size!==!1){var b,c,d,e,f=this,g=this.$menu,h=this.$menuInner,i=a(window),j=this.$newElement[0].offsetHeight,k=this.sizeInfo.liHeight,l=this.sizeInfo.headerHeight,m=this.sizeInfo.searchHeight,n=this.sizeInfo.actionsHeight,o=this.sizeInfo.doneButtonHeight,p=this.sizeInfo.dividerHeight,q=this.sizeInfo.menuPadding,r=this.sizeInfo.menuExtras,s=this.options.hideDisabled?".disabled":"",t=function(){d=f.$newElement.offset().top-i.scrollTop(),e=i.height()-d-j};if(t(),"auto"===this.options.size){var u=function(){var i,j=function(b,c){return function(d){return c?d.classList?d.classList.contains(b):a(d).hasClass(b):!(d.classList?d.classList.contains(b):a(d).hasClass(b))}},p=f.$menuInner[0].getElementsByTagName("li"),s=Array.prototype.filter?Array.prototype.filter.call(p,j("hidden",!1)):f.$lis.not(".hidden"),u=Array.prototype.filter?Array.prototype.filter.call(s,j("dropdown-header",!0)):s.filter(".dropdown-header");t(),b=e-r,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&f.$newElement.toggleClass("dropup",d>e&&c>b-r),f.$newElement.hasClass("dropup")&&(b=d-r),i=s.length+u.length>3?3*k+r-2:0,g.css({"max-height":b+"px",overflow:"hidden","min-height":i+l+m+n+o+"px"}),h.css({"max-height":b-l-m-n-o-q+"px","overflow-y":"auto","min-height":Math.max(i-q,0)+"px"})};u(),this.$searchbox.off("input.getSize propertychange.getSize").on("input.getSize propertychange.getSize",u),i.off("resize.getSize scroll.getSize").on("resize.getSize scroll.getSize",u)}else if(this.options.size&&"auto"!=this.options.size&&this.$lis.not(s).length>this.options.size){var v=this.$lis.not(".divider").not(s).children().slice(0,this.options.size).last().parent().index(),w=this.$lis.slice(0,v+1).filter(".divider").length;b=k*this.options.size+w*p+q,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&this.$newElement.toggleClass("dropup",d>e&&c>b-r),g.css({"max-height":b+l+m+n+o+"px",overflow:"hidden","min-height":""}),h.css({"max-height":b-q+"px","overflow-y":"auto","min-height":""})}}},setWidth:function(){if("auto"===this.options.width){this.$menu.css("min-width","0");var a=this.$menu.parent().clone().appendTo("body"),b=this.options.container?this.$newElement.clone().appendTo("body"):a,c=a.children(".dropdown-menu").outerWidth(),d=b.css("width","auto").children("button").outerWidth();a.remove(),b.remove(),this.$newElement.css("width",Math.max(c,d)+"px")}else"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width",""));this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement.removeClass("fit-width")},selectPosition:function(){this.$bsContainer=a('<div class="bs-container" />');var b,c,d=this,e=function(a){d.$bsContainer.addClass(a.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass("dropup",a.hasClass("dropup")),b=a.offset(),c=a.hasClass("dropup")?0:a[0].offsetHeight,d.$bsContainer.css({top:b.top+c,left:b.left,width:a[0].offsetWidth})};this.$button.on("click",function(){var b=a(this);d.isDisabled()||(e(d.$newElement),d.$bsContainer.appendTo(d.options.container).toggleClass("open",!b.hasClass("open")).append(d.$menu))}),a(window).on("resize scroll",function(){e(d.$newElement)}),this.$element.on("hide.bs.select",function(){d.$menu.data("height",d.$menu.height()),d.$bsContainer.detach()})},setSelected:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),c.toggleClass("selected",b)},setDisabled:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),b?c.addClass("disabled").children("a").attr("href","#").attr("tabindex",-1):c.removeClass("disabled").children("a").removeAttr("href").attr("tabindex",0)},isDisabled:function(){return this.$element[0].disabled},checkDisabled:function(){var a=this;this.isDisabled()?(this.$newElement.addClass("disabled"),this.$button.addClass("disabled").attr("tabindex",-1)):(this.$button.hasClass("disabled")&&(this.$newElement.removeClass("disabled"),this.$button.removeClass("disabled")),-1!=this.$button.attr("tabindex")||this.$element.data("tabindex")||this.$button.removeAttr("tabindex")),this.$button.click(function(){return!a.isDisabled()})},tabIndex:function(){this.$element.data("tabindex")!==this.$element.attr("tabindex")&&-98!==this.$element.attr("tabindex")&&"-98"!==this.$element.attr("tabindex")&&(this.$element.data("tabindex",this.$element.attr("tabindex")),this.$button.attr("tabindex",this.$element.data("tabindex"))),this.$element.attr("tabindex",-98)},clickListener:function(){var b=this,c=a(document);this.$newElement.on("touchstart.dropdown",".dropdown-menu",function(a){a.stopPropagation()}),c.data("spaceSelect",!1),this.$button.on("keyup",function(a){/(32)/.test(a.keyCode.toString(10))&&c.data("spaceSelect")&&(a.preventDefault(),c.data("spaceSelect",!1))}),this.$button.on("click",function(){b.setSize()}),this.$element.on("shown.bs.select",function(){if(b.options.liveSearch||b.multiple){if(!b.multiple){var a=b.liObj[b.$element[0].selectedIndex];if("number"!=typeof a||b.options.size===!1)return;var c=b.$lis.eq(a)[0].offsetTop-b.$menuInner[0].offsetTop;c=c-b.$menuInner[0].offsetHeight/2+b.sizeInfo.liHeight/2,b.$menuInner[0].scrollTop=c}}else b.$menuInner.find(".selected a").focus()}),this.$menuInner.on("click","li a",function(c){var d=a(this),e=d.parent().data("originalIndex"),f=b.$element.val(),g=b.$element.prop("selectedIndex");if(b.multiple&&c.stopPropagation(),c.preventDefault(),!b.isDisabled()&&!d.parent().hasClass("disabled")){var h=b.$element.find("option"),i=h.eq(e),j=i.prop("selected"),k=i.parent("optgroup"),l=b.options.maxOptions,m=k.data("maxOptions")||!1;if(b.multiple){if(i.prop("selected",!j),b.setSelected(e,!j),d.blur(),l!==!1||m!==!1){var n=l<h.filter(":selected").length,o=m<k.find("option:selected").length;if(l&&n||m&&o)if(l&&1==l)h.prop("selected",!1),i.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected"),b.setSelected(e,!0);else if(m&&1==m){k.find("option:selected").prop("selected",!1),i.prop("selected",!0);var p=d.parent().data("optgroup");b.$menuInner.find('[data-optgroup="'+p+'"]').removeClass("selected"),b.setSelected(e,!0)}else{var q="function"==typeof b.options.maxOptionsText?b.options.maxOptionsText(l,m):b.options.maxOptionsText,r=q[0].replace("{n}",l),s=q[1].replace("{n}",m),t=a('<div class="notify"></div>');q[2]&&(r=r.replace("{var}",q[2][l>1?0:1]),s=s.replace("{var}",q[2][m>1?0:1])),i.prop("selected",!1),b.$menu.append(t),l&&n&&(t.append(a("<div>"+r+"</div>")),b.$element.trigger("maxReached.bs.select")),m&&o&&(t.append(a("<div>"+s+"</div>")),b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(e,!1)},10),t.delay(750).fadeOut(300,function(){a(this).remove()})}}}else h.prop("selected",!1),i.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected"),b.setSelected(e,!0);b.multiple?b.options.liveSearch&&b.$searchbox.focus():b.$button.focus(),(f!=b.$element.val()&&b.multiple||g!=b.$element.prop("selectedIndex")&&!b.multiple)&&b.$element.trigger("changed.bs.select",[e,i.prop("selected"),j]).triggerNative("change")}}),this.$menu.on("click","li.disabled a, .popover-title, .popover-title :not(.close)",function(c){c.currentTarget==this&&(c.preventDefault(),c.stopPropagation(),b.options.liveSearch&&!a(c.target).hasClass("close")?b.$searchbox.focus():b.$button.focus())}),this.$menuInner.on("click",".divider, .dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click",".popover-title .close",function(){b.$button.click()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).hasClass("bs-select-all")?b.selectAll():b.deselectAll()}),this.$element.change(function(){b.render(!1)})},liveSearchListener:function(){var d=this,e=a('<li class="no-results"></li>');this.$button.on("click.dropdown.data-api touchstart.dropdown.data-api",function(){d.$menuInner.find(".active").removeClass("active"),d.$searchbox.val()&&(d.$searchbox.val(""),d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove()),d.multiple||d.$menuInner.find(".selected").addClass("active"),setTimeout(function(){d.$searchbox.focus()},10)}),this.$searchbox.on("click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){if(d.$searchbox.val()){var f=d.$lis.not(".is-hidden").removeClass("hidden").children("a");f=d.options.liveSearchNormalize?f.not(":a"+d._searchStyle()+'("'+b(d.$searchbox.val())+'")'):f.not(":"+d._searchStyle()+'("'+d.$searchbox.val()+'")'),f.parent().addClass("hidden"),d.$lis.filter(".dropdown-header").each(function(){var b=a(this),c=b.data("optgroup");0===d.$lis.filter("[data-optgroup="+c+"]").not(b).not(".hidden").length&&(b.addClass("hidden"),d.$lis.filter("[data-optgroup="+c+"div]").addClass("hidden"))});var g=d.$lis.not(".hidden");g.each(function(b){var c=a(this);c.hasClass("divider")&&(c.index()===g.first().index()||c.index()===g.last().index()||g.eq(b+1).hasClass("divider"))&&c.addClass("hidden")}),d.$lis.not(".hidden, .no-results").length?e.parent().length&&e.remove():(e.parent().length&&e.remove(),e.html(d.options.noneResultsText.replace("{0}",'"'+c(d.$searchbox.val())+'"')).show(),d.$menuInner.append(e))}else d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove();d.$lis.filter(".active").removeClass("active"),d.$searchbox.val()&&d.$lis.not(".hidden, .divider, .dropdown-header").eq(0).addClass("active").children("a").focus(),a(this).focus()})},_searchStyle:function(){var a={begins:"ibegins",startsWith:"ibegins"};return a[this.options.liveSearchStyle]||"icontains"},val:function(a){return"undefined"!=typeof a?(this.$element.val(a),this.render(),this.$element):this.$element.val()},changeAll:function(b){"undefined"==typeof b&&(b=!0),this.findLis();for(var c=this.$element.find("option"),d=this.$lis.not(".divider, .dropdown-header, .disabled, .hidden").toggleClass("selected",b),e=d.length,f=[],g=0;e>g;g++){var h=d[g].getAttribute("data-original-index");f[f.length]=c.eq(h)[0]}a(f).prop("selected",b),this.render(!1),this.$element.trigger("changed.bs.select").triggerNative("change")},selectAll:function(){return this.changeAll(!0)},deselectAll:function(){return this.changeAll(!1)},toggle:function(a){a=a||window.event,a&&a.stopPropagation(),this.$button.trigger("click")},keydown:function(c){var d,e,f,g,h,i,j,k,l,m=a(this),n=m.is("input")?m.parent().parent():m.parent(),o=n.data("this"),p=":not(.disabled, .hidden, .dropdown-header, .divider)",q={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"};if(o.options.liveSearch&&(n=m.parent().parent()),o.options.container&&(n=o.$menu),d=a("[role=menu] li",n),l=o.$newElement.hasClass("open"),!l&&(c.keyCode>=48&&c.keyCode<=57||c.keyCode>=96&&c.keyCode<=105||c.keyCode>=65&&c.keyCode<=90)&&(o.options.container?o.$button.trigger("click"):(o.setSize(),o.$menu.parent().addClass("open"),l=!0),o.$searchbox.focus()),o.options.liveSearch&&(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&0===o.$menu.find(".active").length&&(c.preventDefault(),o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus()),d=a("[role=menu] li"+p,n),m.val()||/(38|40)/.test(c.keyCode.toString(10))||0===d.filter(".active").length&&(d=o.$menuInner.find("li"),d=o.options.liveSearchNormalize?d.filter(":a"+o._searchStyle()+"("+b(q[c.keyCode])+")"):d.filter(":"+o._searchStyle()+"("+q[c.keyCode]+")"))),d.length){if(/(38|40)/.test(c.keyCode.toString(10)))e=d.index(d.find("a").filter(":focus").parent()),g=d.filter(p).first().index(),h=d.filter(p).last().index(),f=d.eq(e).nextAll(p).eq(0).index(),i=d.eq(e).prevAll(p).eq(0).index(),j=d.eq(f).prevAll(p).eq(0).index(),o.options.liveSearch&&(d.each(function(b){a(this).hasClass("disabled")||a(this).data("index",b)}),e=d.index(d.filter(".active")),g=d.first().data("index"),h=d.last().data("index"),f=d.eq(e).nextAll().eq(0).data("index"),i=d.eq(e).prevAll().eq(0).data("index"),j=d.eq(f).prevAll().eq(0).data("index")),k=m.data("prevIndex"),38==c.keyCode?(o.options.liveSearch&&e--,e!=j&&e>i&&(e=i),g>e&&(e=g),e==k&&(e=h)):40==c.keyCode&&(o.options.liveSearch&&e++,-1==e&&(e=0),e!=j&&f>e&&(e=f),e>h&&(e=h),e==k&&(e=g)),m.data("prevIndex",e),o.options.liveSearch?(c.preventDefault(),m.hasClass("dropdown-toggle")||(d.removeClass("active").eq(e).addClass("active").children("a").focus(),m.focus())):d.eq(e).children("a").focus();else if(!m.is("input")){var r,s,t=[];d.each(function(){a(this).hasClass("disabled")||a.trim(a(this).children("a").text().toLowerCase()).substring(0,1)==q[c.keyCode]&&t.push(a(this).index())}),r=a(document).data("keycount"),r++,a(document).data("keycount",r),s=a.trim(a(":focus").text().toLowerCase()).substring(0,1),s!=q[c.keyCode]?(r=1,a(document).data("keycount",r)):r>=t.length&&(a(document).data("keycount",0),r>t.length&&(r=1)),d.eq(t[r-1]).children("a").focus()}if((/(13|32)/.test(c.keyCode.toString(10))||/(^9$)/.test(c.keyCode.toString(10))&&o.options.selectOnTab)&&l){if(/(32)/.test(c.keyCode.toString(10))||c.preventDefault(),o.options.liveSearch)/(32)/.test(c.keyCode.toString(10))||(o.$menuInner.find(".active a").click(),m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){this.$lis=null,this.liObj={},this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var f=a.fn.selectpicker;a.fn.selectpicker=d,a.fn.selectpicker.Constructor=e,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=f,this},a(document).data("keycount",0).on("keydown.bs.select",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',e.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);d.call(b,b.data())})})}(a)});
//# sourceMappingURL=bootstrap-select.js.map //# sourceMappingURL=bootstrap-select.js.map
\ No newline at end of file
morpheus.DatasetUtil = function() { morpheus.DatasetUtil = function() {
}; };
morpheus.DatasetUtil.min = function(dataset) { morpheus.DatasetUtil.min = function(dataset, seriesIndex) {
seriesIndex = seriesIndex || 0;
var min = Number.MAX_VALUE; var min = Number.MAX_VALUE;
for (var i = 0, rows = dataset.getRowCount(); i < rows; i++) { for (var i = 0, rows = dataset.getRowCount(); i < rows; i++) {
for (var j = 0, columns = dataset.getColumnCount(); j < columns; j++) { for (var j = 0, columns = dataset.getColumnCount(); j < columns; j++) {
var d = dataset.getValue(i, j); var d = dataset.getValue(i, j, seriesIndex);
if (isNaN(d)) { if (isNaN(d)) {
continue; continue;
} }
...@@ -20,11 +21,12 @@ morpheus.DatasetUtil.transposedView = function(dataset) { ...@@ -20,11 +21,12 @@ morpheus.DatasetUtil.transposedView = function(dataset) {
return dataset instanceof morpheus.TransposedDatasetView ? dataset return dataset instanceof morpheus.TransposedDatasetView ? dataset
.getDataset() : new morpheus.TransposedDatasetView(dataset); .getDataset() : new morpheus.TransposedDatasetView(dataset);
}; };
morpheus.DatasetUtil.max = function(dataset) { morpheus.DatasetUtil.max = function(dataset, seriesIndex) {
seriesIndex = seriesIndex || 0;
var max = -Number.MAX_VALUE; var max = -Number.MAX_VALUE;
for (var i = 0, rows = dataset.getRowCount(); i < rows; i++) { for (var i = 0, rows = dataset.getRowCount(); i < rows; i++) {
for (var j = 0, columns = dataset.getColumnCount(); j < columns; j++) { for (var j = 0, columns = dataset.getColumnCount(); j < columns; j++) {
var d = dataset.getValue(i, j); var d = dataset.getValue(i, j, seriesIndex);
if (isNaN(d)) { if (isNaN(d)) {
continue; continue;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
morpheus.HeatMapElementCanvas = function(project) { morpheus.HeatMapElementCanvas = function (project) {
morpheus.AbstractCanvas.call(this, true); morpheus.AbstractCanvas.call(this, true);
this.colorScheme = null; this.colorScheme = null;
this.project = project; this.project = project;
...@@ -7,56 +7,56 @@ morpheus.HeatMapElementCanvas = function(project) { ...@@ -7,56 +7,56 @@ morpheus.HeatMapElementCanvas = function(project) {
this.columnPositions = new morpheus.Positions(); this.columnPositions = new morpheus.Positions();
this.rowPositions = new morpheus.Positions(); this.rowPositions = new morpheus.Positions();
this.lastPosition = { this.lastPosition = {
left : -1, left: -1,
right : -1, right: -1,
top : -1, top: -1,
bottom : -1 bottom: -1
}; };
project.getElementSelectionModel().on('selectionChanged', function() { project.getElementSelectionModel().on('selectionChanged', function () {
_this.repaint(); _this.repaint();
}); });
}; };
morpheus.HeatMapElementCanvas.GRID_COLOR = 'rgb(128,128,128)'; morpheus.HeatMapElementCanvas.GRID_COLOR = 'rgb(128,128,128)';
morpheus.HeatMapElementCanvas.prototype = { morpheus.HeatMapElementCanvas.prototype = {
drawGrid : true, drawGrid: true,
getColorScheme : function() { getColorScheme: function () {
return this.colorScheme; return this.colorScheme;
}, },
isDrawGrid : function() { isDrawGrid: function () {
return this.drawGrid; return this.drawGrid;
}, },
setDrawGrid : function(drawGrid) { setDrawGrid: function (drawGrid) {
this.drawGrid = drawGrid; this.drawGrid = drawGrid;
}, },
setColorScheme : function(colorScheme) { setColorScheme: function (colorScheme) {
this.colorScheme = colorScheme; this.colorScheme = colorScheme;
}, },
setDataset : function(dataset) { setDataset: function (dataset) {
this.dataset = dataset; this.dataset = dataset;
this.columnPositions.setLength(this.dataset.getColumnCount()); this.columnPositions.setLength(this.dataset.getColumnCount());
this.rowPositions.setLength(this.dataset.getRowCount()); this.rowPositions.setLength(this.dataset.getRowCount());
}, },
getColumnPositions : function() { getColumnPositions: function () {
return this.columnPositions; return this.columnPositions;
}, },
getRowPositions : function() { getRowPositions: function () {
return this.rowPositions; return this.rowPositions;
}, },
getPreferredSize : function(context) { getPreferredSize: function (context) {
var w = Math.ceil(this.columnPositions.getPosition(this.columnPositions var w = Math.ceil(this.columnPositions.getPosition(this.columnPositions
.getLength() - 1) .getLength() - 1)
+ this.columnPositions.getItemSize(this.columnPositions + this.columnPositions.getItemSize(this.columnPositions
.getLength() - 1)); .getLength() - 1));
var h = Math.ceil(this.rowPositions.getPosition(this.rowPositions var h = Math.ceil(this.rowPositions.getPosition(this.rowPositions
.getLength() - 1) .getLength() - 1)
+ this.rowPositions + this.rowPositions
.getItemSize(this.rowPositions.getLength() - 1)); .getItemSize(this.rowPositions.getLength() - 1));
return { return {
width : w, width: w,
height : h height: h
}; };
}, },
prePaint : function(clip, context) { prePaint: function (clip, context) {
var lastPosition = this.lastPosition; var lastPosition = this.lastPosition;
var columnPositions = this.columnPositions; var columnPositions = this.columnPositions;
var rowPositions = this.rowPositions; var rowPositions = this.rowPositions;
...@@ -65,8 +65,8 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -65,8 +65,8 @@ morpheus.HeatMapElementCanvas.prototype = {
var top = morpheus.Positions.getTop(clip, rowPositions); var top = morpheus.Positions.getTop(clip, rowPositions);
var bottom = morpheus.Positions.getBottom(clip, rowPositions); var bottom = morpheus.Positions.getBottom(clip, rowPositions);
if (this.invalid || left !== lastPosition.left if (this.invalid || left !== lastPosition.left
|| right !== lastPosition.right || top !== lastPosition.top || right !== lastPosition.right || top !== lastPosition.top
|| bottom !== lastPosition.bottom) { || bottom !== lastPosition.bottom) {
lastPosition.right = right; lastPosition.right = right;
lastPosition.left = left; lastPosition.left = left;
lastPosition.top = top; lastPosition.top = top;
...@@ -74,7 +74,7 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -74,7 +74,7 @@ morpheus.HeatMapElementCanvas.prototype = {
this.invalid = true; this.invalid = true;
} }
}, },
postPaint : function(clip, context) { postPaint: function (clip, context) {
// draw mouse over stuff // draw mouse over stuff
morpheus.CanvasUtil.resetTransform(context); morpheus.CanvasUtil.resetTransform(context);
var project = this.project; var project = this.project;
...@@ -83,33 +83,33 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -83,33 +83,33 @@ morpheus.HeatMapElementCanvas.prototype = {
var rowPositions = this.getRowPositions(); var rowPositions = this.getRowPositions();
var columnPositions = this.getColumnPositions(); var columnPositions = this.getColumnPositions();
if (project.getHoverColumnIndex() >= 0 if (project.getHoverColumnIndex() >= 0
|| project.getHoverRowIndex() >= 0) { || project.getHoverRowIndex() >= 0) {
var height = rowPositions var height = rowPositions
.getItemSize(project.getHoverColumnIndex()); .getItemSize(project.getHoverColumnIndex());
var width = columnPositions.getItemSize(project var width = columnPositions.getItemSize(project
.getHoverColumnIndex()); .getHoverColumnIndex());
var y = (project.getHoverRowIndex() === -1 ? rowPositions var y = (project.getHoverRowIndex() === -1 ? rowPositions
.getPosition(rowPositions.getLength() - 1) : rowPositions .getPosition(rowPositions.getLength() - 1) : rowPositions
.getPosition(project.getHoverRowIndex())); .getPosition(project.getHoverRowIndex()));
var x = (project.getHoverColumnIndex() === -1 ? columnPositions var x = (project.getHoverColumnIndex() === -1 ? columnPositions
.getPosition(0) : columnPositions.getPosition(project .getPosition(0) : columnPositions.getPosition(project
.getHoverColumnIndex())); .getHoverColumnIndex()));
if (project.getHoverColumnIndex() !== -1) { if (project.getHoverColumnIndex() !== -1) {
context.strokeRect(x - clip.x, 0, width, this context.strokeRect(x - clip.x, 0, width, this
.getUnscaledHeight()); .getUnscaledHeight());
} }
if (project.getHoverRowIndex() !== -1) { if (project.getHoverRowIndex() !== -1) {
context.strokeRect(0, y - clip.y, this.getUnscaledWidth(), context.strokeRect(0, y - clip.y, this.getUnscaledWidth(),
height); height);
} }
if (project.getHoverColumnIndex() !== -1 if (project.getHoverColumnIndex() !== -1
&& project.getHoverRowIndex() !== -1) { && project.getHoverRowIndex() !== -1) {
context.strokeStyle = 'black'; context.strokeStyle = 'black';
context.lineWidth = 3; context.lineWidth = 3;
context.strokeRect(x - clip.x + 1.5, y - clip.y + 1.5, context.strokeRect(x - clip.x + 1.5, y - clip.y + 1.5,
width - 1.5, height - 1.5); width - 1.5, height - 1.5);
} }
} }
var left = morpheus.Positions.getLeft(clip, columnPositions); var left = morpheus.Positions.getLeft(clip, columnPositions);
...@@ -121,20 +121,20 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -121,20 +121,20 @@ morpheus.HeatMapElementCanvas.prototype = {
// context.fillRect(0, 0, this.canvas.width, this.canvas.height); // context.fillRect(0, 0, this.canvas.width, this.canvas.height);
context.translate(-clip.x, -clip.y); context.translate(-clip.x, -clip.y);
var selectedElements = project.getElementSelectionModel() var selectedElements = project.getElementSelectionModel()
.getViewIndices(); .getViewIndices();
if (selectedElements != null) { if (selectedElements != null) {
selectedElements.forEach(function(id) { selectedElements.forEach(function (id) {
var rowIndex = id.getArray()[0]; var rowIndex = id.getArray()[0];
var columnIndex = id.getArray()[1]; var columnIndex = id.getArray()[1];
if (rowIndex >= top && rowIndex < bottom && columnIndex >= left if (rowIndex >= top && rowIndex < bottom && columnIndex >= left
&& columnIndex < right) { && columnIndex < right) {
var rowSize = rowPositions.getItemSize(rowIndex); var rowSize = rowPositions.getItemSize(rowIndex);
var py = rowPositions.getPosition(rowIndex); var py = rowPositions.getPosition(rowIndex);
var columnSize = columnPositions.getItemSize(columnIndex); var columnSize = columnPositions.getItemSize(columnIndex);
var px = columnPositions.getPosition(columnIndex); var px = columnPositions.getPosition(columnIndex);
context.strokeRect(px + 1.5, py + 1.5, columnSize - 1.5, context.strokeRect(px + 1.5, py + 1.5, columnSize - 1.5,
rowSize - 1.5); rowSize - 1.5);
} }
}); });
...@@ -158,23 +158,33 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -158,23 +158,33 @@ morpheus.HeatMapElementCanvas.prototype = {
// emptySelection = emptySelection && selectedColumnElements.size() == // emptySelection = emptySelection && selectedColumnElements.size() ==
// 0; // 0;
}, },
setElementDrawCallback : function(elementDrawCallback) { setElementDrawCallback: function (elementDrawCallback) {
this._elementDrawCallback = elementDrawCallback; this._elementDrawCallback = elementDrawCallback;
}, },
setDrawCallback : function(drawCallback) { draw: function (clip, context) {
this.drawCallback = drawCallback;
},
draw : function(clip, context) {
var columnPositions = this.columnPositions; var columnPositions = this.columnPositions;
var rowPositions = this.rowPositions; var rowPositions = this.rowPositions;
var left = morpheus.Positions.getLeft(clip, columnPositions); var left = morpheus.Positions.getLeft(clip, columnPositions);
var right = morpheus.Positions.getRight(clip, columnPositions); var right = morpheus.Positions.getRight(clip, columnPositions);
var top = morpheus.Positions.getTop(clip, rowPositions); var top = morpheus.Positions.getTop(clip, rowPositions);
var bottom = morpheus.Positions.getBottom(clip, rowPositions); var bottom = morpheus.Positions.getBottom(clip, rowPositions);
context.translate(-clip.x, -clip.y);
this._draw({left: left, right: right, top: top, bottom: bottom, context: context});
context.translate(clip.x, clip.y);
},
_draw: function (options) {
var left = options.left;
var right = options.right;
var top = options.top;
var bottom = options.bottom;
var context = options.context;
var dataset = this.dataset; var dataset = this.dataset;
var columnPositions = this.columnPositions;
var rowPositions = this.rowPositions;
// context.fillStyle = 'LightGrey'; // context.fillStyle = 'LightGrey';
// context.fillRect(0, 0, this.canvas.width, this.canvas.height); // context.fillRect(0, 0, this.canvas.width, this.canvas.height);
context.translate(-clip.x, -clip.y);
var colorScheme = this.colorScheme; var colorScheme = this.colorScheme;
var drawGrid = this.drawGrid; var drawGrid = this.drawGrid;
...@@ -197,19 +207,19 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -197,19 +207,19 @@ morpheus.HeatMapElementCanvas.prototype = {
var columnSize = columnPositions.getItemSize(column); var columnSize = columnPositions.getItemSize(column);
var px = columnPositions.getPosition(column); var px = columnPositions.getPosition(column);
context.fillStyle = colorScheme.getColor(row, column, dataset context.fillStyle = colorScheme.getColor(row, column, dataset
.getValue(row, column)); .getValue(row, column));
if (column === left) { // check if the color scheme for this if (column === left) { // check if the color scheme for this
// row is sizing // row is sizing
sizer = colorScheme.getSizer(); sizer = colorScheme.getSizer();
sizeBySeriesName = sizer.getSeriesName(); sizeBySeriesName = sizer.getSeriesName();
sizeBySeriesIndex = sizeBySeriesName != null ? seriesNameToIndex[sizeBySeriesName] sizeBySeriesIndex = sizeBySeriesName != null ? seriesNameToIndex[sizeBySeriesName]
: undefined; : undefined;
conditionSeriesIndices = []; conditionSeriesIndices = [];
conditions = colorScheme.getConditions().getConditions(); conditions = colorScheme.getConditions().getConditions();
for (var ci = 0, nconditions = conditions.length; ci < nconditions; ci++) { for (var ci = 0, nconditions = conditions.length; ci < nconditions; ci++) {
conditionSeriesIndices conditionSeriesIndices
.push(seriesNameToIndex[conditions[ci].series]); .push(seriesNameToIndex[conditions[ci].series]);
} }
} }
...@@ -217,7 +227,7 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -217,7 +227,7 @@ morpheus.HeatMapElementCanvas.prototype = {
var cellRowSize = rowSize; var cellRowSize = rowSize;
if (sizeBySeriesIndex !== undefined) { if (sizeBySeriesIndex !== undefined) {
var sizeByValue = dataset.getValue(row, column, var sizeByValue = dataset.getValue(row, column,
sizeBySeriesIndex); sizeBySeriesIndex);
if (!isNaN(sizeByValue)) { if (!isNaN(sizeByValue)) {
var f = sizer.valueToFraction(sizeByValue); var f = sizer.valueToFraction(sizeByValue);
var rowDiff = rowSize - rowSize * f; var rowDiff = rowSize - rowSize * f;
...@@ -230,7 +240,7 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -230,7 +240,7 @@ morpheus.HeatMapElementCanvas.prototype = {
for (var ci = 0, nconditions = conditions.length; ci < nconditions; ci++) { for (var ci = 0, nconditions = conditions.length; ci < nconditions; ci++) {
var cond = conditions[ci]; var cond = conditions[ci];
var condValue = dataset.getValue(row, column, var condValue = dataset.getValue(row, column,
conditionSeriesIndices[ci]); conditionSeriesIndices[ci]);
if (!isNaN(condValue) && cond.accept(condValue)) { if (!isNaN(condValue) && cond.accept(condValue)) {
condition = cond; condition = cond;
...@@ -240,17 +250,17 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -240,17 +250,17 @@ morpheus.HeatMapElementCanvas.prototype = {
} }
if (condition !== null) { if (condition !== null) {
context.fillRect(px, py + yoffset, columnSize, context.fillRect(px, py + yoffset, columnSize,
cellRowSize); cellRowSize);
// x and y are at center // x and y are at center
var x = px + cellRowSize / 2; var x = px + cellRowSize / 2;
var y = py + yoffset + columnSize / 2; var y = py + yoffset + columnSize / 2;
context.fillStyle = condition.color; context.fillStyle = condition.color;
morpheus.CanvasUtil.drawShape(context, condition.shape, morpheus.CanvasUtil.drawShape(context, condition.shape,
x, y, Math.min(columnSize, cellRowSize) / 4); x, y, Math.min(columnSize, cellRowSize) / 4);
context.fill(); context.fill();
} else { } else {
context.fillRect(px, py + yoffset, columnSize, context.fillRect(px, py + yoffset, columnSize,
cellRowSize); cellRowSize);
} }
} else { } else {
context.fillRect(px, py + yoffset, columnSize, cellRowSize); context.fillRect(px, py + yoffset, columnSize, cellRowSize);
...@@ -258,7 +268,7 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -258,7 +268,7 @@ morpheus.HeatMapElementCanvas.prototype = {
if (elementDrawCallback) { if (elementDrawCallback) {
elementDrawCallback(context, dataset, row, column, px, py, elementDrawCallback(context, dataset, row, column, px, py,
columnSize, rowSize); columnSize, rowSize);
} }
} }
} }
...@@ -279,22 +289,8 @@ morpheus.HeatMapElementCanvas.prototype = { ...@@ -279,22 +289,8 @@ morpheus.HeatMapElementCanvas.prototype = {
} }
} }
if (this.drawCallback) {
this.drawCallback({
context : context,
dataset : dataset,
top : top,
bottom : bottom,
left : left,
right : right,
rowPositions : rowPositions,
columnPositions : columnPositions,
project : this.project,
clip : clip
});
}
context.lineWidth = 1; context.lineWidth = 1;
context.translate(clip.x, clip.y);
} }
}; };
morpheus.Util.extend(morpheus.HeatMapElementCanvas, morpheus.AbstractCanvas); morpheus.Util.extend(morpheus.HeatMapElementCanvas, morpheus.AbstractCanvas);
morpheus.HeatMapOptions = function(controller) { morpheus.HeatMapOptions = function (controller) {
var items = [ var items = [
{ {
name : 'color_by', name: 'color_by',
required : true, required: true,
type : 'select', type: 'select',
options : [ '(None)' ].concat(morpheus.MetadataUtil options: ['(None)'].concat(morpheus.MetadataUtil
.getMetadataNames(controller.getProject() .getMetadataNames(controller.getProject()
.getFullDataset().getRowMetadata())), .getFullDataset().getRowMetadata())),
value : controller.heatmap.getColorScheme() value: controller.heatmap.getColorScheme()
.getSeparateColorSchemeForRowMetadataField() .getSeparateColorSchemeForRowMetadataField()
}, {
name: 'color_by_value',
required: true,
type: 'select',
options: []
}, {
name: 'load_predefined_scheme',
required: true,
type: 'select',
options: [{
name: '',
value: ''
}, {
name: 'relative',
value: 'gene'
}, { }, {
name : 'color_by_value', name: 'binary',
required : true, value: 'binary'
type : 'select',
options : []
}, { }, {
name : 'load_predefined_scheme', name: 'MAF',
required : true, value: 'MAF'
type : 'select',
options : [ {
name : '',
value : ''
}, {
name : 'relative',
value : 'gene'
}, {
name : 'binary',
value : 'binary'
}, {
name : 'MAF',
value : 'MAF'
}, {
name : 'fixed (-1, -0.5, 0.5, 1)',
value : 'wtcs'
}, {
name : 'fixed (-1.5, -0.1, 0.1, 1.5)',
value : 'cn'
}, {
name : 'fixed (-90, -80, 80, 90)',
value : '100scale2'
}, {
name : 'fixed (-90, 90)',
value : '100scale1'
} ]
}, { }, {
name : 'save_color_scheme', name: 'fixed (-1, -0.5, 0.5, 1)',
type : 'button' value: 'wtcs'
}, { }, {
name : 'load_color_scheme', name: 'fixed (-1.5, -0.1, 0.1, 1.5)',
type : 'file' value: 'cn'
} ]; }, {
name: 'fixed (-90, -80, 80, 90)',
value: '100scale2'
}, {
name: 'fixed (-90, 90)',
value: '100scale1'
}]
}, {
name: 'save_color_scheme',
type: 'button'
}, {
name: 'load_color_scheme',
type: 'file'
}];
if (controller.getProject().getFullDataset().getSeriesCount() > 1) { if (controller.getProject().getFullDataset().getSeriesCount() > 1) {
items.push({ items.push({
name : 'size_by', name: 'size_by',
required : true, required: true,
type : 'select', type: 'select',
options : [ '(None)' ].concat(morpheus.DatasetUtil options: ['(None)'].concat(morpheus.DatasetUtil
.getSeriesNames(controller.getProject().getFullDataset())) .getSeriesNames(controller.getProject().getFullDataset()))
}); });
items.push({ items.push({
name : 'size_by_minimum', name: 'size_by_minimum',
title : 'Size by minimum', title: 'Size by minimum',
required : true, required: true,
type : 'text', type: 'text',
col : 'col-xs-4' col: 'col-xs-4'
}); });
items.push({ items.push({
name : 'size_by_maximum', name: 'size_by_maximum',
title : 'Size by maximum', title: 'Size by maximum',
required : true, required: true,
type : 'text', type: 'text',
col : 'col-xs-4' col: 'col-xs-4'
}); });
items.push({ items.push({
name : 'conditional_rendering', name: 'conditional_rendering',
required : true, required: true,
type : 'button', type: 'button',
col : 'col-xs-4' col: 'col-xs-4'
}); });
} }
var displayItems = [ var displayItems = [
{ {
name : 'show_grid', name: 'show_grid',
required : true, required: true,
type : 'checkbox', type: 'checkbox',
value : controller.heatmap.isDrawGrid() value: controller.heatmap.isDrawGrid()
}, },
{ {
name : 'row_size', name: 'row_size',
required : true, required: true,
type : 'text', type: 'text',
col : 'col-xs-4', col: 'col-xs-4',
value : morpheus.Util.nf(controller.heatmap.getRowPositions() value: morpheus.Util.nf(controller.heatmap.getRowPositions()
.getSize()) .getSize())
}, },
{ {
name : 'column_size', name: 'column_size',
required : true, required: true,
type : 'text', type: 'text',
col : 'col-xs-4', col: 'col-xs-4',
value : morpheus.Util.nf(controller.heatmap value: morpheus.Util.nf(controller.heatmap
.getColumnPositions().getSize()) .getColumnPositions().getSize())
} ]; }];
if (controller.rowDendrogram) { if (controller.rowDendrogram) {
displayItems displayItems
.push({ .push({
name : 'row_dendrogram_line_thickness', name: 'row_dendrogram_line_thickness',
required : true, required: true,
type : 'text', type: 'text',
col : 'col-xs-4', col: 'col-xs-4',
value : morpheus.Util value: morpheus.Util
.nf(controller.rowDendrogram ? controller.rowDendrogram.lineWidth .nf(controller.rowDendrogram ? controller.rowDendrogram.lineWidth
: 1) : 1)
}); });
} }
if (controller.columnDendrogram) { if (controller.columnDendrogram) {
displayItems displayItems
.push({ .push({
name : 'column_dendrogram_line_thickness', name: 'column_dendrogram_line_thickness',
required : true, required: true,
type : 'text', type: 'text',
col : 'col-xs-4', col: 'col-xs-4',
value : morpheus.Util value: morpheus.Util
.nf(controller.columnDendrogram ? controller.columnDendrogram.lineWidth .nf(controller.columnDendrogram ? controller.columnDendrogram.lineWidth
: 1) : 1)
}); });
} }
displayItems.push({ displayItems.push({
name : 'info_window', name: 'info_window',
required : true, required: true,
type : 'select', type: 'select',
col : 'col-xs-4', col: 'col-xs-4',
options : [ { options: [{
name : 'Fixed To Top', name: 'Fixed To Top',
value : 0 value: 0
}, { }, {
name : 'New Window', name: 'New Window',
value : 1 value: 1
} ], }],
value : controller.tooltipMode value: controller.tooltipMode
}); });
displayItems.push({ displayItems.push({
name : 'inline_tooltip', name: 'inline_tooltip',
required : true, required: true,
type : 'checkbox', type: 'checkbox',
value : controller.options.inlineTooltip value: controller.options.inlineTooltip
}); });
var colorSchemeFormBuilder = new morpheus.FormBuilder(); var colorSchemeFormBuilder = new morpheus.FormBuilder();
_.each(items, function(item) { _.each(items, function (item) {
colorSchemeFormBuilder.append(item); colorSchemeFormBuilder.append(item);
}); });
var displayFormBuilder = new morpheus.FormBuilder(); var displayFormBuilder = new morpheus.FormBuilder();
_.each(displayItems, function(item) { _.each(displayItems, function (item) {
displayFormBuilder.append(item); displayFormBuilder.append(item);
}); });
var colorSchemeChooser = new morpheus.HeatMapColorSchemeChooser({ var colorSchemeChooser = new morpheus.HeatMapColorSchemeChooser({
showRelative : true showRelative: true
}); });
colorSchemeChooser.on('change', function() { var updatingSizer = false;
colorSchemeChooser.on('change', function () {
if (controller.heatmap.getColorScheme().getSizer if (controller.heatmap.getColorScheme().getSizer
&& controller.heatmap.getColorScheme().getSizer() != null) { && controller.heatmap.getColorScheme().getSizer() != null) {
colorSchemeFormBuilder.setValue('size_by', controller.heatmap colorSchemeFormBuilder.setValue('size_by', controller.heatmap
.getColorScheme().getSizer().getSeriesName()); .getColorScheme().getSizer().getSeriesName());
colorSchemeFormBuilder.setEnabled('size_by_minimum', colorSchemeFormBuilder.setEnabled('size_by_minimum',
controller.heatmap.getColorScheme().getSizer() controller.heatmap.getColorScheme().getSizer()
.getSeriesName() != null); .getSeriesName() != null);
colorSchemeFormBuilder.setEnabled('size_by_maximum', colorSchemeFormBuilder.setEnabled('size_by_maximum',
controller.heatmap.getColorScheme().getSizer() controller.heatmap.getColorScheme().getSizer()
.getSeriesName() != null); .getSeriesName() != null);
colorSchemeFormBuilder.setValue('size_by_minimum', if (!updatingSizer) {
colorSchemeFormBuilder.setValue('size_by_minimum',
controller.heatmap.getColorScheme().getSizer().getMin()); controller.heatmap.getColorScheme().getSizer().getMin());
colorSchemeFormBuilder.setValue('size_by_maximum', colorSchemeFormBuilder.setValue('size_by_maximum',
controller.heatmap.getColorScheme().getSizer().getMax()); controller.heatmap.getColorScheme().getSizer().getMax());
}
} }
// repaint the heat map when color scheme changes // repaint the heat map when color scheme changes
...@@ -187,59 +190,61 @@ morpheus.HeatMapOptions = function(controller) { ...@@ -187,59 +190,61 @@ morpheus.HeatMapOptions = function(controller) {
var options = []; var options = [];
var value = {}; var value = {};
var field = { var field = {
type : 'bootstrap-select', type: 'bootstrap-select',
name : isColumns ? 'column_annotations' : 'row_annotations', name: isColumns ? 'column_annotations' : 'row_annotations',
multiple : true, multiple: true,
value : value, value: value,
options : options, options: options,
toggle : true toggle: true
}; };
_.each(controller.getVisibleTrackNames(isColumns), function(name) { _.each(controller.getVisibleTrackNames(isColumns), function (name) {
value[name] = true; value[name] = true;
}); });
_.each(morpheus.MetadataUtil.getMetadataNames(isColumns ? controller _.each(morpheus.MetadataUtil.getMetadataNames(isColumns ? controller
.getProject().getFullDataset().getColumnMetadata() : controller .getProject().getFullDataset().getColumnMetadata() : controller
.getProject().getFullDataset().getRowMetadata()), .getProject().getFullDataset().getRowMetadata()),
function(name) { function (name) {
options.push(name); options.push(name);
}); });
return field; return field;
} }
var annotationsBuilder = new morpheus.FormBuilder(); var annotationsBuilder = new morpheus.FormBuilder();
annotationsBuilder.append(createMetadataField(false)); annotationsBuilder.append(createMetadataField(false));
annotationsBuilder.append(createMetadataField(true)); annotationsBuilder.append(createMetadataField(true));
function annotationsListener($select, isColumns) { function annotationsListener($select, isColumns) {
var names = []; var names = [];
_.each(controller.getVisibleTrackNames(isColumns), function(name) { _.each(controller.getVisibleTrackNames(isColumns), function (name) {
names.push(name); names.push(name);
}); });
var values = $select.val(); var values = $select.val();
var selectedNow = _.difference(values, names); var selectedNow = _.difference(values, names);
var unselectedNow = _.difference(names, values); var unselectedNow = _.difference(names, values);
var tracks = []; var tracks = [];
_.each(selectedNow, function(name) { _.each(selectedNow, function (name) {
tracks.push({ tracks.push({
name : name, name: name,
isColumns : isColumns, isColumns: isColumns,
visible : true visible: true
}); });
}); });
_.each(unselectedNow, function(name) { _.each(unselectedNow, function (name) {
tracks.push({ tracks.push({
name : name, name: name,
isColumns : isColumns, isColumns: isColumns,
visible : false visible: false
}); });
}); });
controller.setTrackVisibility(tracks); controller.setTrackVisibility(tracks);
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
} }
var $ca = annotationsBuilder.$form.find('[name=column_annotations]'); var $ca = annotationsBuilder.$form.find('[name=column_annotations]');
$ca.on('change', function(e) { $ca.on('change', function (e) {
annotationsListener($(this), true); annotationsListener($(this), true);
}); });
var $ra = annotationsBuilder.$form.find('[name=row_annotations]'); var $ra = annotationsBuilder.$form.find('[name=row_annotations]');
$ra.on('change', function(e) { $ra.on('change', function (e) {
annotationsListener($(this), false); annotationsListener($(this), false);
}); });
var annotationOptionsTabId = _.uniqueId('morpheus'); var annotationOptionsTabId = _.uniqueId('morpheus');
...@@ -247,48 +252,48 @@ morpheus.HeatMapOptions = function(controller) { ...@@ -247,48 +252,48 @@ morpheus.HeatMapOptions = function(controller) {
var displayOptionsTabId = _.uniqueId('morpheus'); var displayOptionsTabId = _.uniqueId('morpheus');
var $metadataDiv = $('<div class="tab-pane" id="' + annotationOptionsTabId var $metadataDiv = $('<div class="tab-pane" id="' + annotationOptionsTabId
+ '"></div>'); + '"></div>');
$metadataDiv.append($(annotationsBuilder.$form)); $metadataDiv.append($(annotationsBuilder.$form));
var $heatMapDiv = $('<div class="tab-pane active" id="' var $heatMapDiv = $('<div class="tab-pane active" id="'
+ heatMapOptionsTabId + '"></div>'); + heatMapOptionsTabId + '"></div>');
$heatMapDiv.append(colorSchemeChooser.$div); $heatMapDiv.append(colorSchemeChooser.$div);
$heatMapDiv.append($(colorSchemeFormBuilder.$form)); $heatMapDiv.append($(colorSchemeFormBuilder.$form));
var $displayDiv = $('<div class="tab-pane" id="' + displayOptionsTabId var $displayDiv = $('<div class="tab-pane" id="' + displayOptionsTabId
+ '"></div>'); + '"></div>');
$displayDiv.append($(displayFormBuilder.$form)); $displayDiv.append($(displayFormBuilder.$form));
displayFormBuilder.$form.find('[name=show_grid]').on('click', function(e) { displayFormBuilder.$form.find('[name=show_grid]').on('click', function (e) {
var grid = $(this).prop('checked'); var grid = $(this).prop('checked');
controller.heatmap.setDrawGrid(grid); controller.heatmap.setDrawGrid(grid);
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}); });
displayFormBuilder.$form.find('[name=inline_tooltip]').on('click', displayFormBuilder.$form.find('[name=inline_tooltip]').on('click',
function(e) { function (e) {
controller.options.inlineTooltip = $(this).prop('checked'); controller.options.inlineTooltip = $(this).prop('checked');
}); });
displayFormBuilder.$form.find('[name=row_size]').on( displayFormBuilder.$form.find('[name=row_size]').on(
'keyup', 'keyup',
_.debounce(function(e) { _.debounce(function (e) {
controller.heatmap.getRowPositions().setSize( controller.heatmap.getRowPositions().setSize(
parseFloat($(this).val())); parseFloat($(this).val()));
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}, 100)); }, 100));
displayFormBuilder.$form.find('[name=info_window]').on('change', displayFormBuilder.$form.find('[name=info_window]').on('change',
function(e) { function (e) {
controller.setTooltipMode(parseInt($(this).val())); controller.setTooltipMode(parseInt($(this).val()));
}); });
var $colorByValue = colorSchemeFormBuilder.$form var $colorByValue = colorSchemeFormBuilder.$form
.find('[name=color_by_value]'); .find('[name=color_by_value]');
var separateSchemesField = controller.heatmap.getColorScheme() var separateSchemesField = controller.heatmap.getColorScheme()
.getSeparateColorSchemeForRowMetadataField(); .getSeparateColorSchemeForRowMetadataField();
if (separateSchemesField != null) { if (separateSchemesField != null) {
$colorByValue.html(morpheus.Util.createOptions(morpheus.VectorUtil $colorByValue.html(morpheus.Util.createOptions(morpheus.VectorUtil
.createValueToIndexMap( .createValueToIndexMap(
controller.project.getFullDataset().getRowMetadata() controller.project.getFullDataset().getRowMetadata()
.getByName(separateSchemesField)).keys())); .getByName(separateSchemesField)).keys()));
} }
colorSchemeChooser.setColorScheme(controller.heatmap.getColorScheme()); colorSchemeChooser.setColorScheme(controller.heatmap.getColorScheme());
...@@ -296,81 +301,84 @@ morpheus.HeatMapOptions = function(controller) { ...@@ -296,81 +301,84 @@ morpheus.HeatMapOptions = function(controller) {
colorSchemeChooser.setCurrentValue($colorByValue.val()); colorSchemeChooser.setCurrentValue($colorByValue.val());
} }
if (controller.heatmap.getColorScheme().getSizer if (controller.heatmap.getColorScheme().getSizer
&& controller.heatmap.getColorScheme().getSizer() != null && controller.heatmap.getColorScheme().getSizer() != null
&& controller.heatmap.getColorScheme().getSizer().getSeriesName()) { && controller.heatmap.getColorScheme().getSizer().getSeriesName()) {
colorSchemeFormBuilder.setValue('size_by', controller.heatmap colorSchemeFormBuilder.setValue('size_by', controller.heatmap
.getColorScheme().getSizer().getSeriesName()); .getColorScheme().getSizer().getSeriesName());
} }
colorSchemeFormBuilder.$form.find('[name=size_by]') colorSchemeFormBuilder.$form.find('[name=size_by]')
.on( .on(
'change', 'change',
function(e) { function (e) {
var series = $(this).val(); var series = $(this).val();
if (series == '(None)') { if (series == '(None)') {
series = null; series = null;
} }
colorSchemeChooser.colorScheme.getSizer() colorSchemeChooser.colorScheme.getSizer()
.setSeriesName(series); .setSeriesName(series);
colorSchemeChooser.fireChanged(); colorSchemeChooser.fireChanged();
}); });
colorSchemeFormBuilder.$form.find('[name=size_by_minimum]').on( colorSchemeFormBuilder.$form.find('[name=size_by_minimum]').on(
'keyup', 'keyup',
_.debounce(function(e) { _.debounce(function (e) {
colorSchemeChooser.colorScheme.getSizer().setMax( updatingSizer = true;
parseFloat($(this).val())); colorSchemeChooser.colorScheme.getSizer().setMax(
colorSchemeChooser.fireChanged(); parseFloat($(this).val()));
colorSchemeChooser.fireChanged(true);
}, 100)); updatingSizer = false;
}, 100));
colorSchemeFormBuilder.$form.find('[name=size_by_maximum]').on(
'keyup',
_.debounce(function (e) {
updatingSizer = true;
colorSchemeChooser.colorScheme.getSizer().setMax(
parseFloat($(this).val()));
colorSchemeChooser.fireChanged(true);
updatingSizer = false;
}, 100));
colorSchemeFormBuilder.$form colorSchemeFormBuilder.$form
.find('[name=conditional_rendering]') .find('[name=conditional_rendering]')
.on( .on(
'click', 'click',
function(e) { function (e) {
e.preventDefault(); e.preventDefault();
var conditionalRenderingUI = new morpheus.ConditionalRenderingUI( var conditionalRenderingUI = new morpheus.ConditionalRenderingUI(
controller); controller);
morpheus.FormBuilder.showInModal({ morpheus.FormBuilder.showInModal({
title : 'Conditional Rendering', title: 'Conditional Rendering',
html : conditionalRenderingUI.$div, html: conditionalRenderingUI.$div,
close : 'Close', close: 'Close',
z : 1051, z: 1051,
callback : function() { callback: function () {
} }
}); });
}); });
colorSchemeFormBuilder.$form.find('[name=size_by_maximum]').on(
'keyup', colorSchemeFormBuilder.find('save_color_scheme').on('click', function (e) {
_.debounce(function(e) {
colorSchemeChooser.colorScheme.getSizer().setMax(
parseFloat($(this).val()));
colorSchemeChooser.fireChanged();
}, 100));
colorSchemeFormBuilder.find('save_color_scheme').on('click', function(e) {
e.preventDefault(); e.preventDefault();
var blob = new Blob([ controller.heatmap.getColorScheme().toJson() ], { var blob = new Blob([controller.heatmap.getColorScheme().toJson()], {
type : 'application/json' type: 'application/json'
}); });
saveAs(blob, 'color_scheme.json'); saveAs(blob, 'color_scheme.json');
}); });
colorSchemeFormBuilder.on('change', function(e) { colorSchemeFormBuilder.on('change', function (e) {
if (e.name === 'load_color_scheme') { if (e.name === 'load_color_scheme') {
if (e.value !== '' && e.value != null) { if (e.value !== '' && e.value != null) {
morpheus.Util.getText(e.value).done( morpheus.Util.getText(e.value).done(
function(text) { function (text) {
var json = JSON.parse($.trim(text)); var json = JSON.parse($.trim(text));
controller.heatmap.getColorScheme().fromJson(json); controller.heatmap.getColorScheme().fromJson(json);
colorSchemeChooser colorSchemeChooser
.setColorScheme(controller.heatmap .setColorScheme(controller.heatmap
.getColorScheme()); .getColorScheme());
controller.heatmap.setInvalid(true); controller.heatmap.setInvalid(true);
controller.heatmap.repaint(); controller.heatmap.repaint();
}).fail(function() { }).fail(function () {
morpheus.FormBuilder.showInModal({ morpheus.FormBuilder.showInModal({
title : 'Error', title: 'Error',
html : 'Unable to read saved color scheme.' html: 'Unable to read saved color scheme.'
}); });
}); });
...@@ -379,195 +387,195 @@ morpheus.HeatMapOptions = function(controller) { ...@@ -379,195 +387,195 @@ morpheus.HeatMapOptions = function(controller) {
}); });
colorSchemeFormBuilder.$form colorSchemeFormBuilder.$form
.on( .on(
'change', 'change',
'[name=load_predefined_scheme]', '[name=load_predefined_scheme]',
function(e) { function (e) {
var val = $(this).val(); var val = $(this).val();
if (val !== '') { if (val !== '') {
if (val === 'gene') { if (val === 'gene') {
controller.heatmap controller.heatmap
.getColorScheme() .getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier(morpheus.HeatMapColorScheme.Predefined .createColorSupplier(morpheus.HeatMapColorScheme.Predefined
.RELATIVE())); .RELATIVE()));
} else if (val === 'cn') { } else if (val === 'cn') {
controller.heatmap controller.heatmap
.getColorScheme() .getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier(morpheus.HeatMapColorScheme.Predefined .createColorSupplier(morpheus.HeatMapColorScheme.Predefined
.CN())); .CN()));
} else if (val === 'wtcs') { } else if (val === 'wtcs') {
controller.heatmap.getColorScheme() controller.heatmap.getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier({ .createColorSupplier({
type : 'fixed', type: 'fixed',
map : [ { map: [{
value : -1, value: -1,
color : 'blue' color: 'blue'
}, { }, {
value : -0.5, value: -0.5,
color : 'white' color: 'white'
}, { }, {
value : 0.5, value: 0.5,
color : 'white' color: 'white'
}, { }, {
value : 1, value: 1,
color : 'red' color: 'red'
} ] }]
})); }));
} else if (val === 'MAF') { } else if (val === 'MAF') {
controller.heatmap controller.heatmap
.getColorScheme() .getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier(morpheus.HeatMapColorScheme.Predefined .createColorSupplier(morpheus.HeatMapColorScheme.Predefined
.MAF())); .MAF()));
} else if (val === 'binary') { } else if (val === 'binary') {
controller.heatmap controller.heatmap
.getColorScheme() .getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier(morpheus.HeatMapColorScheme.Predefined .createColorSupplier(morpheus.HeatMapColorScheme.Predefined
.BINARY())); .BINARY()));
} else if (val === '100scale1') { } else if (val === '100scale1') {
controller.heatmap controller.heatmap
.getColorScheme() .getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier(morpheus.HeatMapColorScheme.Predefined .createColorSupplier(morpheus.HeatMapColorScheme.Predefined
.SUMMLY())); .SUMMLY()));
} else if (val === '100scale2') { } else if (val === '100scale2') {
controller.heatmap controller.heatmap
.getColorScheme() .getColorScheme()
.setColorSupplierForCurrentValue( .setColorSupplierForCurrentValue(
morpheus.HeatMapColorScheme morpheus.HeatMapColorScheme
.createColorSupplier(morpheus.HeatMapColorScheme.Predefined .createColorSupplier(morpheus.HeatMapColorScheme.Predefined
.SUMMLY2())); .SUMMLY2()));
} else { } else {
console.log('not found'); console.log('not found');
} }
colorSchemeChooser colorSchemeChooser
.setColorScheme(controller.heatmap .setColorScheme(controller.heatmap
.getColorScheme()); .getColorScheme());
controller.heatmap.setInvalid(true); controller.heatmap.setInvalid(true);
controller.heatmap.repaint(); controller.heatmap.repaint();
$(this).val(''); $(this).val('');
} else { } else {
console.log('empty option selected'); console.log('empty option selected');
} }
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}); });
colorSchemeFormBuilder.$form colorSchemeFormBuilder.$form
.find('[name=color_by]') .find('[name=color_by]')
.on( .on(
'change', 'change',
function(e) { function (e) {
var colorByField = $(this).val(); var colorByField = $(this).val();
if (colorByField == '(None)') { if (colorByField == '(None)') {
colorByField = null; colorByField = null;
} }
controller.heatmap.getColorScheme() controller.heatmap.getColorScheme()
.setSeparateColorSchemeForRowMetadataField( .setSeparateColorSchemeForRowMetadataField(
colorByField); colorByField);
if (colorByField != null) { if (colorByField != null) {
$colorByValue $colorByValue
.html(morpheus.Util .html(morpheus.Util
.createOptions(morpheus.VectorUtil .createOptions(morpheus.VectorUtil
.createValueToIndexMap( .createValueToIndexMap(
controller.project controller.project
.getFullDataset() .getFullDataset()
.getRowMetadata() .getRowMetadata()
.getByName( .getByName(
colorByField)) colorByField))
.keys())); .keys()));
} }
var colorByValue = $colorByValue.val(); var colorByValue = $colorByValue.val();
controller.heatmap.getColorScheme().setCurrentValue( controller.heatmap.getColorScheme().setCurrentValue(
colorByValue); colorByValue);
colorSchemeChooser.setCurrentValue(colorByValue); colorSchemeChooser.setCurrentValue(colorByValue);
controller.heatmap.setInvalid(true); controller.heatmap.setInvalid(true);
controller.heatmap.repaint(); controller.heatmap.repaint();
colorSchemeChooser.setColorScheme(controller.heatmap colorSchemeChooser.setColorScheme(controller.heatmap
.getColorScheme()); .getColorScheme());
}); });
$colorByValue.on('change', function(e) { $colorByValue.on('change', function (e) {
if (controller.heatmap.getColorScheme() if (controller.heatmap.getColorScheme()
.getSeparateColorSchemeForRowMetadataField() == null) { .getSeparateColorSchemeForRowMetadataField() == null) {
colorSchemeChooser.setCurrentValue(null); colorSchemeChooser.setCurrentValue(null);
controller.heatmap.getColorScheme().setCurrentValue(null); controller.heatmap.getColorScheme().setCurrentValue(null);
colorSchemeChooser.setColorScheme(controller.heatmap colorSchemeChooser.setColorScheme(controller.heatmap
.getColorScheme()); .getColorScheme());
} else { } else {
colorSchemeChooser.setCurrentValue($colorByValue.val()); colorSchemeChooser.setCurrentValue($colorByValue.val());
colorSchemeChooser.setColorScheme(controller.heatmap colorSchemeChooser.setColorScheme(controller.heatmap
.getColorScheme()); .getColorScheme());
} }
}); });
displayFormBuilder.$form.find('[name=column_size]').on( displayFormBuilder.$form.find('[name=column_size]').on(
'keyup', 'keyup',
_.debounce(function(e) { _.debounce(function (e) {
controller.heatmap.getColumnPositions().setSize( controller.heatmap.getColumnPositions().setSize(
parseFloat($(this).val())); parseFloat($(this).val()));
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}, 100)); }, 100));
displayFormBuilder.$form.find('[name=gap_size]').on('keyup', displayFormBuilder.$form.find('[name=gap_size]').on('keyup',
_.debounce(function(e) { _.debounce(function (e) {
controller.gapSize = parseFloat($(this).val()); controller.gapSize = parseFloat($(this).val());
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}, 100)); }, 100));
displayFormBuilder.$form.find('[name=squish_factor]').on('keyup', displayFormBuilder.$form.find('[name=squish_factor]').on('keyup',
_.debounce(function(e) { _.debounce(function (e) {
var f = parseFloat($(this).val()); var f = parseFloat($(this).val());
controller.heatmap.getColumnPositions().setSquishFactor(f); controller.heatmap.getColumnPositions().setSquishFactor(f);
controller.heatmap.getRowPositions().setSquishFactor(f); controller.heatmap.getRowPositions().setSquishFactor(f);
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}, 100)); }, 100));
displayFormBuilder.$form.find('[name=row_dendrogram_line_thickness]').on( displayFormBuilder.$form.find('[name=row_dendrogram_line_thickness]').on(
'keyup', _.debounce(function(e) { 'keyup', _.debounce(function (e) {
controller.rowDendrogram.lineWidth = parseFloat($(this).val()); controller.rowDendrogram.lineWidth = parseFloat($(this).val());
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}, 100)); }, 100));
displayFormBuilder.$form.find('[name=column_dendrogram_line_thickness]') displayFormBuilder.$form.find('[name=column_dendrogram_line_thickness]')
.on( .on(
'keyup', 'keyup',
_.debounce(function(e) { _.debounce(function (e) {
controller.columnDendrogram.lineWidth = parseFloat($( controller.columnDendrogram.lineWidth = parseFloat($(
this).val()); this).val());
controller.revalidate(); controller.revalidate();
colorSchemeChooser.restoreCurrentValue(); colorSchemeChooser.restoreCurrentValue();
}, 100)); }, 100));
var $tab = $('<div class="tab-content"></div>'); var $tab = $('<div class="tab-content"></div>');
$metadataDiv.appendTo($tab); $metadataDiv.appendTo($tab);
$heatMapDiv.appendTo($tab); $heatMapDiv.appendTo($tab);
$displayDiv.appendTo($tab); $displayDiv.appendTo($tab);
var $div = $('<div></div>'); var $div = $('<div></div>');
var $ul = $('<ul class="nav nav-tabs" role="tablist">' + '<li><a href="#' var $ul = $('<ul class="nav nav-tabs" role="tablist">' + '<li><a href="#'
+ annotationOptionsTabId + annotationOptionsTabId
+ '" role="tab" data-toggle="tab">Annotations</a></li>' + '" role="tab" data-toggle="tab">Annotations</a></li>'
+ '<li><a href="#' + heatMapOptionsTabId + '<li><a href="#' + heatMapOptionsTabId
+ '" role="tab" data-toggle="tab">Color Scheme</a></li>' + '" role="tab" data-toggle="tab">Color Scheme</a></li>'
+ '<li><a href="#' + displayOptionsTabId + '<li><a href="#' + displayOptionsTabId
+ '" role="tab" data-toggle="tab">Display</a></li>' + '</ul>'); + '" role="tab" data-toggle="tab">Display</a></li>' + '</ul>');
$ul.appendTo($div); $ul.appendTo($div);
$tab.appendTo($div); $tab.appendTo($div);
$ul.find('[role=tab]:eq(1)').tab('show'); $ul.find('[role=tab]:eq(1)').tab('show');
morpheus.FormBuilder.showInModal({ morpheus.FormBuilder.showInModal({
title : 'Options', title: 'Options',
html : $div, html: $div,
close : 'Close', close: 'Close',
callback : function() { callback: function () {
$div.find('input').off('keyup'); $div.find('input').off('keyup');
$ca.off('change'); $ca.off('change');
$ra.off('change'); $ra.off('change');
......
/** /**
* @param model{morpheus.SelectionModel} * @param model{morpheus.SelectionModel}
*/ */
morpheus.ScentedSearch = function(model, positions, isVertical, scrollbar, morpheus.ScentedSearch = function (model, positions, isVertical, scrollbar,
controller) { controller) {
morpheus.AbstractCanvas.call(this, false); morpheus.AbstractCanvas.call(this, false);
this.model = model; this.model = model;
this.positions = positions; this.positions = positions;
...@@ -12,41 +12,42 @@ morpheus.ScentedSearch = function(model, positions, isVertical, scrollbar, ...@@ -12,41 +12,42 @@ morpheus.ScentedSearch = function(model, positions, isVertical, scrollbar,
this.searchIndices = []; this.searchIndices = [];
scrollbar.decorator = this; scrollbar.decorator = this;
var _this = this; var _this = this;
var mouseMove = function(e) { var mouseMove = function (e) {
var index = _this.getIndex(e); var index = _this.getIndex(e);
_this.mouseMovedIndex = index; _this.mouseMovedIndex = index;
document.body.style.cursor = index < 0 ? 'default' : 'pointer'; document.body.style.cursor = index < 0 ? 'default' : 'pointer';
scrollbar.canvas.style.cursor = index < 0 ? 'default' : 'pointer'; scrollbar.canvas.style.cursor = index < 0 ? 'default' : 'pointer';
var tipOptions = { var tipOptions = {
event : e event: e,
dataLens: true
}; };
if (isVertical) { if (isVertical) {
controller.setToolTip(index >= 0 ? _this.searchIndices[index] : -1, controller.setToolTip(index >= 0 ? _this.searchIndices[index] : -1,
-1, tipOptions); -1, tipOptions);
} else { } else {
controller.setToolTip(-1, index >= 0 ? _this.searchIndices[index] controller.setToolTip(-1, index >= 0 ? _this.searchIndices[index]
: -1, tipOptions); : -1, tipOptions);
} }
}; };
var mouseExit = function(e) { var mouseExit = function (e) {
// need to set body cursor b/c mouse can be partially on the scroll bar, // need to set body cursor b/c mouse can be partially on the scroll bar,
// but the canvas cursor has no effect // but the canvas cursor has no effect
document.body.style.cursor = 'default'; document.body.style.cursor = 'default';
scrollbar.canvas.style.cursor = 'default'; scrollbar.canvas.style.cursor = 'default';
}; };
$(scrollbar.canvas).on('mousemove', mouseMove).on('mouseexit', mouseExit); $(scrollbar.canvas).on('mousemove', mouseMove).on('mouseout', mouseExit);
}; };
morpheus.ScentedSearch.LINE_HEIGHT = 3.5; morpheus.ScentedSearch.LINE_HEIGHT = 3.5;
morpheus.ScentedSearch.prototype = { morpheus.ScentedSearch.prototype = {
mouseMovedIndex : -1, mouseMovedIndex: -1,
getIndex : function(event) { getIndex: function (event) {
var pix = morpheus.CanvasUtil.getMousePos(event.target, event); var pix = morpheus.CanvasUtil.getMousePos(event.target, event);
var val = pix[this.isVertical ? 'y' : 'x']; var val = pix[this.isVertical ? 'y' : 'x'];
return this.getIndexForPix(val); return this.getIndexForPix(val);
}, },
getIndexForPix : function(pix) { getIndexForPix: function (pix) {
var indices = this.searchIndices; var indices = this.searchIndices;
if (indices == null) { if (indices == null) {
return -1; return -1;
...@@ -54,8 +55,8 @@ morpheus.ScentedSearch.prototype = { ...@@ -54,8 +55,8 @@ morpheus.ScentedSearch.prototype = {
var tolerance = morpheus.ScentedSearch.LINE_HEIGHT; var tolerance = morpheus.ScentedSearch.LINE_HEIGHT;
if (this.mouseMovedIndex > 0) { if (this.mouseMovedIndex > 0) {
var midVal = this.positions var midVal = this.positions
.getPosition(indices[this.mouseMovedIndex]) .getPosition(indices[this.mouseMovedIndex])
* scale; * scale;
if (Math.abs(midVal - pix) <= tolerance) { if (Math.abs(midVal - pix) <= tolerance) {
return this.mouseMovedIndex; return this.mouseMovedIndex;
} }
...@@ -85,71 +86,71 @@ morpheus.ScentedSearch.prototype = { ...@@ -85,71 +86,71 @@ morpheus.ScentedSearch.prototype = {
return -1; // -(low + 1); // key not found. return -1; // -(low + 1); // key not found.
}, },
tap : function(position) { tap: function (position) {
var val = position[this.isVertical ? 'y' : 'x']; var val = position[this.isVertical ? 'y' : 'x'];
var index = this.getIndexForPix(val); var index = this.getIndexForPix(val);
this.scrollbar.canvas.style.cursor = index < 0 ? 'default' : 'pointer'; this.scrollbar.canvas.style.cursor = index < 0 ? 'default' : 'pointer';
if (index >= 0) { if (index >= 0) {
if (this.isVertical) { if (this.isVertical) {
this.controller.scrollTop(this.positions this.controller.scrollTop(this.positions
.getPosition(this.searchIndices[index])); .getPosition(this.searchIndices[index]));
} else { } else {
this.controller.scrollLeft(this.positions this.controller.scrollLeft(this.positions
.getPosition(this.searchIndices[index])); .getPosition(this.searchIndices[index]));
} }
return true; return true;
} }
return false; return false;
}, },
update : function() { update: function () {
this.searchIndices = this.model.getViewIndices().values().sort( this.searchIndices = this.model.getViewIndices().values().sort(
function(a, b) { function (a, b) {
return a < b ? -1 : 1; return a < b ? -1 : 1;
}); });
}, },
draw : function(clip, context) { draw: function (clip, context) {
var width = this.scrollbar.getUnscaledWidth(); var width = this.scrollbar.getUnscaledWidth();
var height = this.scrollbar.getUnscaledHeight(); var height = this.scrollbar.getUnscaledHeight();
var availableLength = ((this.isVertical ? height : width)) var availableLength = ((this.isVertical ? height : width))
- morpheus.ScentedSearch.LINE_HEIGHT; - morpheus.ScentedSearch.LINE_HEIGHT;
this.scale = availableLength this.scale = availableLength
/ (this.positions.getPosition(this.positions.getLength() - 1) + this.positions / (this.positions.getPosition(this.positions.getLength() - 1) + this.positions
.getItemSize(this.positions.getLength() - 1)); .getItemSize(this.positions.getLength() - 1));
context.strokeStyle = 'rgb(106,137,177)'; context.strokeStyle = 'rgb(106,137,177)';
context.fillStyle = 'rgb(182,213,253)'; context.fillStyle = 'rgb(182,213,253)';
context.lineWidth = 1; context.lineWidth = 1;
this.drawIndices(context, this.searchIndices); this.drawIndices(context, this.searchIndices);
this.drawHoverMatchingValues(context); this.drawHoverMatchingValues(context);
}, },
drawHoverMatchingValues : function(context) { drawHoverMatchingValues: function (context) {
var heatmap = this.controller; var heatmap = this.controller;
context.fillStyle = 'black'; context.fillStyle = 'black';
if (heatmap.mousePositionOptions if (heatmap.mousePositionOptions
&& heatmap.mousePositionOptions.name != null) { && heatmap.mousePositionOptions.name != null) {
var isColumns = !this.isVertical; var isColumns = !this.isVertical;
var track = heatmap.getTrack(heatmap.mousePositionOptions.name, var track = heatmap.getTrack(heatmap.mousePositionOptions.name,
isColumns); isColumns);
if (track == null) { if (track == null) {
return; return;
} }
if (track.settings.highlightMatchingValues) { if (track.settings.highlightMatchingValues) {
var hoverIndex = isColumns ? heatmap.getProject() var hoverIndex = isColumns ? heatmap.getProject()
.getHoverColumnIndex() : heatmap.getProject() .getHoverColumnIndex() : heatmap.getProject()
.getHoverRowIndex(); .getHoverRowIndex();
if (hoverIndex === -1) { if (hoverIndex === -1) {
return; return;
} }
var vector = track.getVector(); var vector = track.getVector();
var value = vector.getValue(hoverIndex); var value = vector.getValue(hoverIndex);
var valueToModelIndices = track.getFullVector().getProperties() var valueToModelIndices = track.getFullVector().getProperties()
.get(morpheus.VectorKeys.VALUE_TO_INDICES); .get(morpheus.VectorKeys.VALUE_TO_INDICES);
if (!valueToModelIndices) { if (!valueToModelIndices) {
var fullVector = track.getFullVector(); var fullVector = track.getFullVector();
valueToModelIndices = morpheus.VectorUtil valueToModelIndices = morpheus.VectorUtil
.createValueToIndicesMap(fullVector); .createValueToIndicesMap(fullVector);
fullVector.getProperties().set( fullVector.getProperties().set(
morpheus.VectorKeys.VALUE_TO_INDICES, morpheus.VectorKeys.VALUE_TO_INDICES,
valueToModelIndices); valueToModelIndices);
} }
var modelIndices = valueToModelIndices.get(value); var modelIndices = valueToModelIndices.get(value);
...@@ -159,26 +160,26 @@ morpheus.ScentedSearch.prototype = { ...@@ -159,26 +160,26 @@ morpheus.ScentedSearch.prototype = {
} }
var scale = this.scale; var scale = this.scale;
var lineLength = !this.isVertical ? this.scrollbar var lineLength = !this.isVertical ? this.scrollbar
.getUnscaledHeight() : this.scrollbar .getUnscaledHeight() : this.scrollbar
.getUnscaledWidth(); .getUnscaledWidth();
var isVertical = this.isVertical; var isVertical = this.isVertical;
var positions = this.positions; var positions = this.positions;
var project = heatmap.getProject(); var project = heatmap.getProject();
for (var i = 0, length = modelIndices.length; i < length; i++) { for (var i = 0, length = modelIndices.length; i < length; i++) {
var modelIndex = modelIndices[i]; var modelIndex = modelIndices[i];
var index = isVertical ? project var index = isVertical ? project
.convertModelRowIndexToView(modelIndex) : project .convertModelRowIndexToView(modelIndex) : project
.convertModelColumnIndexToView(modelIndex); .convertModelColumnIndexToView(modelIndex);
if (index === -1) { if (index === -1) {
continue; continue;
} }
var pix = positions.getPosition(index) * scale; var pix = positions.getPosition(index) * scale;
if (isVertical) { if (isVertical) {
context.fillRect(0, pix, lineLength, context.fillRect(0, pix, lineLength,
morpheus.ScentedSearch.LINE_HEIGHT); morpheus.ScentedSearch.LINE_HEIGHT);
} else { } else {
context.fillRect(pix, 0, context.fillRect(pix, 0,
morpheus.ScentedSearch.LINE_HEIGHT, lineLength); morpheus.ScentedSearch.LINE_HEIGHT, lineLength);
} }
} }
...@@ -186,10 +187,10 @@ morpheus.ScentedSearch.prototype = { ...@@ -186,10 +187,10 @@ morpheus.ScentedSearch.prototype = {
} }
}, },
drawIndices : function(context, highlightedIndices) { drawIndices: function (context, highlightedIndices) {
var scale = this.scale; var scale = this.scale;
var lineLength = !this.isVertical ? this.scrollbar.getUnscaledHeight() var lineLength = !this.isVertical ? this.scrollbar.getUnscaledHeight()
: this.scrollbar.getUnscaledWidth(); : this.scrollbar.getUnscaledWidth();
var isVertical = this.isVertical; var isVertical = this.isVertical;
var positions = this.positions; var positions = this.positions;
...@@ -199,14 +200,14 @@ morpheus.ScentedSearch.prototype = { ...@@ -199,14 +200,14 @@ morpheus.ScentedSearch.prototype = {
if (isVertical) { if (isVertical) {
context.beginPath(); context.beginPath();
context.rect(0, pix, lineLength, context.rect(0, pix, lineLength,
morpheus.ScentedSearch.LINE_HEIGHT); morpheus.ScentedSearch.LINE_HEIGHT);
context.fill(); context.fill();
context.stroke(); context.stroke();
} else { } else {
context.beginPath(); context.beginPath();
context.rect(pix, 0, morpheus.ScentedSearch.LINE_HEIGHT, context.rect(pix, 0, morpheus.ScentedSearch.LINE_HEIGHT,
lineLength); lineLength);
context.fill(); context.fill();
context.stroke(); context.stroke();
} }
......
morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) { morpheus.VectorTrack = function (project, name, positions, isColumns, heatmap) {
morpheus.AbstractCanvas.call(this, true); morpheus.AbstractCanvas.call(this, true);
this.preferredSize = { this.preferredSize = {
width : 0, width: 0,
height : 0 height: 0
}; };
this.project = project; this.project = project;
this.positions = positions; this.positions = positions;
...@@ -14,17 +14,17 @@ morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) { ...@@ -14,17 +14,17 @@ morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) {
// this.highlightColor = 'rgb(255,255,0)'; // this.highlightColor = 'rgb(255,255,0)';
this.id = _.uniqueId(); this.id = _.uniqueId();
var _this = this; var _this = this;
this.updateSpanMapFunction = function() { this.updateSpanMapFunction = function () {
_this.spanMap = morpheus.VectorUtil.createSpanMap(_this.getVector()); _this.spanMap = morpheus.VectorUtil.createSpanMap(_this.getVector());
}; };
this.lastPosition = { this.lastPosition = {
start : -1, start: -1,
end : -1 end: -1
}; };
// for molecule span // for molecule span
this.events = 'rowSortOrderChanged rowFilterChanged datasetChanged'; this.events = 'rowSortOrderChanged rowFilterChanged datasetChanged';
var isTruncated = function(index) { var isTruncated = function (index) {
if (index !== -1) { if (index !== -1) {
var size = _this.positions.getItemSize(index); var size = _this.positions.getItemSize(index);
if (size < 6) { if (size < 6) {
...@@ -41,40 +41,40 @@ morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) { ...@@ -41,40 +41,40 @@ morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) {
} }
} }
}; };
var mouseMoved = function(event) { var mouseMoved = function (event) {
var index = -1; var index = -1;
if (event.type !== 'mouseout') { if (event.type !== 'mouseout') {
var position = morpheus.CanvasUtil.getMousePosWithScroll( var position = morpheus.CanvasUtil.getMousePosWithScroll(
event.target, event, heatmap.scrollLeft(), heatmap event.target, event, heatmap.scrollLeft(), heatmap
.scrollTop()); .scrollTop());
if (_this.settings.squished) { if (_this.settings.squished) {
var total = positions.getPosition(positions.getLength() - 1) var total = positions.getPosition(positions.getLength() - 1)
+ positions.getItemSize(positions.getLength() - 1); + positions.getItemSize(positions.getLength() - 1);
var squishFactor = total var squishFactor = total
/ (isColumns ? _this.getUnscaledWidth() : _this / (isColumns ? _this.getUnscaledWidth() : _this
.getUnscaledHeight()); .getUnscaledHeight());
position[isColumns ? 'x' : 'y'] *= squishFactor; position[isColumns ? 'x' : 'y'] *= squishFactor;
} }
index = !isColumns ? _this.positions.getIndex(position.y, false) index = !isColumns ? _this.positions.getIndex(position.y, false)
: _this.positions.getIndex(position.x, false); : _this.positions.getIndex(position.x, false);
} }
if (isColumns) { if (isColumns) {
heatmap.setMousePosition(-1, index, { heatmap.setMousePosition(-1, index, {
name : _this.name, name: _this.name,
event : event event: event
}); });
} else { } else {
heatmap.setMousePosition(index, -1, { heatmap.setMousePosition(index, -1, {
name : _this.name, name: _this.name,
event : event event: event
}); });
} }
}; };
$(this.canvas).on('contextmenu.morpheus', function(e) { $(this.canvas).on('contextmenu.morpheus', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
e.stopImmediatePropagation(); e.stopImmediatePropagation();
...@@ -89,49 +89,49 @@ morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) { ...@@ -89,49 +89,49 @@ morpheus.VectorTrack = function(project, name, positions, isColumns, heatmap) {
// - color and bar-discrete or contin // - color and bar-discrete or contin
// - color by for bar plots // - color by for bar plots
this.settings = { this.settings = {
maxTextWidth : undefined, maxTextWidth: undefined,
squished : false, squished: false,
inlineTooltip : false, inlineTooltip: false,
tooltip : true, tooltip: true,
discrete : true, // will be set automatically if discrete: true, // will be set automatically if
// discreteAutoDetermined is false // discreteAutoDetermined is false
highlightMatchingValues : false, highlightMatchingValues: false,
discreteAutoDetermined : false, discreteAutoDetermined: false,
colorBarSize : 12, colorBarSize: 12,
stackedBar : false, stackedBar: false,
renderMethod : {}, renderMethod: {},
selectionColor : 'rgb(182,213,253)', selectionColor: 'rgb(182,213,253)',
colorByField : null, // color this vector by another vector colorByField: null, // color this vector by another vector
barColor : '#bdbdbd', barColor: '#bdbdbd',
barSize : 40, barSize: 40,
arcSize : 60, arcSize: 60,
min : undefined, min: undefined,
mid : undefined, mid: undefined,
max : undefined, max: undefined,
minMaxReversed : false minMaxReversed: false
// whether to reverse min and max when auto-setting min and max // whether to reverse min and max when auto-setting min and max
}; };
$(this.canvas).on('mousemove.morpheus mouseout.morpheus', mouseMoved); $(this.canvas).on('mousemove.morpheus mouseout.morpheus', mouseMoved);
}; };
morpheus.VectorTrack.RENDER = { morpheus.VectorTrack.RENDER = {
TEXT : 0, TEXT: 0,
COLOR : 1, COLOR: 1,
BAR : 2, BAR: 2,
MOLECULE : 3, MOLECULE: 3,
TEXT_AND_COLOR : 4, TEXT_AND_COLOR: 4,
SHAPE : 5, SHAPE: 5,
ARC : 6, ARC: 6,
BOX_PLOT : 7 BOX_PLOT: 7
}; };
morpheus.VectorTrack.vectorToString = function(vector) { morpheus.VectorTrack.vectorToString = function (vector) {
var formatter = function(v) { var formatter = function (v) {
return '' + v; return '' + v;
}; };
var dataType = morpheus.VectorUtil.getDataType(vector); var dataType = morpheus.VectorUtil.getDataType(vector);
if (dataType === 'number') { if (dataType === 'number') {
formatter = morpheus.Util.nf; formatter = morpheus.Util.nf;
} else if (dataType === '[number]') { } else if (dataType === '[number]') {
formatter = function(v) { formatter = function (v) {
var s = []; var s = [];
if (v != null) { if (v != null) {
for (var i = 0, arrayLength = v.length; i < arrayLength; i++) { for (var i = 0, arrayLength = v.length; i < arrayLength; i++) {
...@@ -141,7 +141,7 @@ morpheus.VectorTrack.vectorToString = function(vector) { ...@@ -141,7 +141,7 @@ morpheus.VectorTrack.vectorToString = function(vector) {
return s.join(', '); return s.join(', ');
}; };
} else if (dataType === '[string]') { } else if (dataType === '[string]') {
formatter = function(v) { formatter = function (v) {
var s = []; var s = [];
if (v != null) { if (v != null) {
for (var i = 0, arrayLength = v.length; i < arrayLength; i++) { for (var i = 0, arrayLength = v.length; i < arrayLength; i++) {
...@@ -155,7 +155,7 @@ morpheus.VectorTrack.vectorToString = function(vector) { ...@@ -155,7 +155,7 @@ morpheus.VectorTrack.vectorToString = function(vector) {
}; };
morpheus.VectorTrack.prototype = { morpheus.VectorTrack.prototype = {
settingFromConfig : function(conf) { settingFromConfig: function (conf) {
var settings = this.settings; var settings = this.settings;
if (_.isString(conf)) { if (_.isString(conf)) {
settings.renderMethod = {}; settings.renderMethod = {};
...@@ -194,56 +194,56 @@ morpheus.VectorTrack.prototype = { ...@@ -194,56 +194,56 @@ morpheus.VectorTrack.prototype = {
this._update(); this._update();
}, },
isDiscrete : function() { isDiscrete: function () {
return this.settings.discrete; return this.settings.discrete;
}, },
setShowTooltip : function(value) { setShowTooltip: function (value) {
this.settings.tooltip = value; this.settings.tooltip = value;
}, },
isShowTooltip : function() { isShowTooltip: function () {
return this.settings.tooltip; return this.settings.tooltip;
}, },
isRenderAs : function(value) { isRenderAs: function (value) {
return this.settings.renderMethod[value]; return this.settings.renderMethod[value];
}, },
dispose : function() { dispose: function () {
morpheus.AbstractCanvas.prototype.dispose.call(this); morpheus.AbstractCanvas.prototype.dispose.call(this);
$(this.canvas).off( $(this.canvas).off(
'contextmenu.morpheus mousemove.morpheus mouseout.morpheus'); 'contextmenu.morpheus mousemove.morpheus mouseout.morpheus');
this.project.off(this.events, this.updateSpanMapFunction); this.project.off(this.events, this.updateSpanMapFunction);
}, },
getName : function() { getName: function () {
return this.name; return this.name;
}, },
getVector : function(name) { getVector: function (name) {
name = name == null ? this.name : name; name = name == null ? this.name : name;
var vector = this.isColumns ? this.project.getSortedFilteredDataset() var vector = this.isColumns ? this.project.getSortedFilteredDataset()
.getColumnMetadata().getByName(name) : this.project .getColumnMetadata().getByName(name) : this.project
.getSortedFilteredDataset().getRowMetadata().getByName(name); .getSortedFilteredDataset().getRowMetadata().getByName(name);
return !vector ? new morpheus.Vector(name, 0) : vector; return !vector ? new morpheus.Vector(name, 0) : vector;
}, },
getFullVector : function() { getFullVector: function () {
var vector = this.isColumns ? this.project.getFullDataset() var vector = this.isColumns ? this.project.getFullDataset()
.getColumnMetadata().getByName(this.name) : this.project .getColumnMetadata().getByName(this.name) : this.project
.getFullDataset().getRowMetadata().getByName(this.name); .getFullDataset().getRowMetadata().getByName(this.name);
return !vector ? new morpheus.Vector(this.name, 0) : vector; return !vector ? new morpheus.Vector(this.name, 0) : vector;
}, },
_updatePreferredSize : function() { _updatePreferredSize: function () {
var size = this._computePreferredSize(); var size = this._computePreferredSize();
this.preferredSize.width = size.width; this.preferredSize.width = size.width;
this.preferredSize.height = size.height; this.preferredSize.height = size.height;
}, },
_computePreferredSize : function(forPrint) { _computePreferredSize: function (forPrint) {
var width = 0; var width = 0;
var height = 0; var height = 0;
if (this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT) if (this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)) { || this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)) {
if (this.positions.getSize() >= 6) { if (this.positions.getSize() >= 6) {
var context = this.canvas.getContext('2d'); var context = this.canvas.getContext('2d');
var textWidth = morpheus.CanvasUtil.getVectorStringWidth( var textWidth = morpheus.CanvasUtil.getVectorStringWidth(
context, this.getVector(), this.positions, context, this.getVector(), this.positions,
forPrint ? -1 : (this.isColumns ? 120 : 100)); forPrint ? -1 : (this.isColumns ? 120 : 100));
if (!forPrint) { if (!forPrint) {
textWidth = Math.min(textWidth, this.isColumns ? 100 : 500); textWidth = Math.min(textWidth, this.isColumns ? 100 : 500);
this.settings.maxTextWidth = textWidth; this.settings.maxTextWidth = textWidth;
...@@ -284,21 +284,21 @@ morpheus.VectorTrack.prototype = { ...@@ -284,21 +284,21 @@ morpheus.VectorTrack.prototype = {
} }
width = Math.max(0, width); width = Math.max(0, width);
return this.isColumns ? { return this.isColumns ? {
width : height, width: height,
height : width height: width
} : { } : {
width : width, width: width,
height : height height: height
}; };
}, },
getPreferredSize : function() { getPreferredSize: function () {
return this.preferredSize; return this.preferredSize;
}, },
getPrintSize : function() { getPrintSize: function () {
return this._computePreferredSize(true); return this._computePreferredSize(true);
}, },
_createDiscreteValueMap : function() { _createDiscreteValueMap: function () {
var values = morpheus.VectorUtil.getValues(this.getFullVector()); var values = morpheus.VectorUtil.getValues(this.getFullVector());
values.sort(morpheus.SortKey.ASCENDING_COMPARATOR); values.sort(morpheus.SortKey.ASCENDING_COMPARATOR);
this.discreteValueMap = new morpheus.Map(); this.discreteValueMap = new morpheus.Map();
...@@ -309,17 +309,17 @@ morpheus.VectorTrack.prototype = { ...@@ -309,17 +309,17 @@ morpheus.VectorTrack.prototype = {
this.settings.mid = 0; this.settings.mid = 0;
this.settings.max = values.length; this.settings.max = values.length;
}, },
_setChartMinMax : function() { _setChartMinMax: function () {
if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) { || this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) {
if (!this.settings.stackedBar && this.settings.discrete if (!this.settings.stackedBar && this.settings.discrete
&& !this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) { && !this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) {
if (!this.discreteValueMap) { if (!this.discreteValueMap) {
this._createDiscreteValueMap(); this._createDiscreteValueMap();
} }
} else { } else {
if (this.settings.min == null || this.settings.max == null if (this.settings.min == null || this.settings.max == null
|| this.settings.mid == null) { || this.settings.mid == null) {
var vector = this.getFullVector(); var vector = this.getFullVector();
var minMax = morpheus.VectorUtil.getMinMax(vector); var minMax = morpheus.VectorUtil.getMinMax(vector);
var min = minMax.min; var min = minMax.min;
...@@ -337,7 +337,7 @@ morpheus.VectorTrack.prototype = { ...@@ -337,7 +337,7 @@ morpheus.VectorTrack.prototype = {
} }
if (this.settings.mid == null) { if (this.settings.mid == null) {
this.settings.mid = this.settings.min < 0 ? 0 this.settings.mid = this.settings.min < 0 ? 0
: this.settings.min; : this.settings.min;
} }
} }
...@@ -345,14 +345,14 @@ morpheus.VectorTrack.prototype = { ...@@ -345,14 +345,14 @@ morpheus.VectorTrack.prototype = {
} }
}, },
_update : function() { _update: function () {
if (!this.settings.discreteAutoDetermined if (!this.settings.discreteAutoDetermined
&& (this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR) && (this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR) || this || this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR) || this
.isRenderAs(morpheus.VectorTrack.RENDER.BAR))) { .isRenderAs(morpheus.VectorTrack.RENDER.BAR))) {
if (this.getFullVector().getProperties().has( if (this.getFullVector().getProperties().has(
morpheus.VectorKeys.FIELDS) morpheus.VectorKeys.FIELDS)
|| morpheus.VectorUtil.getDataType(this.getFullVector()) === 'number') { || morpheus.VectorUtil.getDataType(this.getFullVector()) === 'number') {
this.settings.discrete = false; this.settings.discrete = false;
this.settings.highlightMatchingValues = false; this.settings.highlightMatchingValues = false;
} }
...@@ -369,53 +369,53 @@ morpheus.VectorTrack.prototype = { ...@@ -369,53 +369,53 @@ morpheus.VectorTrack.prototype = {
var _this = this; var _this = this;
var valueToModelIndices = this.getFullVector().getProperties() var valueToModelIndices = this.getFullVector().getProperties()
.get(morpheus.VectorKeys.VALUE_TO_INDICES); .get(morpheus.VectorKeys.VALUE_TO_INDICES);
if (!valueToModelIndices) { if (!valueToModelIndices) {
var fullVector = this.getFullVector(); var fullVector = this.getFullVector();
valueToModelIndices = morpheus.VectorUtil valueToModelIndices = morpheus.VectorUtil
.createValueToIndicesMap(fullVector); .createValueToIndicesMap(fullVector);
fullVector.getProperties().set( fullVector.getProperties().set(
morpheus.VectorKeys.VALUE_TO_INDICES, morpheus.VectorKeys.VALUE_TO_INDICES,
valueToModelIndices); valueToModelIndices);
} }
if (_this.heatmap.options.structureUrlProvider !== undefined) { if (_this.heatmap.options.structureUrlProvider !== undefined) {
valueToModelIndices.forEach(function(indices, value) { valueToModelIndices.forEach(function (indices, value) {
var url = _this.heatmap.options var url = _this.heatmap.options
.structureUrlProvider(value); .structureUrlProvider(value);
var image = new Image(); var image = new Image();
image.src = url; image.src = url;
_this.moleculeCache[value] = image; _this.moleculeCache[value] = image;
}); });
setTimeout(2000, function() { setTimeout(2000, function () {
_this.setInvalid(true); _this.setInvalid(true);
_this.repaint(); _this.repaint();
}); });
} else { } else {
var values = valueToModelIndices.keys(); var values = valueToModelIndices.keys();
var doRequest = function(smile) { var doRequest = function (smile) {
$ $
.ajax( .ajax(
{ {
contentType : 'text/plain', contentType: 'text/plain',
context : { context: {
smile : smile smile: smile
}, },
data : { data: {
'string' : smile, 'string': smile,
'representation' : 'sdf' 'representation': 'sdf'
}, },
url : 'http://cactus.nci.nih.gov/chemical/structure', url: 'http://cactus.nci.nih.gov/chemical/structure',
}).done(function(text) { }).done(function (text) {
_this.moleculeCache[this.smile] = text; _this.moleculeCache[this.smile] = text;
if (values.length > 0) { if (values.length > 0) {
doRequest(values.pop()); doRequest(values.pop());
} }
_this.invalid = true; _this.invalid = true;
_this.repaint(); _this.repaint();
}); });
}; };
for (var i = 0; i < 6; i++) { for (var i = 0; i < 6; i++) {
doRequest(values.pop()); doRequest(values.pop());
...@@ -426,7 +426,8 @@ morpheus.VectorTrack.prototype = { ...@@ -426,7 +426,8 @@ morpheus.VectorTrack.prototype = {
} }
this._updatePreferredSize(); this._updatePreferredSize();
}, },
postPaint : function(clip, context) { postPaint: function (clip, context) {
// draw hover, matching values
context.lineWidth = 1; context.lineWidth = 1;
context.strokeStyle = 'Grey'; context.strokeStyle = 'Grey';
var project = this.project; var project = this.project;
...@@ -439,40 +440,40 @@ morpheus.VectorTrack.prototype = { ...@@ -439,40 +440,40 @@ morpheus.VectorTrack.prototype = {
if (this.isColumns) { if (this.isColumns) {
if (project.getHoverColumnIndex() !== -1) { if (project.getHoverColumnIndex() !== -1) {
this.drawColumnBorder(context, this.positions, project this.drawColumnBorder(context, this.positions, project
.getHoverColumnIndex(), this.getUnscaledHeight()); .getHoverColumnIndex(), this.getUnscaledHeight());
} }
} else { } else {
if (project.getHoverRowIndex() !== -1) { if (project.getHoverRowIndex() !== -1) {
this.drawRowBorder(context, this.positions, project this.drawRowBorder(context, this.positions, project
.getHoverRowIndex(), this.getUnscaledWidth()); .getHoverRowIndex(), this.getUnscaledWidth());
} }
} }
this._highlightMatchingValues(context, vector, start, end); this._highlightMatchingValues(context, vector, start, end);
}, },
_highlightMatchingValues : function(context, viewVector, start, end) { _highlightMatchingValues: function (context, viewVector, start, end) {
var project = this.project; var project = this.project;
var positions = this.positions; var positions = this.positions;
context.strokeStyle = 'black'; context.strokeStyle = 'black';
context.lineWidth = 3; context.lineWidth = 3;
var hoverIndex = this.isColumns ? project.getHoverColumnIndex() var hoverIndex = this.isColumns ? project.getHoverColumnIndex()
: project.getHoverRowIndex(); : project.getHoverRowIndex();
var value = viewVector.getValue(hoverIndex); var value = viewVector.getValue(hoverIndex);
if (this.settings.highlightMatchingValues if (this.settings.highlightMatchingValues
&& hoverIndex !== -1 && hoverIndex !== -1
&& this.heatmap.mousePositionOptions && this.heatmap.mousePositionOptions
&& this.heatmap.mousePositionOptions.name === viewVector && this.heatmap.mousePositionOptions.name === viewVector
.getName()) { .getName()) {
var valueToModelIndices = this.getFullVector().getProperties().get( var valueToModelIndices = this.getFullVector().getProperties().get(
morpheus.VectorKeys.VALUE_TO_INDICES); morpheus.VectorKeys.VALUE_TO_INDICES);
if (!valueToModelIndices) { if (!valueToModelIndices) {
var fullVector = this.getFullVector(); var fullVector = this.getFullVector();
valueToModelIndices = morpheus.VectorUtil valueToModelIndices = morpheus.VectorUtil
.createValueToIndicesMap(fullVector); .createValueToIndicesMap(fullVector);
fullVector.getProperties().set( fullVector.getProperties().set(
morpheus.VectorKeys.VALUE_TO_INDICES, morpheus.VectorKeys.VALUE_TO_INDICES,
valueToModelIndices); valueToModelIndices);
} }
var indices = valueToModelIndices.get(value); var indices = valueToModelIndices.get(value);
...@@ -490,7 +491,7 @@ morpheus.VectorTrack.prototype = { ...@@ -490,7 +491,7 @@ morpheus.VectorTrack.prototype = {
context.beginPath(); context.beginPath();
for (var i = 0, nindices = indices.length; i < nindices; i++) { for (var i = 0, nindices = indices.length; i < nindices; i++) {
var viewIndex = project var viewIndex = project
.convertModelColumnIndexToView(indices[i]); .convertModelColumnIndexToView(indices[i]);
if (viewIndex >= start && viewIndex < end) { if (viewIndex >= start && viewIndex < end) {
var size = positions.getItemSize(viewIndex); var size = positions.getItemSize(viewIndex);
var pix = positions.getPosition(viewIndex); var pix = positions.getPosition(viewIndex);
...@@ -506,7 +507,7 @@ morpheus.VectorTrack.prototype = { ...@@ -506,7 +507,7 @@ morpheus.VectorTrack.prototype = {
var indices = valueToModelIndices.get(value); var indices = valueToModelIndices.get(value);
for (var i = 0, nindices = indices.length; i < nindices; i++) { for (var i = 0, nindices = indices.length; i < nindices; i++) {
var viewIndex = project var viewIndex = project
.convertModelRowIndexToView(indices[i]); .convertModelRowIndexToView(indices[i]);
if (viewIndex >= start && viewIndex < end) { if (viewIndex >= start && viewIndex < end) {
var size = positions.getItemSize(viewIndex); var size = positions.getItemSize(viewIndex);
var pix = positions.getPosition(viewIndex); var pix = positions.getPosition(viewIndex);
...@@ -519,23 +520,20 @@ morpheus.VectorTrack.prototype = { ...@@ -519,23 +520,20 @@ morpheus.VectorTrack.prototype = {
} }
}, },
prePaint : function(clip, context) {
// draw selection, highlighted, hover drawSelection: function (options) {
var project = this.project; var project = this.project;
var positions = this.positions; var positions = this.positions;
var height = this.getUnscaledHeight(); var context = options.context;
var width = this.getUnscaledWidth(); var start = options.start;
var setup = this._setup(context, clip); var end = options.end;
var start = setup.start;
var end = setup.end;
// selection
context.lineWidth = 1; context.lineWidth = 1;
context.fillStyle = this.settings.selectionColor; context.fillStyle = this.settings.selectionColor;
var _this = this;
if (this.isColumns) { if (this.isColumns) {
var height = this.getUnscaledHeight();
var viewIndices = project.getColumnSelectionModel() var viewIndices = project.getColumnSelectionModel()
.getViewIndices(); .getViewIndices();
viewIndices.forEach(function(i) { viewIndices.forEach(function (i) {
if (i >= start && i <= end) { if (i >= start && i <= end) {
var size = positions.getItemSize(i); var size = positions.getItemSize(i);
var pix = positions.getPosition(i); var pix = positions.getPosition(i);
...@@ -543,10 +541,11 @@ morpheus.VectorTrack.prototype = { ...@@ -543,10 +541,11 @@ morpheus.VectorTrack.prototype = {
} }
}); });
} else { } else {
var width = this.getUnscaledWidth();
if (!this.isRenderAs(morpheus.VectorTrack.RENDER.MOLECULE)) { if (!this.isRenderAs(morpheus.VectorTrack.RENDER.MOLECULE)) {
var viewIndices = project.getRowSelectionModel() var viewIndices = project.getRowSelectionModel()
.getViewIndices(); .getViewIndices();
viewIndices.forEach(function(i) { viewIndices.forEach(function (i) {
if (i >= start && i <= end) { if (i >= start && i <= end) {
var size = positions.getItemSize(i); var size = positions.getItemSize(i);
var pix = positions.getPosition(i); var pix = positions.getPosition(i);
...@@ -556,14 +555,27 @@ morpheus.VectorTrack.prototype = { ...@@ -556,14 +555,27 @@ morpheus.VectorTrack.prototype = {
} }
} }
},
prePaint: function (clip, context) {
// draw selection
var project = this.project;
var positions = this.positions;
var setup = this._setup(context, clip);
var start = setup.start;
var end = setup.end;
this.drawSelection({
context: context,
start: start,
end: end
});
if (this.invalid || start !== this.lastPosition.start if (this.invalid || start !== this.lastPosition.start
|| end !== this.lastPosition.end) { || end !== this.lastPosition.end) {
this.lastPosition.start = start; this.lastPosition.start = start;
this.lastPosition.end = end; this.lastPosition.end = end;
this.invalid = true; this.invalid = true;
} }
}, },
drawRowBorder : function(context, positions, index, gridSize) { drawRowBorder: function (context, positions, index, gridSize) {
var size = positions.getItemSize(index); var size = positions.getItemSize(index);
var pix = positions.getPosition(index); var pix = positions.getPosition(index);
// top and bottom lines // top and bottom lines
...@@ -576,7 +588,7 @@ morpheus.VectorTrack.prototype = { ...@@ -576,7 +588,7 @@ morpheus.VectorTrack.prototype = {
context.lineTo(gridSize, pix); context.lineTo(gridSize, pix);
context.stroke(); context.stroke();
}, },
drawColumnBorder : function(context, positions, index, gridSize) { drawColumnBorder: function (context, positions, index, gridSize) {
var size = positions.getItemSize(index); var size = positions.getItemSize(index);
var pix = positions.getPosition(index); var pix = positions.getPosition(index);
// top and bottom lines // top and bottom lines
...@@ -589,10 +601,10 @@ morpheus.VectorTrack.prototype = { ...@@ -589,10 +601,10 @@ morpheus.VectorTrack.prototype = {
context.lineTo(pix, gridSize); context.lineTo(pix, gridSize);
context.stroke(); context.stroke();
}, },
isSquished : function() { isSquished: function () {
return this.settings.squished; return this.settings.squished;
}, },
_setup : function(context, clip) { _setup: function (context, clip) {
var start = 0; var start = 0;
var vector = this.getVector(); var vector = this.getVector();
var end = vector.size(); var end = vector.size();
...@@ -612,7 +624,7 @@ morpheus.VectorTrack.prototype = { ...@@ -612,7 +624,7 @@ morpheus.VectorTrack.prototype = {
if (settings.squished) { if (settings.squished) {
var total = positions.getPosition(positions.getLength() - 1) var total = positions.getPosition(positions.getLength() - 1)
+ positions.getItemSize(positions.getLength() - 1); + positions.getItemSize(positions.getLength() - 1);
if (!this.isColumns) { if (!this.isColumns) {
var squishFactor = height / total; var squishFactor = height / total;
context.scale(1, squishFactor); context.scale(1, squishFactor);
...@@ -625,26 +637,53 @@ morpheus.VectorTrack.prototype = { ...@@ -625,26 +637,53 @@ morpheus.VectorTrack.prototype = {
context.translate(-clip.x, -clip.y); context.translate(-clip.x, -clip.y);
} }
return { return {
start : start, start: start,
end : end, end: end,
vector : vector vector: vector
}; };
}, },
draw : function(clip, context) { draw: function (clip, context) {
this._draw(clip, context, this.isColumns ? this.getUnscaledHeight() var setup = this._setup(context, clip);
: this.getUnscaledWidth()); this._draw({
start: setup.start,
end: setup.end,
vector: setup.vector,
context: context,
availableSpace: this.isColumns ? this.getUnscaledHeight()
: this.getUnscaledWidth(),
clip: clip
});
}, },
print : function(clip, context) { print: function (clip, context) {
this._draw(clip, context, this.isColumns ? clip.height : clip.width); var vector = this.getVector();
this._draw({
start: 0,
end: vector.size(),
vector: vector,
context: context,
availableSpace: this.isColumns ? clip.height
: clip.width,
clip: clip
});
}, },
_draw : function(clip, context, availableSpace) { /**
* @param options.vector
* @param options.context
* @param options.start
* @param options.end
* @param options.availableSpace
*/
_draw: function (options) {
var _this = this; var _this = this;
var fullAvailableSpace = availableSpace; var context = options.context;
var vector = options.vector;
var availableSpace = options.availableSpace;
var fullAvailableSpace = options.availableSpace;
var start = options.start;
var end = options.end;
var clip = options.clip;
var positions = this.positions; var positions = this.positions;
var setup = this._setup(context, clip);
var start = setup.start;
var end = setup.end;
var vector = setup.vector;
context.textAlign = 'left'; context.textAlign = 'left';
context.fillStyle = morpheus.CanvasUtil.FONT_COLOR; context.fillStyle = morpheus.CanvasUtil.FONT_COLOR;
...@@ -689,61 +728,61 @@ morpheus.VectorTrack.prototype = { ...@@ -689,61 +728,61 @@ morpheus.VectorTrack.prototype = {
if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR)) {
this.renderColor(context, vector, start, end, clip, this.renderColor(context, vector, start, end, clip,
this.isColumns ? availableSpace : 0, this.isColumns ? availableSpace : 0,
!this.settings.discrete); !this.settings.discrete);
offset += this.settings.colorBarSize + 2; offset += this.settings.colorBarSize + 2;
availableSpace -= offset; availableSpace -= offset;
} }
if (!this.settings.squished if (!this.settings.squished
&& this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) { && this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) {
this.renderShape(context, vector, start, end, clip, this.renderShape(context, vector, start, end, clip,
this.isColumns ? availableSpace - offset : offset); this.isColumns ? availableSpace - offset : offset);
offset += this.settings.colorBarSize + 2; offset += this.settings.colorBarSize + 2;
availableSpace -= offset; availableSpace -= offset;
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.ARC)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.ARC)) {
this.renderArc(context, vector, start, end, clip, this.renderArc(context, vector, start, end, clip,
this.settings.arcSize); this.settings.arcSize);
offset += this.settings.arcSize + 2; offset += this.settings.arcSize + 2;
availableSpace -= offset; availableSpace -= offset;
} }
if (!this.settings.squished if (!this.settings.squished
&& this.isRenderAs(morpheus.VectorTrack.RENDER.MOLECULE)) { && this.isRenderAs(morpheus.VectorTrack.RENDER.MOLECULE)) {
this.renderMolecule(context, vector, start, end, clip, offset, this.renderMolecule(context, vector, start, end, clip, offset,
availableSpace); availableSpace);
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) {
var barSize = !this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT) ? (availableSpace - 2) var barSize = !this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT) ? (availableSpace - 2)
: this.settings.barSize; : this.settings.barSize;
offset++; offset++;
this.renderBoxPlot(context, vector, start, end, clip, offset, this.renderBoxPlot(context, vector, start, end, clip, offset,
barSize); barSize);
offset += barSize + 2; offset += barSize + 2;
availableSpace -= offset; availableSpace -= offset;
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)) {
var barSize = !this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT) ? (availableSpace - 1) var barSize = !this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT) ? (availableSpace - 1)
: this.settings.barSize; : this.settings.barSize;
if (this.settings.stackedBar) { if (this.settings.stackedBar) {
this.renderStackedBar(context, vector, start, end, clip, this.renderStackedBar(context, vector, start, end, clip,
offset, barSize); offset, barSize);
} else { } else {
var fields = vector.getProperties().get( var fields = vector.getProperties().get(
morpheus.VectorKeys.FIELDS); morpheus.VectorKeys.FIELDS);
var visibleFieldIndices = vector.getProperties().get( var visibleFieldIndices = vector.getProperties().get(
morpheus.VectorKeys.VISIBLE_FIELDS); morpheus.VectorKeys.VISIBLE_FIELDS);
if (fields != null && visibleFieldIndices == null) { if (fields != null && visibleFieldIndices == null) {
visibleFieldIndices = morpheus.Util.seq(fields.length); visibleFieldIndices = morpheus.Util.seq(fields.length);
} }
if (fields != null) { if (fields != null) {
this.renderUnstackedBar(context, vector, start, end, clip, this.renderUnstackedBar(context, vector, start, end, clip,
offset, barSize, visibleFieldIndices); offset, barSize, visibleFieldIndices);
} else { } else {
this.renderBar(context, vector, start, end, clip, offset, this.renderBar(context, vector, start, end, clip, offset,
barSize); barSize);
} }
} }
offset += barSize + 2; offset += barSize + 2;
...@@ -751,24 +790,24 @@ morpheus.VectorTrack.prototype = { ...@@ -751,24 +790,24 @@ morpheus.VectorTrack.prototype = {
} }
if (!this.settings.squished if (!this.settings.squished
&& this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)) { && this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)) {
this.renderText(context, vector, true, start, end, clip, offset, this.renderText(context, vector, true, start, end, clip, offset,
this.isColumns ? fullAvailableSpace : 0); this.isColumns ? fullAvailableSpace : 0);
offset += this.settings.maxTextWidth + 2; offset += this.settings.maxTextWidth + 2;
availableSpace -= offset; availableSpace -= offset;
} }
this.textWidth = 0; this.textWidth = 0;
if (!this.settings.squished if (!this.settings.squished
&& this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT)) { && this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT)) {
this.textWidth = availableSpace; this.textWidth = availableSpace;
this.renderText(context, vector, false, start, end, clip, offset, this.renderText(context, vector, false, start, end, clip, offset,
this.isColumns ? fullAvailableSpace : 0); this.isColumns ? fullAvailableSpace : 0);
offset += this.settings.textWidth + 2; offset += this.settings.textWidth + 2;
availableSpace -= offset; availableSpace -= offset;
} }
}, },
showPopup : function(e, isHeader) { showPopup: function (e, isHeader) {
if (!this.heatmap.options.popupEnabled) { if (!this.heatmap.options.popupEnabled) {
return; return;
} }
...@@ -776,7 +815,7 @@ morpheus.VectorTrack.prototype = { ...@@ -776,7 +815,7 @@ morpheus.VectorTrack.prototype = {
var project = this.project; var project = this.project;
var isColumns = this.isColumns; var isColumns = this.isColumns;
var hasSelection = isColumns ? project.getColumnSelectionModel() var hasSelection = isColumns ? project.getColumnSelectionModel()
.count() > 0 : project.getRowSelectionModel().count() > 0; .count() > 0 : project.getRowSelectionModel().count() > 0;
var ANNOTATE_SELECTION = 'Annotate Selection'; var ANNOTATE_SELECTION = 'Annotate Selection';
var INVERT_SELECTION = 'Invert Selection'; var INVERT_SELECTION = 'Invert Selection';
var SELECT_ALL = 'Select All'; var SELECT_ALL = 'Select All';
...@@ -808,13 +847,13 @@ morpheus.VectorTrack.prototype = { ...@@ -808,13 +847,13 @@ morpheus.VectorTrack.prototype = {
var heatmap = this.heatmap; var heatmap = this.heatmap;
var sectionToItems = { var sectionToItems = {
'Sort' : [], 'Sort': [],
'Selection' : [], 'Selection': [],
'Display' : [] 'Display': []
}; };
if (isHeader) { if (isHeader) {
sectionToItems.Sort.push({ sectionToItems.Sort.push({
name : FILTER name: FILTER
}); });
// sectionToItems['Sort'].push({ // sectionToItems['Sort'].push({
// name : SORT_ASC // name : SORT_ASC
...@@ -828,23 +867,23 @@ morpheus.VectorTrack.prototype = { ...@@ -828,23 +867,23 @@ morpheus.VectorTrack.prototype = {
var dataset = project.getSortedFilteredDataset(); var dataset = project.getSortedFilteredDataset();
try { try {
project.getRowSelectionModel().getViewIndices().forEach( project.getRowSelectionModel().getViewIndices().forEach(
function(index) { function (index) {
if (dataset.getState(index) !== -1) { if (dataset.getState(index) !== -1) {
toggle = true; toggle = true;
throw 'break'; throw 'break';
} }
}); });
} catch (x) { // break out of loop } catch (x) { // break out of loop
} }
if (toggle) { if (toggle) {
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : TOGGLE name: TOGGLE
}); });
} }
} }
var customItems = this.heatmap.getPopupItems(); var customItems = this.heatmap.getPopupItems();
if (customItems && customItems.length > 0) { if (customItems && customItems.length > 0) {
customItems.forEach(function(item) { customItems.forEach(function (item) {
if (item.columns === isColumns) { if (item.columns === isColumns) {
sectionToItems[item.section].push(item); sectionToItems[item.section].push(item);
} }
...@@ -852,89 +891,89 @@ morpheus.VectorTrack.prototype = { ...@@ -852,89 +891,89 @@ morpheus.VectorTrack.prototype = {
} }
if (sectionToItems.Selection.length > 0) { if (sectionToItems.Selection.length > 0) {
sectionToItems.Selection.push({ sectionToItems.Selection.push({
separator : true separator: true
}); });
} }
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : 'Copy' name: 'Copy'
}); });
sectionToItems.Selection.push({ sectionToItems.Selection.push({
separator : true separator: true
}); });
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : ANNOTATE_SELECTION name: ANNOTATE_SELECTION
}); });
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : INVERT_SELECTION name: INVERT_SELECTION
}); });
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : SELECT_ALL name: SELECT_ALL
}); });
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : CLEAR_SELECTION name: CLEAR_SELECTION
}); });
// sectionToItems.Selection.push({ // sectionToItems.Selection.push({
// name : SHOW_SELECTION_ONLY // name : SHOW_SELECTION_ONLY
// }); // });
var combinedFilter = isColumns ? project.getColumnFilter() : project var combinedFilter = isColumns ? project.getColumnFilter() : project
.getRowFilter(); .getRowFilter();
var showSelectionOnlyIndex = combinedFilter var showSelectionOnlyIndex = combinedFilter
.indexOf(SHOW_SELECTION_ONLY); .indexOf(SHOW_SELECTION_ONLY);
if (showSelectionOnlyIndex !== -1) { if (showSelectionOnlyIndex !== -1) {
sectionToItems.Selection.push({ sectionToItems.Selection.push({
name : REMOVE_SHOW_SELECTION_ONLY name: REMOVE_SHOW_SELECTION_ONLY
}); });
} }
if (!isHeader) { if (!isHeader) {
sectionToItems['Sort'].push({ sectionToItems['Sort'].push({
name : SORT_SEL_ASC, name: SORT_SEL_ASC,
disabled : !hasSelection disabled: !hasSelection
}); });
sectionToItems['Sort'].push({ sectionToItems['Sort'].push({
name : SORT_SEL_DESC, name: SORT_SEL_DESC,
disabled : !hasSelection disabled: !hasSelection
}); });
sectionToItems['Sort'].push({ sectionToItems['Sort'].push({
name : SORT_SEL_TOP_N, name: SORT_SEL_TOP_N,
disabled : !hasSelection disabled: !hasSelection
}); });
} }
var dataType = morpheus.VectorUtil.getDataType(this.getFullVector()); var dataType = morpheus.VectorUtil.getDataType(this.getFullVector());
var arrayFields = this.getFullVector().getProperties().get( var arrayFields = this.getFullVector().getProperties().get(
morpheus.VectorKeys.FIELDS); morpheus.VectorKeys.FIELDS);
var isArray = arrayFields !== undefined; var isArray = arrayFields !== undefined;
var isNumber = dataType === 'number' || dataType === '[number]'; var isNumber = dataType === 'number' || dataType === '[number]';
if (isNumber || isArray) { if (isNumber || isArray) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_BAR, name: DISPLAY_BAR,
checked : this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) checked: this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)
}); });
} }
if (isArray) { if (isArray) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_STACKED_BAR, name: DISPLAY_STACKED_BAR,
checked : this.settings.stackedBar checked: this.settings.stackedBar
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
name : FIELDS, name: FIELDS,
}); });
} }
if (!isArray) { if (!isArray) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_COLOR, name: DISPLAY_COLOR,
checked : this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR) checked: this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR)
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_TEXT, name: DISPLAY_TEXT,
checked : this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT) checked: this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT)
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_SHAPE, name: DISPLAY_SHAPE,
checked : this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE) checked: this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)
}); });
// sectionToItems.Display.push({ // sectionToItems.Display.push({
// name : DISPLAY_ARC, // name : DISPLAY_ARC,
...@@ -949,100 +988,100 @@ morpheus.VectorTrack.prototype = { ...@@ -949,100 +988,100 @@ morpheus.VectorTrack.prototype = {
// }); // });
if (!isArray && !isNumber && !this.isColumns if (!isArray && !isNumber && !this.isColumns
&& name.toLowerCase().indexOf('smile') !== -1) { && name.toLowerCase().indexOf('smile') !== -1) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_STRUCTURE, name: DISPLAY_STRUCTURE,
checked : this.isRenderAs(morpheus.VectorTrack.RENDER.MOLECULE) checked: this.isRenderAs(morpheus.VectorTrack.RENDER.MOLECULE)
}); });
} }
sectionToItems.Display.push({ sectionToItems.Display.push({
name : TOOLTIP, name: TOOLTIP,
checked : this.settings.inlineTooltip checked: this.settings.inlineTooltip
}); });
if (!isArray) { if (!isArray) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : HIGHLIGHT_MATCHING_VALUES, name: HIGHLIGHT_MATCHING_VALUES,
checked : this.settings.highlightMatchingValues checked: this.settings.highlightMatchingValues
}); });
} }
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Squished', name: 'Squished',
checked : this.settings.squished checked: this.settings.squished
}); });
if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) { || this.isRenderAs(morpheus.VectorTrack.RENDER.BOX_PLOT)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
separator : true separator: true
}); });
if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Edit Bar Color...' name: 'Edit Bar Color...'
}); });
} }
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Auto Range' name: 'Auto Range'
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Custom Range...' name: 'Custom Range...'
}); });
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR) if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR) || this.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) || this.isRenderAs(morpheus.VectorTrack.RENDER.BAR)
|| this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) { || this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
separator : true separator: true
}); });
if (isNumber) { if (isNumber) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DISPLAY_CONTINUOUS, name: DISPLAY_CONTINUOUS,
checked : !this.settings.discrete checked: !this.settings.discrete
}); });
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR) if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR)
|| this || this
.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR) .isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)
|| (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) && isArray)) { || (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) && isArray)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Edit Colors...' name: 'Edit Colors...'
}); });
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Edit Shapes...' name: 'Edit Shapes...'
}); });
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR) if (this.isRenderAs(morpheus.VectorTrack.RENDER.COLOR)
|| this || this
.isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR) .isRenderAs(morpheus.VectorTrack.RENDER.TEXT_AND_COLOR)
|| (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) && isArray)) { || (this.isRenderAs(morpheus.VectorTrack.RENDER.BAR) && isArray)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Color Key', name: 'Color Key',
icon : 'fa fa-key' icon: 'fa fa-key'
}); });
} }
} }
if (this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) { if (this.isRenderAs(morpheus.VectorTrack.RENDER.SHAPE)) {
sectionToItems.Display.push({ sectionToItems.Display.push({
name : 'Shape Key', name: 'Shape Key',
icon : 'fa fa-key' icon: 'fa fa-key'
}); });
} }
sectionToItems.Display.push({ sectionToItems.Display.push({
separator : true separator: true
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
name : HIDE name: HIDE
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
separator : true separator: true
}); });
sectionToItems.Display.push({ sectionToItems.Display.push({
name : DELETE name: DELETE
}); });
var items = []; var items = [];
...@@ -1050,16 +1089,16 @@ morpheus.VectorTrack.prototype = { ...@@ -1050,16 +1089,16 @@ morpheus.VectorTrack.prototype = {
function addSection(name) { function addSection(name) {
if (items.length > 0) { if (items.length > 0) {
items.push({ items.push({
separator : true separator: true
}); });
} }
items = items.concat(sectionToItems[name]); items = items.concat(sectionToItems[name]);
} }
addSection('Sort'); addSection('Sort');
_.each(sectionToItems.Selection, function(item) { _.each(sectionToItems.Selection, function (item) {
if (item.name !== REMOVE_SHOW_SELECTION_ONLY if (item.name !== REMOVE_SHOW_SELECTION_ONLY
&& item.name !== SELECT_ALL) { && item.name !== SELECT_ALL) {
item.disabled = !hasSelection; item.disabled = !hasSelection;
} }
}); });
...@@ -1073,646 +1112,642 @@ morpheus.VectorTrack.prototype = { ...@@ -1073,646 +1112,642 @@ morpheus.VectorTrack.prototype = {
} }
morpheus.Popup morpheus.Popup
.showPopup( .showPopup(
items, items,
{ {
x : e.pageX, x: e.pageX,
y : e.pageY y: e.pageY
}, },
e.target, e.target,
function(event, item) { function (event, item) {
var customItem; var customItem;
if (item === 'Copy') { if (item === 'Copy') {
var dataset = project var dataset = project
.getSortedFilteredDataset(); .getSortedFilteredDataset();
var v = isColumns ? dataset.getColumnMetadata() var v = isColumns ? dataset.getColumnMetadata()
.getByName(_this.name) : dataset .getByName(_this.name) : dataset
.getRowMetadata().getByName(_this.name); .getRowMetadata().getByName(_this.name);
var selectionModel = isColumns ? project var selectionModel = isColumns ? project
.getColumnSelectionModel() : project .getColumnSelectionModel() : project
.getRowSelectionModel(); .getRowSelectionModel();
var text = []; var text = [];
selectionModel.getViewIndices().forEach( selectionModel.getViewIndices().forEach(
function(index) { function (index) {
text.push(morpheus.Util.toString(v text.push(morpheus.Util.toString(v
.getValue(index))); .getValue(index)));
}); });
event.clipboardData.setData('text/plain', text event.clipboardData.setData('text/plain', text
.join('\t')); .join('\t'));
} else if (item === FIELDS) { } else if (item === FIELDS) {
var visibleFieldIndices = _this var visibleFieldIndices = _this
.getFullVector() .getFullVector()
.getProperties() .getProperties()
.get(morpheus.VectorKeys.VISIBLE_FIELDS); .get(morpheus.VectorKeys.VISIBLE_FIELDS);
var visibleFields; var visibleFields;
if (visibleFieldIndices == null) { if (visibleFieldIndices == null) {
visibleFields = arrayFields.slice(0); visibleFields = arrayFields.slice(0);
} else { } else {
visibleFields = []; visibleFields = [];
for (var i = 0; i < visibleFieldIndices.length; i++) { for (var i = 0; i < visibleFieldIndices.length; i++) {
visibleFields visibleFields
.push(arrayFields[visibleFieldIndices[i]]); .push(arrayFields[visibleFieldIndices[i]]);
} }
}
var availableFields = [];
for (var i = 0; i < arrayFields.length; i++) {
if (visibleFields.indexOf(arrayFields[i]) === -1) {
availableFields.push(arrayFields[i]);
}
}
var leftOptions = []; }
var rightOptions = []; var availableFields = [];
for (var i = 0; i < availableFields.length; i++) { for (var i = 0; i < arrayFields.length; i++) {
leftOptions.push(new Option( if (visibleFields.indexOf(arrayFields[i]) === -1) {
availableFields[i], availableFields.push(arrayFields[i]);
availableFields[i])); }
} }
for (var i = 0; i < visibleFields.length; i++) {
rightOptions
.push(new Option(visibleFields[i],
visibleFields[i]));
}
var list = new morpheus.DualList(leftOptions, var leftOptions = [];
rightOptions); var rightOptions = [];
for (var i = 0; i < availableFields.length; i++) {
morpheus.FormBuilder leftOptions.push(new Option(
.showOkCancel({ availableFields[i],
title : 'Fields', availableFields[i]));
okCallback : function() { }
var visibleFields = list for (var i = 0; i < visibleFields.length; i++) {
.getOptions(false); rightOptions
var visibleFieldIndices = []; .push(new Option(visibleFields[i],
for (var i = 0; i < visibleFields.length; i++) { visibleFields[i]));
visibleFieldIndices }
.push(arrayFields
.indexOf(visibleFields[i]));
}
var fullVector = _this
.getFullVector();
fullVector
.getProperties()
.set(
morpheus.VectorKeys.VISIBLE_FIELDS,
visibleFieldIndices);
// remove cached box field
var summaryFunction = fullVector
.getProperties()
.get(
morpheus.VectorKeys.ARRAY_SUMMARY_FUNCTION);
if (summaryFunction) {
summaryFunction.indices = visibleFieldIndices;
}
var updatedVector = _this.isColumns ? _this.project
.getFullDataset()
.getColumnMetadata()
.add(_this.name)
: _this.project
.getFullDataset()
.getRowMetadata()
.add(_this.name);
for (var i = 0; i < updatedVector
.size(); i++) {
var array = fullVector
.getValue(i);
if (array != null) {
array.box = null;
}
}
_this.setInvalid(true);
_this.repaint();
},
content : list.$el
});
} else if (item === 'Edit Bar Color...') {
var formBuilder = new morpheus.FormBuilder();
formBuilder.append({
name : 'bar_color',
type : 'color',
value : _this.settings.barColor,
required : true,
col : 'col-xs-2'
});
formBuilder.find('bar_color').on(
'change',
function() {
_this.settings.barColor = $(this)
.val();
_this.setInvalid(true);
_this.repaint();
});
morpheus.FormBuilder.showInModal({
title : 'Bar Color',
close : 'Close',
html : formBuilder.$form
});
} else if (item === TOGGLE) {
var dataset = project
.getSortedFilteredDataset();
project.getRowSelectionModel().getViewIndices()
.forEach(function(index) {
dataset.setState(index, undefined); // FIXME
});
project.setFullDataset(
project.getFullDataset(), true);
} else if (item === ANNOTATE_SELECTION) {
var formBuilder = new morpheus.FormBuilder();
formBuilder.append({
name : 'annotation_name',
type : 'text',
required : true
});
formBuilder.append({
name : 'annotation_value',
type : 'text',
required : true
});
morpheus.FormBuilder
.showOkCancel({
title : ANNOTATE_SELECTION,
content : formBuilder.$form,
okCallback : function() {
var value = formBuilder
.getValue('annotation_value');
var annotationName = formBuilder
.getValue('annotation_name');
var dataset = project
.getSortedFilteredDataset();
var fullDataset = project
.getFullDataset();
if (isColumns) {
dataset = morpheus.DatasetUtil
.transposedView(dataset);
fullDataset = morpheus.DatasetUtil
.transposedView(fullDataset);
}
var existingVector = fullDataset
.getRowMetadata()
.getByName(
annotationName);
var v = dataset
.getRowMetadata().add(
annotationName);
var selectionModel = isColumns ? project
.getColumnSelectionModel()
: project
.getRowSelectionModel();
selectionModel
.getViewIndices()
.forEach(
function(index) {
v
.setValue(
index,
value);
});
morpheus.VectorUtil
.maybeConvertStringToNumber(v);
project
.trigger(
'trackChanged',
{
vectors : [ v ],
render : existingVector != null ? []
: [ morpheus.VectorTrack.RENDER.TEXT ],
columns : isColumns
});
}
});
} else if (item === DELETE) {
morpheus.FormBuilder
.showOkCancel({
title : 'Delete',
content : 'Are you sure you want to delete '
+ _this.name + '?',
okCallback : function() {
var metadata = isColumns ? project
.getFullDataset()
.getColumnMetadata()
: project
.getFullDataset()
.getRowMetadata();
metadata
.remove(morpheus.MetadataUtil
.indexOf(
metadata,
_this.name));
var sortKeys = isColumns ? project
.getColumnSortKeys()
: project
.getRowSortKeys();
var sortKeyIndex = _.indexOf(
sortKeys.map(function(
key) {
return key.field;
}), _this.name);
if (sortKeyIndex !== -1) {
sortKeys.splice(
sortKeyIndex, 1);
if (isColumns) {
project
.setColumnSortKeys(
sortKeys,
true);
} else {
project.setRowSortKeys(
sortKeys, true);
}
}
var groupByKeys = isColumns ? project
.getGroupColumns()
: project
.getGroupRows();
var groupByKeyIndex = _
.indexOf(
groupByKeys
.map(function(
key) {
return key.field;
}),
_this.name);
if (groupByKeyIndex !== -1) {
groupByKeys.splice(
groupByKeyIndex, 1);
if (isColumns) {
project
.setGroupColumns(
groupByKeys,
true);
} else {
project.setGroupRows(
groupByKeys,
true);
}
}
if (!isColumns) {
// remove from any group
// by or sort by
project
.trigger(
'rowTrackRemoved',
{
vector : _this
.getFullVector()
});
} else {
project
.trigger(
'columnTrackRemoved',
{
vector : _this
.getFullVector()
});
}
}
});
} else if (item === CLEAR_SELECTION) {
var model = isColumns ? project
.getColumnSelectionModel() : project
.getRowSelectionModel();
model.setViewIndices(new morpheus.Set(), true);
} else if (item === INVERT_SELECTION) {
var model = isColumns ? project
.getColumnSelectionModel() : project
.getRowSelectionModel();
var viewIndices = model.getViewIndices();
var inverse = new morpheus.Set();
for (var i = 0, n = positions.getLength(); i < n; i++) {
if (!viewIndices.has(i)) {
inverse.add(i);
}
}
model.setViewIndices(inverse, true);
} else if (item === FILTER) {
var vector = _this.getFullVector();
var filter;
var index = _this.isColumns ? _this.project
.getColumnFilter().indexOf(
vector.getName())
: _this.project.getRowFilter().indexOf(
vector.getName());
if (index === -1) {
if (morpheus.VectorUtil.isNumber(vector)
&& morpheus.VectorUtil
.containsMoreThanNValues(
vector, 9)) {
filter = new morpheus.RangeFilter(NaN,
NaN, vector.getName());
} else {
var set = morpheus.VectorUtil
.getSet(vector);
var array = set.values();
array
.sort(morpheus.SortKey.ASCENDING_COMPARATOR);
filter = new morpheus.VectorFilter(set,
set.size(), vector.getName());
}
if (filter) {
if (_this.isColumns) {
_this.project.getColumnFilter()
.add(filter, true);
} else {
_this.project.getRowFilter().add(
filter, true);
}
}
var list = new morpheus.DualList(leftOptions,
rightOptions);
morpheus.FormBuilder
.showOkCancel({
title: 'Fields',
okCallback: function () {
var visibleFields = list
.getOptions(false);
var visibleFieldIndices = [];
for (var i = 0; i < visibleFields.length; i++) {
visibleFieldIndices
.push(arrayFields
.indexOf(visibleFields[i]));
}
var fullVector = _this
.getFullVector();
fullVector
.getProperties()
.set(
morpheus.VectorKeys.VISIBLE_FIELDS,
visibleFieldIndices);
// remove cached box field
var summaryFunction = fullVector
.getProperties()
.get(
morpheus.VectorKeys.ARRAY_SUMMARY_FUNCTION);
if (summaryFunction) {
summaryFunction.indices = visibleFieldIndices;
}
var updatedVector = _this.isColumns ? _this.project
.getFullDataset()
.getColumnMetadata()
.add(_this.name)
: _this.project
.getFullDataset()
.getRowMetadata()
.add(_this.name);
for (var i = 0; i < updatedVector
.size(); i++) {
var array = fullVector
.getValue(i);
if (array != null) {
array.box = null;
} }
if (_this.isColumns) { }
_this.project.getColumnFilter().trigger(
'focus', {});
} else {
_this.project.getRowFilter().trigger(
'focus', {});
}
} else if (item === SORT_ASC || item === SORT_DESC) { _this.setInvalid(true);
var sortKey = new morpheus.SortKey( _this.repaint();
_this.name, },
item === SORT_ASC ? morpheus.SortKey.SortOrder.ASCENDING content: list.$el
: morpheus.SortKey.SortOrder.DESCENDING); });
if (_this.isColumns) { } else if (item === 'Edit Bar Color...') {
_this.project var formBuilder = new morpheus.FormBuilder();
.setColumnSortKeys( formBuilder.append({
morpheus.SortKey name: 'bar_color',
.keepExistingSortKeys( type: 'color',
[ sortKey ], value: _this.settings.barColor,
project required: true,
.getColumnSortKeys()), col: 'col-xs-2'
true); });
} else { formBuilder.find('bar_color').on(
_this.project 'change',
.setRowSortKeys( function () {
morpheus.SortKey _this.settings.barColor = $(this)
.keepExistingSortKeys( .val();
[ sortKey ], _this.setInvalid(true);
project _this.repaint();
.getRowSortKeys()), });
true); morpheus.FormBuilder.showInModal({
} title: 'Bar Color',
} else if (item == SORT_SEL_ASC close: 'Close',
|| item == SORT_SEL_DESC html: formBuilder.$form
|| item === SORT_SEL_TOP_N) { });
var sortOrder; } else if (item === TOGGLE) {
if (item === SORT_SEL_ASC) { var dataset = project
sortOrder = morpheus.SortKey.SortOrder.ASCENDING; .getSortedFilteredDataset();
} else if (item === SORT_SEL_DESC) { project.getRowSelectionModel().getViewIndices()
sortOrder = morpheus.SortKey.SortOrder.DESCENDING; .forEach(function (index) {
} else { dataset.setState(index, undefined); // FIXME
sortOrder = morpheus.SortKey.SortOrder.TOP_N; });
} project.setFullDataset(
heatmap.sortBasedOnSelection(sortOrder, project.getFullDataset(), true);
isColumns, e && e.shiftKey); } else if (item === ANNOTATE_SELECTION) {
} else if (item === SELECT_ALL) { var formBuilder = new morpheus.FormBuilder();
var selectionModel = !isColumns ? heatmap formBuilder.append({
.getProject().getRowSelectionModel() name: 'annotation_name',
: heatmap.getProject() type: 'text',
.getColumnSelectionModel(); required: true
var count = !isColumns ? heatmap.getProject() });
.getSortedFilteredDataset() formBuilder.append({
.getRowCount() : heatmap.getProject() name: 'annotation_value',
.getSortedFilteredDataset() type: 'text',
.getColumnCount(); required: true
var indices = new morpheus.Set(); });
for (var i = 0; i < count; i++) { morpheus.FormBuilder
indices.add(i); .showOkCancel({
} title: ANNOTATE_SELECTION,
selectionModel.setViewIndices(indices, true); content: formBuilder.$form,
} else if (item === 'Auto Range') { okCallback: function () {
delete _this.settings.min; var value = formBuilder
delete _this.settings.max; .getValue('annotation_value');
delete _this.settings.mid; var annotationName = formBuilder
_this._update(); .getValue('annotation_name');
heatmap.revalidate(); var dataset = project
} else if (item === 'Custom Range...') { .getSortedFilteredDataset();
var formBuilder = new morpheus.FormBuilder(); var fullDataset = project
var items = [ { .getFullDataset();
name : 'min', if (isColumns) {
required : true, dataset = morpheus.DatasetUtil
type : 'number', .transposedView(dataset);
value : _this.settings.min fullDataset = morpheus.DatasetUtil
}, { .transposedView(fullDataset);
name : 'mid', }
required : true,
type : 'number',
value : _this.settings.mid
}, {
name : 'max',
required : true,
type : 'number',
value : _this.settings.max
} ];
_.each(items, function(item) {
formBuilder.append(item);
});
morpheus.FormBuilder
.showOkCancel({
title : 'Range',
content : formBuilder.$form,
okCallback : function() {
_this.settings.min = parseFloat(formBuilder
.getValue('min'));
_this.settings.mid = parseFloat(formBuilder
.getValue('mid'));
_this.settings.max = parseFloat(formBuilder
.getValue('max'));
_this._update();
heatmap.revalidate();
}
});
} else if (item === 'Squished') {
_this.settings.squished = !_this.settings.squished;
heatmap.revalidate();
} else if (item === 'Color Key') {
var legend = new morpheus.HeatMapTrackColorLegend(
[ _this ], isColumns ? _this.project
.getColumnColorModel()
: _this.project
.getRowColorModel());
var size = legend.getPreferredSize();
legend.setBounds(size);
legend.repaint();
morpheus.FormBuilder.showInModal({
title : 'Color Key',
html : legend.canvas
});
} else if (item === 'Shape Key') {
var legend = new morpheus.HeatMapTrackShapeLegend(
[ _this ], isColumns ? _this.project
.getColumnShapeModel()
: _this.project
.getRowShapeModel());
var size = legend.getPreferredSize();
legend.setBounds(size);
legend.repaint();
morpheus.FormBuilder.showInModal({
title : 'Shape Key',
html : legend.canvas
});
} else if (item === 'Edit Shapes...') {
var shapeFormBuilder = new morpheus.FormBuilder();
var shapeModel = isColumns ? _this.project
.getColumnShapeModel() : _this.project
.getRowShapeModel();
var chooser = new morpheus.ShapeChooser({
map : shapeModel.getMap(_this.name)
});
chooser.on('change', function(event) { var existingVector = fullDataset
shapeModel.setMappedValue(_this .getRowMetadata()
.getFullVector(), event.value, .getByName(
event.shape); annotationName);
_this.setInvalid(true); var v = dataset
_this.repaint(); .getRowMetadata().add(
annotationName);
var selectionModel = isColumns ? project
.getColumnSelectionModel()
: project
.getRowSelectionModel();
selectionModel
.getViewIndices()
.forEach(
function (index) {
v
.setValue(
index,
value);
}); });
morpheus.FormBuilder.showInModal({ morpheus.VectorUtil
title : 'Edit Shapes', .maybeConvertStringToNumber(v);
html : chooser.$div, project
close : 'Close' .trigger(
'trackChanged',
{
vectors: [v],
render: existingVector != null ? []
: [morpheus.VectorTrack.RENDER.TEXT],
columns: isColumns
}); });
} else if (item === 'Edit Colors...') { }
var colorSchemeChooser; });
var colorModel = isColumns ? _this.project } else if (item === DELETE) {
.getColumnColorModel() : _this.project morpheus.FormBuilder
.getRowColorModel(); .showOkCancel({
if (_this.settings.discrete) { title: 'Delete',
colorSchemeChooser = new morpheus.DiscreteColorSchemeChooser( content: 'Are you sure you want to delete '
{ + _this.name + '?',
colorScheme : { okCallback: function () {
scale : colorModel var metadata = isColumns ? project
.getDiscreteColorScheme(_this .getFullDataset()
.getFullVector()) .getColumnMetadata()
} : project
}); .getFullDataset()
colorSchemeChooser.on('change', function( .getRowMetadata();
event) { metadata
colorModel.setMappedValue(_this .remove(morpheus.MetadataUtil
.getFullVector(), event.value, .indexOf(
event.color); metadata,
_this.setInvalid(true); _this.name));
_this.repaint(); var sortKeys = isColumns ? project
}); .getColumnSortKeys()
: project
.getRowSortKeys();
var sortKeyIndex = _.indexOf(
sortKeys.map(function (key) {
return key.field;
}), _this.name);
if (sortKeyIndex !== -1) {
sortKeys.splice(
sortKeyIndex, 1);
if (isColumns) {
project
.setColumnSortKeys(
sortKeys,
true);
} else { } else {
colorSchemeChooser = new morpheus.HeatMapColorSchemeChooser( project.setRowSortKeys(
{ sortKeys, true);
showRelative : false,
});
colorSchemeChooser
.setColorScheme(colorModel
.getContinuousColorScheme(_this
.getFullVector()));
colorSchemeChooser.on('change', function(
event) {
_this.setInvalid(true);
_this.repaint();
});
} }
morpheus.FormBuilder.showInModal({ }
title : 'Edit Colors', var groupByKeys = isColumns ? project
html : colorSchemeChooser.$div, .getGroupColumns()
close : 'Close', : project
callback : function() { .getGroupRows();
colorSchemeChooser.dispose(); var groupByKeyIndex = _
} .indexOf(
}); groupByKeys
} else if (item === TOOLTIP) { .map(function (key) {
_this.settings.inlineTooltip = !_this.settings.inlineTooltip; return key.field;
} else if (item === HIGHLIGHT_MATCHING_VALUES) { }),
_this.settings.highlightMatchingValues = !_this.settings.highlightMatchingValues; _this.name);
} else if ((customItem = _ if (groupByKeyIndex !== -1) {
.find( groupByKeys.splice(
customItems, groupByKeyIndex, 1);
function(customItem) { if (isColumns) {
return customItem.name === item project
&& customItem.columns === isColumns; .setGroupColumns(
}))) { groupByKeys,
if (customItem.task) { true);
// add task
var task = {
tabId : _this.heatmap.getTabManager()
.getActiveTabId()
};
_this.heatmap.getTabManager().addTask(task);
setTimeout(function() {
try {
customItem.callback(heatmap);
} catch (x) {
}
_this.heatmap.getTabManager()
.removeTask(task);
}, 1);
} else { } else {
customItem.callback(heatmap); project.setGroupRows(
groupByKeys,
true);
} }
}
} else if (item === DISPLAY_CONTINUOUS) { if (!isColumns) {
_this.settings.discrete = !_this.settings.discrete; // remove from any group
_this._setChartMinMax(); // by or sort by
_this.setInvalid(true); project
_this.repaint(); .trigger(
} else if (item === HIDE) { 'rowTrackRemoved',
heatmap.setTrackVisible(_this.name, false, {
_this.isColumns); vector: _this
heatmap.revalidate(); .getFullVector()
} else if (item === DISPLAY_STACKED_BAR) { });
_this.settings.stackedBar = !_this.settings.stackedBar;
_this._update();
heatmap.revalidate();
} else { } else {
if (item === DISPLAY_BAR) { project
item = morpheus.VectorTrack.RENDER.BAR; .trigger(
} else if (item === DISPLAY_COLOR) { 'columnTrackRemoved',
item = morpheus.VectorTrack.RENDER.COLOR; {
} else if (item === DISPLAY_TEXT) { vector: _this
item = morpheus.VectorTrack.RENDER.TEXT; .getFullVector()
} else if (item === DISPLAY_TEXT_AND_COLOR) { });
item = morpheus.VectorTrack.RENDER.TEXT_AND_COLOR; }
} else if (item === DISPLAY_STRUCTURE) { }
item = morpheus.VectorTrack.RENDER.MOLECULE; });
} else if (item === DISPLAY_SHAPE) { } else if (item === CLEAR_SELECTION) {
item = morpheus.VectorTrack.RENDER.SHAPE; var model = isColumns ? project
} else if (item === DISPLAY_ARC) { .getColumnSelectionModel() : project
item = morpheus.VectorTrack.RENDER.ARC; .getRowSelectionModel();
} else { model.setViewIndices(new morpheus.Set(), true);
console.log('Unknown item ' + item); } else if (item === INVERT_SELECTION) {
} var model = isColumns ? project
var show = !_this.isRenderAs(item); .getColumnSelectionModel() : project
if (!show) { .getRowSelectionModel();
delete _this.settings.renderMethod[item]; var viewIndices = model.getViewIndices();
} else { var inverse = new morpheus.Set();
_this.settings.renderMethod[item] = true; for (var i = 0, n = positions.getLength(); i < n; i++) {
} if (!viewIndices.has(i)) {
_this._update(); inverse.add(i);
heatmap.revalidate(); }
}
model.setViewIndices(inverse, true);
} else if (item === FILTER) {
var vector = _this.getFullVector();
var filter;
var index = _this.isColumns ? _this.project
.getColumnFilter().indexOf(
vector.getName())
: _this.project.getRowFilter().indexOf(
vector.getName());
if (index === -1) {
if (morpheus.VectorUtil.isNumber(vector)
&& morpheus.VectorUtil
.containsMoreThanNValues(
vector, 9)) {
filter = new morpheus.RangeFilter(NaN,
NaN, vector.getName());
} else {
var set = morpheus.VectorUtil
.getSet(vector);
var array = set.values();
array
.sort(morpheus.SortKey.ASCENDING_COMPARATOR);
filter = new morpheus.VectorFilter(set,
set.size(), vector.getName());
}
if (filter) {
if (_this.isColumns) {
_this.project.getColumnFilter()
.add(filter, true);
} else {
_this.project.getRowFilter().add(
filter, true);
} }
}
}
if (_this.isColumns) {
_this.project.getColumnFilter().trigger(
'focus', {});
} else {
_this.project.getRowFilter().trigger(
'focus', {});
}
} else if (item === SORT_ASC || item === SORT_DESC) {
var sortKey = new morpheus.SortKey(
_this.name,
item === SORT_ASC ? morpheus.SortKey.SortOrder.ASCENDING
: morpheus.SortKey.SortOrder.DESCENDING);
if (_this.isColumns) {
_this.project
.setColumnSortKeys(
morpheus.SortKey
.keepExistingSortKeys(
[sortKey],
project
.getColumnSortKeys()),
true);
} else {
_this.project
.setRowSortKeys(
morpheus.SortKey
.keepExistingSortKeys(
[sortKey],
project
.getRowSortKeys()),
true);
}
} else if (item == SORT_SEL_ASC
|| item == SORT_SEL_DESC
|| item === SORT_SEL_TOP_N) {
var sortOrder;
if (item === SORT_SEL_ASC) {
sortOrder = morpheus.SortKey.SortOrder.ASCENDING;
} else if (item === SORT_SEL_DESC) {
sortOrder = morpheus.SortKey.SortOrder.DESCENDING;
} else {
sortOrder = morpheus.SortKey.SortOrder.TOP_N;
}
heatmap.sortBasedOnSelection(sortOrder,
isColumns, e && e.shiftKey);
} else if (item === SELECT_ALL) {
var selectionModel = !isColumns ? heatmap
.getProject().getRowSelectionModel()
: heatmap.getProject()
.getColumnSelectionModel();
var count = !isColumns ? heatmap.getProject()
.getSortedFilteredDataset()
.getRowCount() : heatmap.getProject()
.getSortedFilteredDataset()
.getColumnCount();
var indices = new morpheus.Set();
for (var i = 0; i < count; i++) {
indices.add(i);
}
selectionModel.setViewIndices(indices, true);
} else if (item === 'Auto Range') {
delete _this.settings.min;
delete _this.settings.max;
delete _this.settings.mid;
_this._update();
heatmap.revalidate();
} else if (item === 'Custom Range...') {
var formBuilder = new morpheus.FormBuilder();
var items = [{
name: 'min',
required: true,
type: 'number',
value: _this.settings.min
}, {
name: 'mid',
required: true,
type: 'number',
value: _this.settings.mid
}, {
name: 'max',
required: true,
type: 'number',
value: _this.settings.max
}];
_.each(items, function (item) {
formBuilder.append(item);
});
morpheus.FormBuilder
.showOkCancel({
title: 'Range',
content: formBuilder.$form,
okCallback: function () {
_this.settings.min = parseFloat(formBuilder
.getValue('min'));
_this.settings.mid = parseFloat(formBuilder
.getValue('mid'));
_this.settings.max = parseFloat(formBuilder
.getValue('max'));
_this._update();
heatmap.revalidate();
}
});
} else if (item === 'Squished') {
_this.settings.squished = !_this.settings.squished;
heatmap.revalidate();
} else if (item === 'Color Key') {
var legend = new morpheus.HeatMapTrackColorLegend(
[_this], isColumns ? _this.project
.getColumnColorModel()
: _this.project
.getRowColorModel());
var size = legend.getPreferredSize();
legend.setBounds(size);
legend.repaint();
morpheus.FormBuilder.showInModal({
title: 'Color Key',
html: legend.canvas
});
} else if (item === 'Shape Key') {
var legend = new morpheus.HeatMapTrackShapeLegend(
[_this], isColumns ? _this.project
.getColumnShapeModel()
: _this.project
.getRowShapeModel());
var size = legend.getPreferredSize();
legend.setBounds(size);
legend.repaint();
morpheus.FormBuilder.showInModal({
title: 'Shape Key',
html: legend.canvas
});
} else if (item === 'Edit Shapes...') {
var shapeFormBuilder = new morpheus.FormBuilder();
var shapeModel = isColumns ? _this.project
.getColumnShapeModel() : _this.project
.getRowShapeModel();
var chooser = new morpheus.ShapeChooser({
map: shapeModel.getMap(_this.name)
});
chooser.on('change', function (event) {
shapeModel.setMappedValue(_this
.getFullVector(), event.value,
event.shape);
_this.setInvalid(true);
_this.repaint();
});
morpheus.FormBuilder.showInModal({
title: 'Edit Shapes',
html: chooser.$div,
close: 'Close'
});
} else if (item === 'Edit Colors...') {
var colorSchemeChooser;
var colorModel = isColumns ? _this.project
.getColumnColorModel() : _this.project
.getRowColorModel();
if (_this.settings.discrete) {
colorSchemeChooser = new morpheus.DiscreteColorSchemeChooser(
{
colorScheme: {
scale: colorModel
.getDiscreteColorScheme(_this
.getFullVector())
}
});
colorSchemeChooser.on('change', function (event) {
colorModel.setMappedValue(_this
.getFullVector(), event.value,
event.color);
_this.setInvalid(true);
_this.repaint();
}); });
} else {
colorSchemeChooser = new morpheus.HeatMapColorSchemeChooser(
{
showRelative: false,
});
colorSchemeChooser
.setColorScheme(colorModel
.getContinuousColorScheme(_this
.getFullVector()));
colorSchemeChooser.on('change', function (event) {
_this.setInvalid(true);
_this.repaint();
});
}
morpheus.FormBuilder.showInModal({
title: 'Edit Colors',
html: colorSchemeChooser.$div,
close: 'Close',
callback: function () {
colorSchemeChooser.dispose();
}
});
} else if (item === TOOLTIP) {
_this.settings.inlineTooltip = !_this.settings.inlineTooltip;
} else if (item === HIGHLIGHT_MATCHING_VALUES) {
_this.settings.highlightMatchingValues = !_this.settings.highlightMatchingValues;
} else if ((customItem = _
.find(
customItems,
function (customItem) {
return customItem.name === item
&& customItem.columns === isColumns;
}))) {
if (customItem.task) {
// add task
var task = {
tabId: _this.heatmap.getTabManager()
.getActiveTabId()
};
_this.heatmap.getTabManager().addTask(task);
setTimeout(function () {
try {
customItem.callback(heatmap);
} catch (x) {
}
_this.heatmap.getTabManager()
.removeTask(task);
}, 1);
} else {
customItem.callback(heatmap);
}
} else if (item === DISPLAY_CONTINUOUS) {
_this.settings.discrete = !_this.settings.discrete;
_this._setChartMinMax();
_this.setInvalid(true);
_this.repaint();
} else if (item === HIDE) {
heatmap.setTrackVisible(_this.name, false,
_this.isColumns);
heatmap.revalidate();
} else if (item === DISPLAY_STACKED_BAR) {
_this.settings.stackedBar = !_this.settings.stackedBar;
_this._update();
heatmap.revalidate();
} else {
if (item === DISPLAY_BAR) {
item = morpheus.VectorTrack.RENDER.BAR;
} else if (item === DISPLAY_COLOR) {
item = morpheus.VectorTrack.RENDER.COLOR;
} else if (item === DISPLAY_TEXT) {
item = morpheus.VectorTrack.RENDER.TEXT;
} else if (item === DISPLAY_TEXT_AND_COLOR) {
item = morpheus.VectorTrack.RENDER.TEXT_AND_COLOR;
} else if (item === DISPLAY_STRUCTURE) {
item = morpheus.VectorTrack.RENDER.MOLECULE;
} else if (item === DISPLAY_SHAPE) {
item = morpheus.VectorTrack.RENDER.SHAPE;
} else if (item === DISPLAY_ARC) {
item = morpheus.VectorTrack.RENDER.ARC;
} else {
console.log('Unknown item ' + item);
}
var show = !_this.isRenderAs(item);
if (!show) {
delete _this.settings.renderMethod[item];
} else {
_this.settings.renderMethod[item] = true;
}
_this._update();
heatmap.revalidate();
}
});
}, },
renderColor : function(context, vector, start, end, clip, offset, renderColor: function (context, vector, start, end, clip, offset,
continuous) { continuous) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
var colorModel = isColumns ? this.project.getColumnColorModel() var colorModel = isColumns ? this.project.getColumnColorModel()
: this.project.getRowColorModel(); : this.project.getRowColorModel();
var settings = this.settings; var settings = this.settings;
var canvasSize = isColumns ? this.getUnscaledHeight() : this var canvasSize = isColumns ? this.getUnscaledHeight() : this
.getUnscaledWidth(); .getUnscaledWidth();
if (settings.colorBarSize > canvasSize) { if (settings.colorBarSize > canvasSize) {
settings.colorBarSize = canvasSize >= 5 ? (canvasSize - 1) settings.colorBarSize = canvasSize >= 5 ? (canvasSize - 1)
: canvasSize; : canvasSize;
} }
var getColor; var getColor;
if (!continuous) { if (!continuous) {
...@@ -1729,7 +1764,7 @@ morpheus.VectorTrack.prototype = { ...@@ -1729,7 +1764,7 @@ morpheus.VectorTrack.prototype = {
if (isColumns) { if (isColumns) {
context.beginPath(); context.beginPath();
context.rect(position, offset - settings.colorBarSize, size, context.rect(position, offset - settings.colorBarSize, size,
settings.colorBarSize); settings.colorBarSize);
context.fill(); context.fill();
} else { } else {
context.beginPath(); context.beginPath();
...@@ -1738,17 +1773,17 @@ morpheus.VectorTrack.prototype = { ...@@ -1738,17 +1773,17 @@ morpheus.VectorTrack.prototype = {
} }
} }
}, },
renderShape : function(context, vector, start, end, clip, offset) { renderShape: function (context, vector, start, end, clip, offset) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
var shapeModel = isColumns ? this.project.getColumnShapeModel() var shapeModel = isColumns ? this.project.getColumnShapeModel()
: this.project.getRowShapeModel(); : this.project.getRowShapeModel();
var settings = this.settings; var settings = this.settings;
var canvasSize = isColumns ? this.getUnscaledHeight() : this var canvasSize = isColumns ? this.getUnscaledHeight() : this
.getUnscaledWidth(); .getUnscaledWidth();
if (settings.colorBarSize > canvasSize) { if (settings.colorBarSize > canvasSize) {
settings.colorBarSize = canvasSize >= 5 ? (canvasSize - 1) settings.colorBarSize = canvasSize >= 5 ? (canvasSize - 1)
: canvasSize; : canvasSize;
} }
context.fillStyle = 'black'; context.fillStyle = 'black';
context.strokeStyle = 'black'; context.strokeStyle = 'black';
...@@ -1771,19 +1806,19 @@ morpheus.VectorTrack.prototype = { ...@@ -1771,19 +1806,19 @@ morpheus.VectorTrack.prototype = {
} }
context.lineWidth = lineWidth; context.lineWidth = lineWidth;
}, },
renderArc : function(context, vector, start, end, clip, size) { renderArc: function (context, vector, start, end, clip, size) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
var project = this.project; var project = this.project;
context.save(); context.save();
context.lineWidth = 1; context.lineWidth = 1;
var scale = d3.scale.linear().domain([ 1, size ]).range([ 0.8, 1 ]) var scale = d3.scale.linear().domain([1, size]).range([0.8, 1])
.clamp(true); .clamp(true);
var fill = d3.scale.category20b(); var fill = d3.scale.category20b();
var valueToIndices = morpheus.VectorUtil var valueToIndices = morpheus.VectorUtil
.createValueToIndicesMap(vector); .createValueToIndicesMap(vector);
var total = positions.getPosition(positions.getLength() - 1) var total = positions.getPosition(positions.getLength() - 1)
+ positions.getItemSize(positions.getLength() - 1); + positions.getItemSize(positions.getLength() - 1);
context.translate(clip.x, clip.y); context.translate(clip.x, clip.y);
var width = clip.width; var width = clip.width;
var height = clip.height; var height = clip.height;
...@@ -1802,14 +1837,14 @@ morpheus.VectorTrack.prototype = { ...@@ -1802,14 +1837,14 @@ morpheus.VectorTrack.prototype = {
context.strokeStyle = fill(value); context.strokeStyle = fill(value);
var indices = valueToIndices.get(value); var indices = valueToIndices.get(value);
var pix = positions.getPosition(i) + positions.getItemSize(i) var pix = positions.getPosition(i) + positions.getItemSize(i)
/ 2; / 2;
for (var j = 0, nindices = indices.length; j < nindices; j++) { for (var j = 0, nindices = indices.length; j < nindices; j++) {
var viewIndex = indices[j]; var viewIndex = indices[j];
if (viewIndex === i) { if (viewIndex === i) {
continue; continue;
} }
var endPix = positions.getPosition(viewIndex) var endPix = positions.getPosition(viewIndex)
+ positions.getItemSize(viewIndex) / 2; + positions.getItemSize(viewIndex) / 2;
var midPix = (endPix + pix) / 2; var midPix = (endPix + pix) / 2;
var distance = Math.abs(i - viewIndex); var distance = Math.abs(i - viewIndex);
var arcRadius = size; // scale(distance) * size; var arcRadius = size; // scale(distance) * size;
...@@ -1831,14 +1866,14 @@ morpheus.VectorTrack.prototype = { ...@@ -1831,14 +1866,14 @@ morpheus.VectorTrack.prototype = {
} }
context.restore(); context.restore();
}, },
sdfToSvg : function(sdf, width, height) { sdfToSvg: function (sdf, width, height) {
if (!this.jsme && typeof JSApplet !== 'undefined') { if (!this.jsme && typeof JSApplet !== 'undefined') {
this.jsmeId = _.uniqueId('m'); this.jsmeId = _.uniqueId('m');
this.$jsmeDiv = $( this.$jsmeDiv = $(
'<div id="' '<div id="'
+ this.jsmeId + this.jsmeId
+ '" style="position:absolute;left:-10000px;top:-10000px;"></div>') + '" style="position:absolute;left:-10000px;top:-10000px;"></div>')
.appendTo($(document.body)); .appendTo($(document.body));
this.jsme = new JSApplet.JSME(this.jsmeId, '380px', '340px', {}); this.jsme = new JSApplet.JSME(this.jsmeId, '380px', '340px', {});
} }
// this.$jsmeDiv.css('width', width + 'px').css('height', height + // this.$jsmeDiv.css('width', width + 'px').css('height', height +
...@@ -1850,10 +1885,10 @@ morpheus.VectorTrack.prototype = { ...@@ -1850,10 +1885,10 @@ morpheus.VectorTrack.prototype = {
var svgHeight = svg.height.baseVal.value; var svgHeight = svg.height.baseVal.value;
var scale = Math.min(width / svgWidth, height / svgHeight); var scale = Math.min(width / svgWidth, height / svgHeight);
var text = '<svg><g transform="scale(' + scale + ')">' + svg.innerHTML var text = '<svg><g transform="scale(' + scale + ')">' + svg.innerHTML
+ '</g></svg>'; + '</g></svg>';
return text; return text;
}, },
renderMolecule : function(context, vector, start, end, clip, offset) { renderMolecule: function (context, vector, start, end, clip, offset) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
context.fillStyle = morpheus.CanvasUtil.FONT_COLOR; context.fillStyle = morpheus.CanvasUtil.FONT_COLOR;
...@@ -1861,8 +1896,8 @@ morpheus.VectorTrack.prototype = { ...@@ -1861,8 +1896,8 @@ morpheus.VectorTrack.prototype = {
var width = this.getUnscaledWidth(); var width = this.getUnscaledWidth();
var customUrlProvider = this.heatmap.options.structureUrlProvider !== undefined; var customUrlProvider = this.heatmap.options.structureUrlProvider !== undefined;
var dummyTarget = { var dummyTarget = {
childNodes : [], childNodes: [],
getContext : function() { getContext: function () {
return context; return context;
} }
}; };
...@@ -1871,7 +1906,7 @@ morpheus.VectorTrack.prototype = { ...@@ -1871,7 +1906,7 @@ morpheus.VectorTrack.prototype = {
if (spanEnd !== undefined) { if (spanEnd !== undefined) {
var startPix = positions.getPosition(i); var startPix = positions.getPosition(i);
var endPix = positions.getPosition(spanEnd - 1) var endPix = positions.getPosition(spanEnd - 1)
+ positions.getSize(); + positions.getSize();
var size = endPix - startPix; var size = endPix - startPix;
var value = vector.getValue(i); var value = vector.getValue(i);
var cache = this.moleculeCache[value]; var cache = this.moleculeCache[value];
...@@ -1880,14 +1915,14 @@ morpheus.VectorTrack.prototype = { ...@@ -1880,14 +1915,14 @@ morpheus.VectorTrack.prototype = {
if (cache.complete) { if (cache.complete) {
// 800 x 400 // 800 x 400
var scaleFactor = Math.min(size / cache.height, var scaleFactor = Math.min(size / cache.height,
width / cache.width); width / cache.width);
var scaledWidth = cache.width * scaleFactor; var scaledWidth = cache.width * scaleFactor;
var scaledHeight = cache.height * scaleFactor; var scaledHeight = cache.height * scaleFactor;
var diff = cache.height - scaledHeight; var diff = cache.height - scaledHeight;
startPix += diff / 2; startPix += diff / 2;
try { try {
context.drawImage(cache, offset, startPix, context.drawImage(cache, offset, startPix,
scaledWidth, scaledHeight); scaledWidth, scaledHeight);
} catch (x) { } catch (x) {
} }
...@@ -1895,35 +1930,35 @@ morpheus.VectorTrack.prototype = { ...@@ -1895,35 +1930,35 @@ morpheus.VectorTrack.prototype = {
} else { } else {
var text = this.sdfToSvg(cache, width, size); var text = this.sdfToSvg(cache, width, size);
canvg(dummyTarget, text, { canvg(dummyTarget, text, {
ignoreMouse : true, ignoreMouse: true,
ignoreAnimation : true, ignoreAnimation: true,
offsetY : startPix, offsetY: startPix,
ignoreClear : true, ignoreClear: true,
ignoreDimensions : true ignoreDimensions: true
}); });
} }
} }
} }
} }
}, },
createChartScale : function(availableSpace) { createChartScale: function (availableSpace) {
var domain; var domain;
var range; var range;
if (this.settings.mid !== this.settings.min if (this.settings.mid !== this.settings.min
&& this.settings.mid !== this.settings.max) { && this.settings.mid !== this.settings.max) {
domain = [ this.settings.min, this.settings.mid, this.settings.max ]; domain = [this.settings.min, this.settings.mid, this.settings.max];
range = this.isColumns ? [ availableSpace, availableSpace / 2, 0 ] range = this.isColumns ? [availableSpace, availableSpace / 2, 0]
: [ 0, availableSpace / 2, availableSpace ]; : [0, availableSpace / 2, availableSpace];
} else { } else {
domain = [ this.settings.min, this.settings.max ]; domain = [this.settings.min, this.settings.max];
range = this.isColumns ? [ availableSpace, 0 ] : [ 0, range = this.isColumns ? [availableSpace, 0] : [0,
availableSpace ]; availableSpace];
} }
var scale = d3.scale.linear().domain(domain).range(range).clamp(true); var scale = d3.scale.linear().domain(domain).range(range).clamp(true);
return scale; return scale;
}, },
renderBar : function(context, vector, start, end, clip, offset, renderBar: function (context, vector, start, end, clip, offset,
availableSpace) { availableSpace) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
context.fillStyle = this.settings.barColor; context.fillStyle = this.settings.barColor;
...@@ -1942,18 +1977,18 @@ morpheus.VectorTrack.prototype = { ...@@ -1942,18 +1977,18 @@ morpheus.VectorTrack.prototype = {
if (isColumns) { if (isColumns) {
context.beginPath(); context.beginPath();
context.rect(position, Math.min(midPix, scaledValue), size, context.rect(position, Math.min(midPix, scaledValue), size,
Math.abs(midPix - scaledValue)); Math.abs(midPix - scaledValue));
context.fill(); context.fill();
} else { } else {
context.beginPath(); context.beginPath();
context.rect(offset + Math.min(midPix, scaledValue), position, context.rect(offset + Math.min(midPix, scaledValue), position,
Math.abs(midPix - scaledValue), size); Math.abs(midPix - scaledValue), size);
context.fill(); context.fill();
} }
} }
}, },
renderBoxPlot : function(context, vector, start, end, clip, offset, renderBoxPlot: function (context, vector, start, end, clip, offset,
availableSpace) { availableSpace) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
context.strokeStyle = 'black'; context.strokeStyle = 'black';
...@@ -1961,16 +1996,16 @@ morpheus.VectorTrack.prototype = { ...@@ -1961,16 +1996,16 @@ morpheus.VectorTrack.prototype = {
context.translate(offset, 0); context.translate(offset, 0);
var scale = this.createChartScale(availableSpace); var scale = this.createChartScale(availableSpace);
var visibleFieldIndices = vector.getProperties().get( var visibleFieldIndices = vector.getProperties().get(
morpheus.VectorKeys.VISIBLE_FIELDS); morpheus.VectorKeys.VISIBLE_FIELDS);
if (visibleFieldIndices == null) { if (visibleFieldIndices == null) {
visibleFieldIndices = morpheus.Util.seq(vector.getProperties().get( visibleFieldIndices = morpheus.Util.seq(vector.getProperties().get(
morpheus.VectorKeys.FIELDS).length); morpheus.VectorKeys.FIELDS).length);
} }
var colorByVector = this.settings.colorByField != null ? this var colorByVector = this.settings.colorByField != null ? this
.getVector(this.settings.colorByField) : null; .getVector(this.settings.colorByField) : null;
var colorModel = isColumns ? this.project.getColumnColorModel() var colorModel = isColumns ? this.project.getColumnColorModel()
: this.project.getRowColorModel(); : this.project.getRowColorModel();
for (var i = start; i < end; i++) { for (var i = start; i < end; i++) {
var array = vector.getValue(i); var array = vector.getValue(i);
if (array != null) { if (array != null) {
...@@ -1989,9 +2024,9 @@ morpheus.VectorTrack.prototype = { ...@@ -1989,9 +2024,9 @@ morpheus.VectorTrack.prototype = {
if (box == null) { if (box == null) {
var v = morpheus.VectorUtil.arrayAsVector(array); var v = morpheus.VectorUtil.arrayAsVector(array);
box = morpheus box = morpheus
.BoxPlotItem(visibleFieldIndices != null ? new morpheus.SlicedVector( .BoxPlotItem(visibleFieldIndices != null ? new morpheus.SlicedVector(
v, visibleFieldIndices) v, visibleFieldIndices)
: v); : v);
array.box = box; array.box = box;
} }
context.fillStyle = '#bdbdbd'; context.fillStyle = '#bdbdbd';
...@@ -1999,18 +2034,18 @@ morpheus.VectorTrack.prototype = { ...@@ -1999,18 +2034,18 @@ morpheus.VectorTrack.prototype = {
if (!isColumns) { if (!isColumns) {
// box from q1 (25th q) to q3 // box from q1 (25th q) to q3
context.fillRect(Math.min(scale(box.q1), scale(box.q3)), context.fillRect(Math.min(scale(box.q1), scale(box.q3)),
start, Math.abs(scale(box.q1) - scale(box.q3)), start, Math.abs(scale(box.q1) - scale(box.q3)),
_itemSize); _itemSize);
// draw line from q1 to lav // draw line from q1 to lav
context.fillRect(Math.min(scale(box.q1), context.fillRect(Math.min(scale(box.q1),
scale(box.lowerAdjacentValue)), center - lineHeight scale(box.lowerAdjacentValue)), center - lineHeight
/ 2, Math.abs(scale(box.q1) / 2, Math.abs(scale(box.q1)
- scale(box.lowerAdjacentValue)), lineHeight); - scale(box.lowerAdjacentValue)), lineHeight);
// draw line from q3 to uav // draw line from q3 to uav
context.fillRect(Math.min(scale(box.q3), context.fillRect(Math.min(scale(box.q3),
scale(box.upperAdjacentValue)), center - lineHeight scale(box.upperAdjacentValue)), center - lineHeight
/ 2, Math.abs(scale(box.q3) / 2, Math.abs(scale(box.q3)
- scale(box.upperAdjacentValue)), lineHeight); - scale(box.upperAdjacentValue)), lineHeight);
// points // points
context.fillStyle = '#636363'; context.fillStyle = '#636363';
...@@ -2021,9 +2056,9 @@ morpheus.VectorTrack.prototype = { ...@@ -2021,9 +2056,9 @@ morpheus.VectorTrack.prototype = {
var colorByArray = colorByVector.getValue(i); var colorByArray = colorByVector.getValue(i);
if (colorByArray != null) { if (colorByArray != null) {
var color = colorModel var color = colorModel
.getMappedValue( .getMappedValue(
colorByVector, colorByVector,
colorByArray[visibleFieldIndices[j]]); colorByArray[visibleFieldIndices[j]]);
context.fillStyle = color; context.fillStyle = color;
} else { } else {
context.fillStyle = '#636363'; context.fillStyle = '#636363';
...@@ -2033,8 +2068,8 @@ morpheus.VectorTrack.prototype = { ...@@ -2033,8 +2068,8 @@ morpheus.VectorTrack.prototype = {
var pix = scale(value); var pix = scale(value);
context.beginPath(); context.beginPath();
context context
.arc(pix, center, radius, Math.PI * 2, .arc(pix, center, radius, Math.PI * 2,
false); false);
context.fill(); context.fill();
} }
} }
...@@ -2047,8 +2082,8 @@ morpheus.VectorTrack.prototype = { ...@@ -2047,8 +2082,8 @@ morpheus.VectorTrack.prototype = {
} }
context.restore(); context.restore();
}, },
renderStackedBar : function(context, vector, start, end, clip, offset, renderStackedBar: function (context, vector, start, end, clip, offset,
availableSpace) { availableSpace) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
...@@ -2056,12 +2091,12 @@ morpheus.VectorTrack.prototype = { ...@@ -2056,12 +2091,12 @@ morpheus.VectorTrack.prototype = {
var midPix = scale(this.settings.mid); var midPix = scale(this.settings.mid);
var settings = this.settings; var settings = this.settings;
var colorModel = isColumns ? this.project.getColumnColorModel() var colorModel = isColumns ? this.project.getColumnColorModel()
: this.project.getRowColorModel(); : this.project.getRowColorModel();
var selectionModel = isColumns ? this.project.getRowSelectionModel() var selectionModel = isColumns ? this.project.getRowSelectionModel()
: null; : null;
var selectedModelIndices = selectionModel == null ? [] : selectionModel var selectedModelIndices = selectionModel == null ? [] : selectionModel
.toModelIndices(); .toModelIndices();
context.strokeStyle = 'black'; context.strokeStyle = 'black';
context.lineWidth = 2; context.lineWidth = 2;
for (var i = start; i < end; i++) { for (var i = start; i < end; i++) {
...@@ -2071,7 +2106,7 @@ morpheus.VectorTrack.prototype = { ...@@ -2071,7 +2106,7 @@ morpheus.VectorTrack.prototype = {
if (array.modelIndexToBin != null) { if (array.modelIndexToBin != null) {
for (var j = 0; j < selectedModelIndices.length; j++) { for (var j = 0; j < selectedModelIndices.length; j++) {
var bin = array.modelIndexToBin var bin = array.modelIndexToBin
.get(selectedModelIndices[j]); .get(selectedModelIndices[j]);
if (bin !== undefined) { if (bin !== undefined) {
selectedBins.add(bin); selectedBins.add(bin);
} }
...@@ -2086,19 +2121,19 @@ morpheus.VectorTrack.prototype = { ...@@ -2086,19 +2121,19 @@ morpheus.VectorTrack.prototype = {
var value = array[j]; var value = array[j];
if (value >= this.settings.mid) { if (value >= this.settings.mid) {
positivePairs.push({ positivePairs.push({
value : value, value: value,
index : j index: j
}); });
} else if (value < 0) { } else if (value < 0) {
negativePairs.push({ negativePairs.push({
value : value, value: value,
index : j index: j
}); });
} }
} }
var positiveIndices = morpheus.Util.indexSortPairs( var positiveIndices = morpheus.Util.indexSortPairs(
positivePairs, false); // draw bigger values 1st positivePairs, false); // draw bigger values 1st
for (var j = 0, length = positiveIndices.length; j < length; j++) { for (var j = 0, length = positiveIndices.length; j < length; j++) {
var index = positiveIndices[j]; var index = positiveIndices[j];
var value = array[index]; var value = array[index];
...@@ -2106,19 +2141,19 @@ morpheus.VectorTrack.prototype = { ...@@ -2106,19 +2141,19 @@ morpheus.VectorTrack.prototype = {
context.fillStyle = color; context.fillStyle = color;
var scaledValue = scale(value); var scaledValue = scale(value);
var nextScaledValue = j === (length - 1) ? midPix var nextScaledValue = j === (length - 1) ? midPix
: scale(array[positiveIndices[j + 1]]); : scale(array[positiveIndices[j + 1]]);
if (isColumns) { if (isColumns) {
context.beginPath(); context.beginPath();
context.rect(position, Math.min(nextScaledValue, context.rect(position, Math.min(nextScaledValue,
scaledValue), size, Math.abs(nextScaledValue scaledValue), size, Math.abs(nextScaledValue
- scaledValue)); - scaledValue));
context.fill(); context.fill();
} else { } else {
context.beginPath(); context.beginPath();
context.rect(offset context.rect(offset
+ Math.min(nextScaledValue, scaledValue), + Math.min(nextScaledValue, scaledValue),
position, Math.abs(nextScaledValue position, Math.abs(nextScaledValue
- scaledValue), size); - scaledValue), size);
context.fill(); context.fill();
} }
if (selectedBins.has(index)) { if (selectedBins.has(index)) {
...@@ -2131,7 +2166,7 @@ morpheus.VectorTrack.prototype = { ...@@ -2131,7 +2166,7 @@ morpheus.VectorTrack.prototype = {
} }
} }
var negativeIndices = morpheus.Util.indexSortPairs( var negativeIndices = morpheus.Util.indexSortPairs(
negativePairs, true); // draw smaller (more negative) negativePairs, true); // draw smaller (more negative)
// values 1st // values 1st
for (var j = 0, length = negativeIndices.length; j < length; j++) { for (var j = 0, length = negativeIndices.length; j < length; j++) {
var index = negativeIndices[j]; var index = negativeIndices[j];
...@@ -2140,19 +2175,19 @@ morpheus.VectorTrack.prototype = { ...@@ -2140,19 +2175,19 @@ morpheus.VectorTrack.prototype = {
context.fillStyle = color; context.fillStyle = color;
var scaledValue = scale(value); var scaledValue = scale(value);
var nextScaledValue = j === (length - 1) ? midPix var nextScaledValue = j === (length - 1) ? midPix
: scale(array[negativeIndices[j + 1]]); : scale(array[negativeIndices[j + 1]]);
if (isColumns) { if (isColumns) {
context.beginPath(); context.beginPath();
context.rect(position, Math.min(nextScaledValue, context.rect(position, Math.min(nextScaledValue,
scaledValue), size, Math.abs(nextScaledValue scaledValue), size, Math.abs(nextScaledValue
- scaledValue)); - scaledValue));
context.fill(); context.fill();
} else { } else {
context.beginPath(); context.beginPath();
context.rect(offset context.rect(offset
+ Math.min(nextScaledValue, scaledValue), + Math.min(nextScaledValue, scaledValue),
position, Math.abs(nextScaledValue position, Math.abs(nextScaledValue
- scaledValue), size); - scaledValue), size);
context.fill(); context.fill();
} }
if (selectedBins.has(index)) { if (selectedBins.has(index)) {
...@@ -2168,20 +2203,20 @@ morpheus.VectorTrack.prototype = { ...@@ -2168,20 +2203,20 @@ morpheus.VectorTrack.prototype = {
} }
context.lineWidth = 1; context.lineWidth = 1;
}, },
renderUnstackedBar : function(context, vector, start, end, clip, offset, renderUnstackedBar: function (context, vector, start, end, clip, offset,
availableSpace, fieldIndices) { availableSpace, fieldIndices) {
var isColumns = this.isColumns; var isColumns = this.isColumns;
var positions = this.positions; var positions = this.positions;
var nvalues = fieldIndices.length; var nvalues = fieldIndices.length;
var settings = this.settings; var settings = this.settings;
var colorModel = isColumns ? this.project.getColumnColorModel() var colorModel = isColumns ? this.project.getColumnColorModel()
: this.project.getRowColorModel(); : this.project.getRowColorModel();
context.fillStyle = this.settings.barColor; context.fillStyle = this.settings.barColor;
// context.strokeStyle = '0000f0'; // context.strokeStyle = '0000f0';
var barSpacer = 0; var barSpacer = 0;
var barWidth = (availableSpace - (nvalues - 1) * barSpacer) / nvalues; var barWidth = (availableSpace - (nvalues - 1) * barSpacer) / nvalues;
var colorByVector = this.settings.colorByField != null ? this var colorByVector = this.settings.colorByField != null ? this
.getVector(this.settings.colorByField) : null; .getVector(this.settings.colorByField) : null;
context.strokeStyle = 'white'; context.strokeStyle = 'white';
for (var i = start; i < end; i++) { for (var i = start; i < end; i++) {
var array = vector.getValue(i); var array = vector.getValue(i);
...@@ -2197,10 +2232,10 @@ morpheus.VectorTrack.prototype = { ...@@ -2197,10 +2232,10 @@ morpheus.VectorTrack.prototype = {
if (colorByVector != null) { if (colorByVector != null) {
var colorByArray = colorByVector.getValue(i); var colorByArray = colorByVector.getValue(i);
var color = colorModel var color = colorModel
.getMappedValue( .getMappedValue(
colorByVector, colorByVector,
colorByArray != null ? colorByArray[fieldIndices[j]] colorByArray != null ? colorByArray[fieldIndices[j]]
: null); : null);
context.fillStyle = color; context.fillStyle = color;
} }
...@@ -2209,15 +2244,15 @@ morpheus.VectorTrack.prototype = { ...@@ -2209,15 +2244,15 @@ morpheus.VectorTrack.prototype = {
if (isColumns) { if (isColumns) {
context.beginPath(); context.beginPath();
context.rect(Math.min(midPix, scaledValue), offset context.rect(Math.min(midPix, scaledValue), offset
+ xpix, Math.abs(midPix - scaledValue), + xpix, Math.abs(midPix - scaledValue),
barWidth); barWidth);
context.fill(); context.fill();
} else { } else {
// bar always goes to midpix // bar always goes to midpix
context.beginPath(); context.beginPath();
var barHeight = Math.abs(midPix - scaledValue); var barHeight = Math.abs(midPix - scaledValue);
var ypix = position + itemSize var ypix = position + itemSize
- Math.max(midPix, scaledValue); - Math.max(midPix, scaledValue);
context.rect(offset + xpix, ypix, barWidth, barHeight); context.rect(offset + xpix, ypix, barWidth, barHeight);
context.fill(); context.fill();
...@@ -2230,18 +2265,18 @@ morpheus.VectorTrack.prototype = { ...@@ -2230,18 +2265,18 @@ morpheus.VectorTrack.prototype = {
} }
}, },
renderText : function(context, vector, isColor, start, end, clip, offset, renderText: function (context, vector, isColor, start, end, clip, offset,
canvasSize) { canvasSize) {
context.fillStyle = morpheus.CanvasUtil.FONT_COLOR; context.fillStyle = morpheus.CanvasUtil.FONT_COLOR;
context.textBaseline = 'middle'; context.textBaseline = 'middle';
var positions = this.positions; var positions = this.positions;
var isColumns = this.isColumns; var isColumns = this.isColumns;
var colorModel = isColumns ? this.project.getColumnColorModel() var colorModel = isColumns ? this.project.getColumnColorModel()
: this.project.getRowColorModel(); : this.project.getRowColorModel();
if (isColumns) { if (isColumns) {
context.translate(clip.x, clip.y); // reset transform context.translate(clip.x, clip.y); // reset transform, needed for export to svg
} }
var toStringFunction = morpheus.VectorTrack.vectorToString(vector); var toStringFunction = morpheus.VectorTrack.vectorToString(vector);
for (var i = start; i < end; i++) { for (var i = start; i < end; i++) {
...@@ -2255,12 +2290,12 @@ morpheus.VectorTrack.prototype = { ...@@ -2255,12 +2290,12 @@ morpheus.VectorTrack.prototype = {
var position = positions.getPosition(i); var position = positions.getPosition(i);
if (isColor) { if (isColor) {
context.fillStyle = colorModel context.fillStyle = colorModel
.getMappedValue(vector, value); .getMappedValue(vector, value);
} }
if (isColumns) { if (isColumns) {
context.save(); context.save();
context.translate(position + size / 2 - clip.x, canvasSize context.translate(position + size / 2 - clip.x, canvasSize
- clip.y - offset); - clip.y - offset);
context.rotate(-Math.PI / 2); context.rotate(-Math.PI / 2);
context.fillText(value, 0, 0); context.fillText(value, 0, 0);
context.restore(); context.restore();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment