<commit_before>class TabPaper{
	constructor(w=900,h=900*1.41,bps=4,bl=4,lw=840,lh=140){
		this.width=w;
		this.height=h;
		this.lineHeight=lh;
		this.lineWidth=lw;
		this.beatLength=bl;
		this.beatPerSection=bps;
		this.vHTML="";
		this.st=0;
		this.scale=1;
		this.animatInfo=[0,0,0];//start time,elapsed time,frame
		this.content=document.createElement('div');
		this.content.style.outline="none";
		this.content.onselectstart=function(){return false;}
		this.content.setAttribute('tabindex','1');
		this.grab=(function(e){
			this.displayer.scrollTop+=this.my-e.screenY;
			this.displayer.scrollLeft+=this.mx-e.screenX;
			this.my=e.screenY;
			this.mx=e.screenX;
			this.st=this.displayer.scrollTop;
			this.sl=this.displayer.scrollLeft;
		}).bind(this);
		this.content.addEventListener("mousedown",(e)=>{
			this.my=e.screenY;
			this.mx=e.screenX;
			console.log("fuck");
			this.content.addEventListener("mousemove",this.grab);
		});
		document.addEventListener("mouseup",()=>{
			this.content.removeEventListener("mousemove",this.grab);
		});
		this.content.addEventListener("click",this.ckEvent.bind(this));
		this.content.addEventListener("keydown",this.kdEvent.bind(this));
		this.data=null;
		this.sel=[];
		this.check();
	}
	check(){
		if(this.width<500)this.width=500;
		if(this.height<500)this.height=500;
		if(this.lineHeight>300)this.lineHeight=120;
		if(this.lineWidth>this.width)this.lineWidth=this.width-60;
	}
	render(){
		this.vHTML="";
		let nx=(this.width-this.lineWidth)/2,ix=nx,iy=60,time=0;
		if(!this.data){
			this.drawLine(ix,iy);
			this.vHTML=`

			<svg width="${this.width}" height="${this.height}"
			style="background:#FFFFFF";>`
			+this.vHTML+"</svg>
";
			this.content.innerHTML=this.vHTML;
			this.zoom();
			return;
		}
		this.drawLine(ix,iy);
		ix+=80;

		for(let i=0;i<this.data.length;i++){
			this.drawNote(ix,iy,i,this.data[i][0],this.data[i].slice(1));
			time+=this.beatLength/this.data[i][0];
			if(time>this.beatPerSection){
				this.drawAlert(ix,iy);
				time=this.beatPerSection;
			}
			if(time==this.beatPerSection){
				ix+=20;
				if(ix<nx+this.lineWidth)this.drawBar(ix,iy);
				ix+=20;
				time=0;
			}else{
				ix+=80*this.beatLength/this.data[i][0];
			}
			if(ix>=nx+this.lineWidth){
				ix=nx,iy+=this.lineHeight;
				this.drawLine(ix,iy);
				ix+=80;
			}
		}
		this.vHTML=`

				<svg width="${this.width}" height="${this.height}"
			style="background:#FFFFFF";>`
			+this.vHTML+"</svg>
";
		this.content.innerHTML=this.vHTML;
		this.zoom();
	}

	setDisplayer(e){
		this.displayer=e;
	}

	zoom(){
		for(let i=0;i<this.content.children.length;i++){
			this.content.children[0].style.width=this.width*this.scale+6+"px";
			this.content.children[0].style.height=this.height*this.scale+6+"px";
			this.content.children[0].style.margin="auto";
			this.content.children[0].children[0].style.transformOrigin="0% 0%";
			this.content.children[0].children[0].style.transform=`scale(${this.scale},${this.scale})`;
		}
	}

	animate(){
		this.animatInfo=[0,0,0];
		requestAnimationFrame(this.animateFrame.bind(this));
	}

	animateFrame(t){
		var frametime=500;
		if(this.animatInfo[0]==0){
			this.animatInfo[0]=t;
			this.aData=this.data;
			this.data=[];
		}
		this.animatInfo[1]=t-this.animatInfo[0]-this.animatInfo[2]*frametime;
		if(this.animatInfo[1]>=frametime){
			this.animatInfo[1]=0;
			this.animatInfo[2]++;
			this.data=this.aData.slice(0,this.animatInfo[2]);
			this.render();
		}
		if(this.data.length!=this.aData.length){requestAnimationFrame(this.animateFrame.bind(this));}
		else{console.log("animation end");}
	}

	selNote(pos,id){
		this.sel[0]=[pos,id];
		this.render();
	}

	ckEvent(e){
		if(e.target.getAttribute('data-type')=='nt'){
			var pos=e.target.getAttribute('data-pos');
			var id=e.target.getAttribute('data-i');
			this.selNote(pos,id);
		}
	}

	zoomIn(){
		if(this.scale<2.0){
			this.scale+=0.1;
			this.zoom();
		}
	}

	zoomOut(){
		if(this.scale>0.3){
			this.scale-=0.1;
			this.render();
		}
	}

	setScale(s){
		if(s<=2.0 && s>=0.3)this.scale=s;
	}

	kdEvent(e){
		if(e.keyCode==107){
			if(this.sel.length>0){
				this.data[this.sel[0][0]][this.sel[0][1]*2+1+1]++;
				this.render();
			}
		}
		if(e.keyCode==109){
			if(this.sel.length>0){
				var p=this.sel[0][0];
				var id=this.sel[0][1];
				if(this.data[p][id*2+1+1]>0)this.data[p][id*2+1+1]--;
				this.render();
			}
		}
		if(e.keyCode==87){
			if(this.sel.length>0){
				var p=this.sel[0][0];
				var id=this.sel[0][1];
				if(this.data[p][id*2+1]>1)this.data[p][id*2+1]--;
				this.render();
			}
		}
		if(e.keyCode==83){
			if(this.sel.length>0){
				var p=this.sel[0][0];
				var id=this.sel[0][1];
				if(this.data[p][id*2+1]<6)this.data[p][id*2+1]++;
				this.render();
			}
		}
	}

	load(data){
		this.data=data;
	}

	drawBar(x,y){
		this.vHTML+=`<path d='M${x} ${y} l0 70'
		style='stroke:black;stroke-width:1'></path>`;
	}

	drawAlert(x,y){
		this.vHTML+=`<circle cx='${x}' cy='${y-14}' r='5'
		fill='red' stroke-width='0' stroke='red'></circle>`;
	};

	drawLine(x,y){
		this.vHTML+='<svg  stroke-linecap="square" >'
		for(let i=0;i<6;i++){
			this.vHTML+=`<line x1='${x}' y1='${y+i*14}' x2='${x+this.lineWidth}' y2='${y+i*14}'
				style="stroke:black;stroke-width:1"
			></line>`;
		}
		this.vHTML+=`<text style='fill:black;font:bold 22px Sans-serif'>
		<tspan x='${x+10}' y='${y+21}'>T</tspan>
		<tspan x='${x+10}' y='${y+21+21}'>A</tspan>
		<tspan x='${x+10}' y='${y+42+21}'>B</tspan>
		</text>`;
		this.vHTML+=`<text style='fill:black;font:bold 24px serif'>
		<tspan x='${x+33}' y='${y+28}'>${this.beatPerSection}</tspan>
		<tspan x='${x+33}' y='${y+23+28}'>${this.beatLength}</tspan>
		</text>`;
		this.vHTML+=`<path d='M${x} ${y} l0 70 M${x+this.lineWidth} ${y} l0 70'
		style='stroke:black;stroke-width:1'></path>`;
		this.vHTML=this.vHTML+'</svg>';
	}

	drawNote(x,y,pos,length,data){//data=[chord,block,chord,block.....]
		this.vHTML+='<svg>';
		for(let i=0;i<data.length/2;i++){
			this.vHTML+=`<circle cx='${x}' cy='${y+14*(data[i*2]-1)}' r='5' data-type="nt" data-pos="${pos}" data-i="${i}"
			fill='white' stroke-width='0' stroke='black' style='cursor:pointer;'></circle>`;
			this.vHTML+=`<text data-type="nt" data-pos="${pos}" data-i="${i}" x='${x-4}' y='${y+14*(data[i*2]-1)+5}'
			fill='black' style='font-size:14px;cursor:pointer;'>${data[i*2+1]}</text>`;
		}

		this.vHTML+=`<path d='M${x} ${y+78} l0 25' stroke-width='1' stroke='black'></path>`;
		if(length>this.beatLength){
			this.vHTML+=`<path d='M${x} ${y+102} l6 1' stroke-width='2' stroke='black'></path>`;
		}
		if(length>this.beatLength*2){
			var j=1;
			for(let i=this.beatLength*2;i<length;i*=2){
				this.vHTML+=`<path d='M${x} ${y+102-4*j} l6 1' stroke-width='1' stroke='black'></path>`;
				j++;
			}
		}
		for(let i=0;i<this.sel.length;i++){
			if(this.sel[i][0]==pos){
				this.vHTML+=`<circle cx='${x}' cy='${y+14*(data[(this.sel[i][1])*2]-1)}' r='7' fill='rgb(80,255,80)' stroke-width='0' stroke='black'></circle>`;
				this.vHTML+=`<text data-type="nt" data-pos="${pos}" data-i="${i}" x='${x-4}'
					y='${y+14*(data[(this.sel[i][1])*2]-1)+5}' fill='black' style='font-size:14px'>
					${data[(this.sel[i][1])*2+1]}</text>`;
			}
		}
		this.vHTML+='</svg>';
	}
}<commit_msg>remove grab function<commit_after>class TabPaper{
	constructor(w=900,h=900*1.41,bps=4,bl=4,lw=840,lh=140){
		this.width=w;
		this.height=h;
		this.lineHeight=lh;
		this.lineWidth=lw;
		this.beatLength=bl;
		this.beatPerSection=bps;
		this.vHTML="";
		this.st=0;
		this.scale=1;
		this.animatInfo=[0,0,0];//start time,elapsed time,frame
		this.content=document.createElement('div');
		this.content.style.outline="none";
		this.content.onselectstart=function(){return false;}
		this.content.setAttribute('tabindex','1');
		this.content.addEventListener("click",this.ckEvent.bind(this));
		this.content.addEventListener("keydown",this.kdEvent.bind(this));
		this.data=null;
		this.sel=[];
		this.check();
	}
	check(){
		if(this.width<500)this.width=500;
		if(this.height<500)this.height=500;
		if(this.lineHeight>300)this.lineHeight=120;
		if(this.lineWidth>this.width)this.lineWidth=this.width-60;
	}
	render(){
		this.vHTML="";
		let nx=(this.width-this.lineWidth)/2,ix=nx,iy=60,time=0;
		if(!this.data){
			this.drawLine(ix,iy);
			this.vHTML=`

			<svg width="${this.width}" height="${this.height}"
			style="background:#FFFFFF";>`
			+this.vHTML+"</svg>
";
			this.content.innerHTML=this.vHTML;
			this.zoom();
			return;
		}
		this.drawLine(ix,iy);
		ix+=80;

		for(let i=0;i<this.data.length;i++){
			this.drawNote(ix,iy,i,this.data[i][0],this.data[i].slice(1));
			time+=this.beatLength/this.data[i][0];
			if(time>this.beatPerSection){
				this.drawAlert(ix,iy);
				time=this.beatPerSection;
			}
			if(time==this.beatPerSection){
				ix+=20;
				if(ix<nx+this.lineWidth)this.drawBar(ix,iy);
				ix+=20;
				time=0;
			}else{
				ix+=80*this.beatLength/this.data[i][0];
			}
			if(ix>=nx+this.lineWidth){
				ix=nx,iy+=this.lineHeight;
				this.drawLine(ix,iy);
				ix+=80;
			}
		}
		this.vHTML=`

				<svg width="${this.width}" height="${this.height}"
			style="background:#FFFFFF";>`
			+this.vHTML+"</svg>
";
		this.content.innerHTML=this.vHTML;
		this.zoom();
	}

	setDisplayer(e){
		this.displayer=e;
	}

	zoom(){
		for(let i=0;i<this.content.children.length;i++){
			this.content.children[0].style.width=this.width*this.scale+6+"px";
			this.content.children[0].style.height=this.height*this.scale+6+"px";
			this.content.children[0].style.margin="auto";
			this.content.children[0].children[0].style.transformOrigin="0% 0%";
			this.content.children[0].children[0].style.transform=`scale(${this.scale},${this.scale})`;
		}
	}

	animate(){
		this.animatInfo=[0,0,0];
		requestAnimationFrame(this.animateFrame.bind(this));
	}

	animateFrame(t){
		var frametime=500;
		if(this.animatInfo[0]==0){
			this.animatInfo[0]=t;
			this.aData=this.data;
			this.data=[];
		}
		this.animatInfo[1]=t-this.animatInfo[0]-this.animatInfo[2]*frametime;
		if(this.animatInfo[1]>=frametime){
			this.animatInfo[1]=0;
			this.animatInfo[2]++;
			this.data=this.aData.slice(0,this.animatInfo[2]);
			this.render();
		}
		if(this.data.length!=this.aData.length){requestAnimationFrame(this.animateFrame.bind(this));}
		else{console.log("animation end");}
	}

	selNote(pos,id){
		this.sel[0]=[pos,id];
		this.render();
	}

	ckEvent(e){
		if(e.target.getAttribute('data-type')=='nt'){
			var pos=e.target.getAttribute('data-pos');
			var id=e.target.getAttribute('data-i');
			this.selNote(pos,id);
		}
	}

	zoomIn(){
		if(this.scale<2.0){
			this.scale+=0.1;
			this.zoom();
		}
	}

	zoomOut(){
		if(this.scale>0.3){
			this.scale-=0.1;
			this.render();
		}
	}

	setScale(s){
		if(s<=2.0 && s>=0.3)this.scale=s;
	}

	kdEvent(e){
		if(e.keyCode==107){
			if(this.sel.length>0){
				this.data[this.sel[0][0]][this.sel[0][1]*2+1+1]++;
				this.render();
			}
		}
		if(e.keyCode==109){
			if(this.sel.length>0){
				var p=this.sel[0][0];
				var id=this.sel[0][1];
				if(this.data[p][id*2+1+1]>0)this.data[p][id*2+1+1]--;
				this.render();
			}
		}
		if(e.keyCode==87){
			if(this.sel.length>0){
				var p=this.sel[0][0];
				var id=this.sel[0][1];
				if(this.data[p][id*2+1]>1)this.data[p][id*2+1]--;
				this.render();
			}
		}
		if(e.keyCode==83){
			if(this.sel.length>0){
				var p=this.sel[0][0];
				var id=this.sel[0][1];
				if(this.data[p][id*2+1]<6)this.data[p][id*2+1]++;
				this.render();
			}
		}
	}

	load(data){
		this.data=data;
	}

	drawBar(x,y){
		this.vHTML+=`<path d='M${x} ${y} l0 70'
		style='stroke:black;stroke-width:1'></path>`;
	}

	drawAlert(x,y){
		this.vHTML+=`<circle cx='${x}' cy='${y-14}' r='5'
		fill='red' stroke-width='0' stroke='red'></circle>`;
	};

	drawLine(x,y){
		this.vHTML+='<svg  stroke-linecap="square" >'
		for(let i=0;i<6;i++){
			this.vHTML+=`<line x1='${x}' y1='${y+i*14}' x2='${x+this.lineWidth}' y2='${y+i*14}'
				style="stroke:black;stroke-width:1"
			></line>`;
		}
		this.vHTML+=`<text style='fill:black;font:bold 22px Sans-serif'>
		<tspan x='${x+10}' y='${y+21}'>T</tspan>
		<tspan x='${x+10}' y='${y+21+21}'>A</tspan>
		<tspan x='${x+10}' y='${y+42+21}'>B</tspan>
		</text>`;
		this.vHTML+=`<text style='fill:black;font:bold 24px serif'>
		<tspan x='${x+33}' y='${y+28}'>${this.beatPerSection}</tspan>
		<tspan x='${x+33}' y='${y+23+28}'>${this.beatLength}</tspan>
		</text>`;
		this.vHTML+=`<path d='M${x} ${y} l0 70 M${x+this.lineWidth} ${y} l0 70'
		style='stroke:black;stroke-width:1'></path>`;
		this.vHTML=this.vHTML+'</svg>';
	}

	drawNote(x,y,pos,length,data){//data=[chord,block,chord,block.....]
		this.vHTML+='<svg>';
		for(let i=0;i<data.length/2;i++){
			this.vHTML+=`<circle cx='${x}' cy='${y+14*(data[i*2]-1)}' r='5' data-type="nt" data-pos="${pos}" data-i="${i}"
			fill='white' stroke-width='0' stroke='black' style='cursor:pointer;'></circle>`;
			this.vHTML+=`<text data-type="nt" data-pos="${pos}" data-i="${i}" x='${x-4}' y='${y+14*(data[i*2]-1)+5}'
			fill='black' style='font-size:14px;cursor:pointer;'>${data[i*2+1]}</text>`;
		}

		this.vHTML+=`<path d='M${x} ${y+78} l0 25' stroke-width='1' stroke='black'></path>`;
		if(length>this.beatLength){
			this.vHTML+=`<path d='M${x} ${y+102} l6 1' stroke-width='2' stroke='black'></path>`;
		}
		if(length>this.beatLength*2){
			var j=1;
			for(let i=this.beatLength*2;i<length;i*=2){
				this.vHTML+=`<path d='M${x} ${y+102-4*j} l6 1' stroke-width='1' stroke='black'></path>`;
				j++;
			}
		}
		for(let i=0;i<this.sel.length;i++){
			if(this.sel[i][0]==pos){
				this.vHTML+=`<circle cx='${x}' cy='${y+14*(data[(this.sel[i][1])*2]-1)}' r='7' fill='rgb(80,255,80)' stroke-width='0' stroke='black'></circle>`;
				this.vHTML+=`<text data-type="nt" data-pos="${pos}" data-i="${i}" x='${x-4}'
					y='${y+14*(data[(this.sel[i][1])*2]-1)+5}' fill='black' style='font-size:14px'>
					${data[(this.sel[i][1])*2+1]}</text>`;
			}
		}
		this.vHTML+='</svg>';
	}
}<|endoftext|>


<commit_before>var API = require('./api.js');

var setting = [{
    path:'/data',
    data: {
        status: 'success',
        log:['///log*5///','/// info*10 ///'],
        data:{
            active: true,
            metadata: {
                admin:false,
                data:['/// info*10 ///']
            }
        },
    },
    lipsum:{
        info: true,
        log: false
    },
    info:{
        media:'photo',
        id:1,
        editable:true,
        message:'this is message'
    },
    log:{
        test:'this is test'
    }
},
{
    path:'/api',
    data: {
        status: 'success',
        log:['///status*5///'],
    },
    status:{
        status:'success',
        amount:100,
        id:1
    }
}]

var apiserver = new API(setting)
apiserver.start(3000)
// console.log(apiserver.profile())
// apiserver.start(3000,function(err, message){
//     if(err) conaole.log(err);
// })
// apiserver.port()
// apiserver.stop()
// apiserver.restart(setting)
<commit_msg>add template idea<commit_after>var API = require('./api.js');

var setting = [{
    path:'/data',
    data: {
        status: 'success',
        log:['///log*5///','/// info*10 ///'],
        data:{
            active: true,
            metadata: {
                admin:false,
                data:['/// info*10 ///']
            }
        },
    },
    lipsum:{
        info: true,
        log: false
    },
    info:{
        media:'photo',
        id:1,
        editable:true,
        message:'this is message'
    },
    log:{
        test:'this is test'
    }
},
{
    path:'/api',
    data: {
        status: 'success',
        log:['///status*5///'],
    },
    status:{
        status:'success',
        amount:{
            stub_type:'select',
            choice:[100,200,300,400],
            type:'random' //'liner'
        },
        id:{
            stub_type:'unique_num',
            starting_num:100,
            increments:10,
            max_num:8000,
            min_num:1000,
            type:'incremental' //'random'
        },
        text:{
            stub_type:'lipsum',
            max_char_length:100
        },
        date:{
            stub_type:'date',
            template:'Y-M-D',
            type:'random' //incremental,
            starting_date:'2014-01-01',
            increments:1,
            max_date:'2014-01-01',
            min_date:'2014-01-31',
        }
    }
}]

var apiserver = new API(setting)
apiserver.start(3000)
// console.log(apiserver.profile())
// apiserver.start(3000,function(err, message){
//     if(err) conaole.log(err);
// })
// apiserver.port()
// apiserver.stop()
// apiserver.restart(setting)
<|endoftext|>


<commit_before>define(['jquery', 'base/js/dialog', 'base/js/namespace'],
function ($, dialog, Jupyter) {
    'use strict';

    var NS = 'anaconda-cloud',
      THUMBNAIL_MIN_DIM = 48,
      LOGO_URL = 'http://binstar-static-prod.s3.amazonaws.com' +
        '/latest/img/AnacondaCloud_logo_green.png',
      credentials = {};

    function api(route){
      // reusable API mapping, handles
      return Jupyter.notebook.base_url + NS + '/' + route;
    }

    function metadata(key, value){
        // wrapper for metadata, ensuring the top-level namespace
        var md = Jupyter.notebook.metadata;

        // ensure top-level namespace is initialized
        md[NS] = md[NS] || {};

        if (!arguments.length) {
          return md[NS];
        } else if(arguments.length === 1){
          return md[NS][key];
        } else{
          md[NS][key] = value;
        }
    }

    function publishNotebook(){
      /*
        Select the current environment for the running kernel.
        This is dependent on behavior of 'nb_conda_kernels' 2.0.0:
        - <normal name, like ir, python3, etc>  # server env
        - conda-env-<env name>-<lang key, py or ir>
        - conda-root-<lang key>
        */
        var kernel_name = Jupyter.notebook.kernel.name,
            kernel_env_re = /^conda-(env-)?(.+?)(-[^\-]*)?$/,
            match = kernel_env_re.exec(kernel_name),
            env_name;

        if(match) {
            env_name = m[2];
        }

        metadata('environment', metadata('attach-environment') ?
            env_name :
            null);
        Jupyter.notebook.save_notebook().then(uploadNotebook);
    }

    function uploadNotebook() {
        var interval;

        $.ajax({
              url: api('publish'),
              method: 'POST',
              dataType: 'json',
              contentType: 'application/json; charset=utf-8',
              processData: false,
              data: JSON.stringify({
                  name: Jupyter.notebook.notebook_name,
                  content: Jupyter.notebook.toJSON()
              })
          })
          .done(function(data) {
              Jupyter.notification_area.get_widget('notebook')
                  .set_message(Jupyter.notebook.notebook_name +
                      ' was published',
                      4000);
              metadata('url', data.url);
              Jupyter.notebook.save_notebook();
              updateVisitLink();
          })
          .fail(showError)
          .always(function(data, textStatus) {
              clearInterval(interval);
          });
        interval = uploadingNotification();
    }

    function visitNotebook() {
        var url = metadata('url');
        if (url) {
            var _window = window.open(url, '_blank');
            if (_window) {
                _window.focus();
            }
        }
    }

    function uploadingNotification() {
        var index = 0,
            pattern = ['-', '\\', '|', '/'],
            _updateString = function(i) {
                Jupyter.notification_area.
                    get_widget('notebook').
                    warning('Uploading ' + pattern[i]);
            }
        _updateString(index);
        return setInterval(function() {
            index+=1;
            if (index > 3) { index = 0 };
            _updateString(index);
        }, 250);
    }

    function updateVisitLink(){
        if (!metadata('url')) {
            $('#visit_notebook').addClass('hide');
        } else {
            $('#visit_notebook').removeClass('hide');
        }
    }

    function thumbnailable(){
        // find good candidate thumbnails
        return $('#notebook')
          .find('img, canvas')
          .filter(function(){
            return this.clientWidth > THUMBNAIL_MIN_DIM &&
              this.clientHeight > THUMBNAIL_MIN_DIM;
          });
    }

    function configureUpload(){
        var url,
            body,
            form,
            name,
            modal,
            attach,
            select,
            summary,
            adminUrl,
            thumbnail,
            thumbnails;

        Jupyter.notification_area.get_widget('notebook')
            .set_message('Connecting to Anaconda Cloud', 2000);

        $.ajax({
            url: api('login'),
            method: 'GET',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
        }).done(function(data) {
            body = $('
');
            name = Jupyter.notebook.notebook_name.replace(/.ipynb$/, '');

            // avoid any surprises with user events firing in the background
            Jupyter.notebook.keyboard_manager.register_events(body);

            url = metadata('url') || '';
            adminUrl = !url ? '' :
              url.replace('https://notebooks.', 'https://') + '/settings/admin';

            // actually build the form
            form = $('
', {
                'class': 'form-horizontal',
                'role': 'form'
            }).appendTo(body);

            // provide prior publishing information
            if(url){
              $('
').append(
                  $('')
                      .text('This notebook was previously published as '),
                  $('', {href: url, target: '_blank'}).text(url)
              )
              .css({'border-left': 'solid 4px #43B02A'})
              .appendTo(body);
            }

            // warning about published status
            $('
')
                .text('Initially, all published notebooks will be ').append(
                  $('', {'class': 'label label-default'})
                    .text('public'),
                  $('').text('. ')
                )
            .appendTo(body);

            // call to action to change settings
            if(adminUrl){
                $('
').append(
                    $('').text('Make '),
                    $('').text(name),
                    $('').text(' '),
                    $('', {'class': 'label label-primary'})
                        .text('private'),
                    $('').text(' or '),
                    $('', {'class': 'label label-success'})
                        .text('authenticated'),
                    $('').text(' on the '),
                    $('', {href: adminUrl, target: '_blank'})
                        .text('Anaconda Cloud settings page'),
                    $('').text('.'))
                .appendTo(body);
            }

            // organization picker, if needed
            if (data.organizations && data.organizations.length) {
                select = $('<select/>', {
                        id: 'select-organization',
                        'class': 'form-control'
                    })

                $('
', {'class': 'form-group'}).append(
                    $('', {'class': 'control-label col-sm-3'})
                        .text('User/Organization'),
                    $('
', {'class': 'col-sm-9'}).append(select))
                .appendTo(form);

                [data.user].concat(data.organizations)
                    .forEach(function(org) {
                        $('<option/>', {value: org.login})
                            .text(org.login + ' (' + org.name + ')')
                            .appendTo(select);
                    });

                if (metadata('organization')) {
                    select.val(metadata('organization'));
                }

                select.on('input', function() {
                    metadata('organization', select.val());
                });
            }

            summary = $('<input/>', {
                'class': 'form-control',
                type: 'text',
                id: 'anaconda-summary',
                placeholder: 'A brief summary'
            })
            .val(metadata('summary'))
            .on('input', function(){
                metadata('summary', summary.val())
            });

            $('
', {'class': 'form-group'}).append(
                $('', {'class': 'control-label col-sm-3'})
                    .text('Summary'),
                $('
', {'class': 'col-sm-9'}).append(summary))
            .appendTo(form);

            // whether to include the environment in metadata
            attach = $('<input/>', {type: 'checkbox'}).prop({
                checked: metadata('attach-environment')})
                .on("change", function(){
                  metadata('attach-environment', attach.prop('checked'));
                });

            $('
', {'class': 'form-group'}).append(
                $('', {'class': 'control-label col-sm-3'})
                    .text('Environment'),
                $('
', {'class': 'col-sm-9'}).append(
                    $('
', {'class': 'checkbox'}).append(
                        $('').append(attach,
                            $('').text('Attach conda environment')))))
            .appendTo(form);

            // thumbnails
            thumbnail = $('', {src: metadata('thumbnail'), height: 72});

            thumbnails = [];

            thumbnailable().map(function(){
                var canvas,
                  ctx,
                  uri;

                try{
                    switch(this.tagName.toLowerCase()){
                      case 'canvas':
                        canvas = this;
                        uri = canvas.toDataURL();
                        break;
                      case 'img':
                        canvas = $('<canvas/>').css({display: 'none'});
                        ctx = canvas[0].getContext('2d');
                        ctx.canvas.width = this.clientWidth;
                        ctx.canvas.height = this.clientHeight;
                        ctx.drawImage(this, 0, 0);
                        uri = canvas[0].toDataURL();
                        canvas.remove();
                        break;
                      default:
                        return;
                    }
                }catch (err){
                    console.log("couldn't snapshot", this, "perhaps execute the cell, perhaps?", err);
                    return;
                }

                thumbnails.push($('
', {value: uri}).append(
                    $('')
                        .on('click', function(){
                            metadata('thumbnail', uri);
                            thumbnail.attr({src: uri})
                        })
                        .append($('', {src: uri, height: 100}))));
            });

            if(thumbnails.length){
              $('
', {'class': 'form-group'}).append(
                  $('', {'class': 'control-label col-sm-3'})
                      .text('Thumbnail'),
                  $('
', {'class': 'col-sm-9'}).append(
                      $('
', {'class': 'dropdown'}).append(
                          $('<button/>', {
                              'class': 'btn btn-default dropdown-toggle',
                              'type': 'button',
                              'data-toggle': 'dropdown'
                          }).append(thumbnail),
                          $('
', {'class': 'dropdown-menu'})
                            .append(thumbnails)
                  )))
              .appendTo(form);
            }

            $('
', {'class': 'form-group'}).append(
                $('
', {'class': 'col-sm-9 col-sm-offset-3'}).append(
                    $('<button/>', {'class': 'btn btn-lg btn-success'})
                      .on('click', function(){
                        modal.modal('hide');
                        publishNotebook();
                      })
                      .append(
                        $('', {'class': 'fa fa-cloud-upload'}),
                        $('').text(' Publish')
                      )))
            .appendTo(form);

            // revert notebook CSS customizations to bootstrap default
            form.find('.control-label label')
                .css({'font-weight': 'bold'});
            form.find('.form-control')
                .css({margin: 0});
            form.find('.col-sm-3, .col-sm-9')
                .css({'padding-left': '15px', 'padding-right': '15px'});

            modal = dialog.modal({
                body: body,
                buttons: {
                    'Close': {}
                }
            });

            modal.find('.modal-title').append(
                $('').text('Publish '),
                $('')
                  .text(name),
                $('').text(' to '),
                $('', {href: 'https://anaconda.org', target: '_blank'})
                  .append($('', {src: LOGO_URL, height: 32}))
            );

        }).fail(showError);
    }

    function showError(jqXHR, textStatus, label) {
        var notif, title, body, showLoginForm=false;

        console.log(arguments)

        switch(jqXHR.status){
          case 401:
            title = 'Unauthorized';
            showLoginForm = true;
            break;
          case 500:
            title = label;
            notif = [
              $('
').text('An error ocurred in the Notebook Server'),
              $('
').text('You may need to re-install nb_anacondacloud')
            ];
            break;
          default:
            title = 'Error: ' + label;
            notif = [
              $('
').text('An error ocurred in the Notebook Server'),
            ]
        }

        Jupyter.notification_area.get_widget('notebook').
            danger(title, 4000);

        if (showLoginForm) {
            promptLogin();
        } else {
            body = $('
').append(notif);

            dialog.modal({
                title: title,
                body: body,
                buttons : {
                    OK: {}
                }
            });
        }
    }

    function promptLogin(withError) {
        var body,
            form,
            username,
            password,
            modal;
        body = $('
');

        // avoid any surprises with user events firing in the background
        Jupyter.notebook.keyboard_manager.register_events(body);
        if (withError) {
            $('
', {'class': 'alert alert-danger', 'role': 'alert'})
                .html(
                    'Invalid username or password.
' +
                    'Did you forget your ' +
                    'username or ' +
                    'password?'
                )
                .appendTo(body);
        }

        // warning about SSL
        $('
', {'class': 'alert alert-warning', 'role': 'alert'})
            .html('If you are not under a secure connection we strongly recommend to ' +
                  'login through the command line with:
anaconda login
')
            .appendTo(body);

        // actually build the form
        form = $('
', {
            'class': 'form-horizontal',
            'role': 'form'
        }).appendTo(body);

        username = $('<input/>', {
            'class': 'form-control',
            type: 'text',
            id: 'anaconda-username',
            placeholder: 'username'
        }).on('input', function() {
            credentials['username'] = username.val();
        });

        password = $('<input/>', {
            'class': 'form-control',
            type: 'password',
            id: 'anaconda-password'
        }).on('input', function() {
            credentials['password'] = password.val();
        });

        $('
', {'class': 'form-group'}).append(
            $('', {'for': 'anaconda-username'})
                .text('Username'),
            $('
').append(username))
        .appendTo(form);

        $('
', {'class': 'form-group'}).append(
            $('', {'for': 'anaconda-password'})
                .text('Password'),
            $('
').append(password))
        .appendTo(form);

        $('
', {'class': 'form-group'}).append(
            $('').html(
                'If you don\'t have an account you sign up in ' +
                'Anaconda.org.'
            )
        ).appendTo(form);

        modal = dialog.modal({
            body: body,
            buttons: {
                'OK': {class: 'btn-primary', click: loginIntoAnaconda},
                'Close': {}
            }
        });

        modal.find('.modal-title').append(
            $('').text('Sign in to '),
            $('', {'href': 'https://anaconda.org', 'target': '_blank'})
              .append($('', {'src': LOGO_URL, 'height': 32}))
        );
    }

    function loginIntoAnaconda() {
        $.ajax({
            url: api('login'),
            method: 'POST',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(credentials)
        }).done(function(data) {
            console.log(data);
            Jupyter.notification_area.get_widget('notebook').
                set_message('Welcome ' + data['username'], 2000);
            configureUpload();
        }).fail(function(jqXHR, textStatus, label) {
            Jupyter.notification_area.get_widget('notebook').
                danger('Unauthorized: Please verify your credentials', 4000);
            promptLogin(true);
        }).always(function() {
            credentials = {};
        });
    }

    function updateToolbar() {
        if (!Jupyter.toolbar) {
            $([Jupyter.events])
              .on('app_initialized.NotebookApp', updateToolbar);
            return;
        }
        if ($('#publish_notebook').length === 0) {
            Jupyter.toolbar.add_buttons_group([{
                label: 'Publish your notebook into Anaconda.org',
                icon: 'fa-cloud-upload',
                callback: configureUpload,
                id: 'publish_notebook'
            }, {
                label: 'Visit your notebook',
                icon: 'fa-cloud',
                callback: visitNotebook,
                id: 'visit_notebook'
            }]);
        }
        updateVisitLink();
    }

    function load_ipython_extension() {
        updateToolbar();
    }

    // export new and old API entrypoints
    return {
      load_ipython_extension: load_ipython_extension
    };
});
<commit_msg>fix bad var ref<commit_after>define(['jquery', 'base/js/dialog', 'base/js/namespace'],
function ($, dialog, Jupyter) {
    'use strict';

    var NS = 'anaconda-cloud',
      THUMBNAIL_MIN_DIM = 48,
      LOGO_URL = 'http://binstar-static-prod.s3.amazonaws.com' +
        '/latest/img/AnacondaCloud_logo_green.png',
      credentials = {};

    function api(route){
      // reusable API mapping, handles
      return Jupyter.notebook.base_url + NS + '/' + route;
    }

    function metadata(key, value){
        // wrapper for metadata, ensuring the top-level namespace
        var md = Jupyter.notebook.metadata;

        // ensure top-level namespace is initialized
        md[NS] = md[NS] || {};

        if (!arguments.length) {
          return md[NS];
        } else if(arguments.length === 1){
          return md[NS][key];
        } else{
          md[NS][key] = value;
        }
    }

    function publishNotebook(){
      /*
        Select the current environment for the running kernel.
        This is dependent on behavior of 'nb_conda_kernels' 2.0.0:
        - <normal name, like ir, python3, etc>  # server env
        - conda-env-<env name>-<lang key, py or ir>
        - conda-root-<lang key>
        */
        var kernel_name = Jupyter.notebook.kernel.name,
            kernel_env_re = /^conda-(env-)?(.+?)(-[^\-]*)?$/,
            match = kernel_env_re.exec(kernel_name),
            env_name;

        if(match) {
            env_name = match[2];
        }

        metadata('environment', metadata('attach-environment') ?
            env_name :
            null);
        Jupyter.notebook.save_notebook().then(uploadNotebook);
    }

    function uploadNotebook() {
        var interval;

        $.ajax({
              url: api('publish'),
              method: 'POST',
              dataType: 'json',
              contentType: 'application/json; charset=utf-8',
              processData: false,
              data: JSON.stringify({
                  name: Jupyter.notebook.notebook_name,
                  content: Jupyter.notebook.toJSON()
              })
          })
          .done(function(data) {
              Jupyter.notification_area.get_widget('notebook')
                  .set_message(Jupyter.notebook.notebook_name +
                      ' was published',
                      4000);
              metadata('url', data.url);
              Jupyter.notebook.save_notebook();
              updateVisitLink();
          })
          .fail(showError)
          .always(function(data, textStatus) {
              clearInterval(interval);
          });
        interval = uploadingNotification();
    }

    function visitNotebook() {
        var url = metadata('url');
        if (url) {
            var _window = window.open(url, '_blank');
            if (_window) {
                _window.focus();
            }
        }
    }

    function uploadingNotification() {
        var index = 0,
            pattern = ['-', '\\', '|', '/'],
            _updateString = function(i) {
                Jupyter.notification_area.
                    get_widget('notebook').
                    warning('Uploading ' + pattern[i]);
            }
        _updateString(index);
        return setInterval(function() {
            index+=1;
            if (index > 3) { index = 0 };
            _updateString(index);
        }, 250);
    }

    function updateVisitLink(){
        if (!metadata('url')) {
            $('#visit_notebook').addClass('hide');
        } else {
            $('#visit_notebook').removeClass('hide');
        }
    }

    function thumbnailable(){
        // find good candidate thumbnails
        return $('#notebook')
          .find('img, canvas')
          .filter(function(){
            return this.clientWidth > THUMBNAIL_MIN_DIM &&
              this.clientHeight > THUMBNAIL_MIN_DIM;
          });
    }

    function configureUpload(){
        var url,
            body,
            form,
            name,
            modal,
            attach,
            select,
            summary,
            adminUrl,
            thumbnail,
            thumbnails;

        Jupyter.notification_area.get_widget('notebook')
            .set_message('Connecting to Anaconda Cloud', 2000);

        $.ajax({
            url: api('login'),
            method: 'GET',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
        }).done(function(data) {
            body = $('
');
            name = Jupyter.notebook.notebook_name.replace(/.ipynb$/, '');

            // avoid any surprises with user events firing in the background
            Jupyter.notebook.keyboard_manager.register_events(body);

            url = metadata('url') || '';
            adminUrl = !url ? '' :
              url.replace('https://notebooks.', 'https://') + '/settings/admin';

            // actually build the form
            form = $('
', {
                'class': 'form-horizontal',
                'role': 'form'
            }).appendTo(body);

            // provide prior publishing information
            if(url){
              $('
').append(
                  $('')
                      .text('This notebook was previously published as '),
                  $('', {href: url, target: '_blank'}).text(url)
              )
              .css({'border-left': 'solid 4px #43B02A'})
              .appendTo(body);
            }

            // warning about published status
            $('
')
                .text('Initially, all published notebooks will be ').append(
                  $('', {'class': 'label label-default'})
                    .text('public'),
                  $('').text('. ')
                )
            .appendTo(body);

            // call to action to change settings
            if(adminUrl){
                $('
').append(
                    $('').text('Make '),
                    $('').text(name),
                    $('').text(' '),
                    $('', {'class': 'label label-primary'})
                        .text('private'),
                    $('').text(' or '),
                    $('', {'class': 'label label-success'})
                        .text('authenticated'),
                    $('').text(' on the '),
                    $('', {href: adminUrl, target: '_blank'})
                        .text('Anaconda Cloud settings page'),
                    $('').text('.'))
                .appendTo(body);
            }

            // organization picker, if needed
            if (data.organizations && data.organizations.length) {
                select = $('<select/>', {
                        id: 'select-organization',
                        'class': 'form-control'
                    })

                $('
', {'class': 'form-group'}).append(
                    $('', {'class': 'control-label col-sm-3'})
                        .text('User/Organization'),
                    $('
', {'class': 'col-sm-9'}).append(select))
                .appendTo(form);

                [data.user].concat(data.organizations)
                    .forEach(function(org) {
                        $('<option/>', {value: org.login})
                            .text(org.login + ' (' + org.name + ')')
                            .appendTo(select);
                    });

                if (metadata('organization')) {
                    select.val(metadata('organization'));
                }

                select.on('input', function() {
                    metadata('organization', select.val());
                });
            }

            summary = $('<input/>', {
                'class': 'form-control',
                type: 'text',
                id: 'anaconda-summary',
                placeholder: 'A brief summary'
            })
            .val(metadata('summary'))
            .on('input', function(){
                metadata('summary', summary.val())
            });

            $('
', {'class': 'form-group'}).append(
                $('', {'class': 'control-label col-sm-3'})
                    .text('Summary'),
                $('
', {'class': 'col-sm-9'}).append(summary))
            .appendTo(form);

            // whether to include the environment in metadata
            attach = $('<input/>', {type: 'checkbox'}).prop({
                checked: metadata('attach-environment')})
                .on("change", function(){
                  metadata('attach-environment', attach.prop('checked'));
                });

            $('
', {'class': 'form-group'}).append(
                $('', {'class': 'control-label col-sm-3'})
                    .text('Environment'),
                $('
', {'class': 'col-sm-9'}).append(
                    $('
', {'class': 'checkbox'}).append(
                        $('').append(attach,
                            $('').text('Attach conda environment')))))
            .appendTo(form);

            // thumbnails
            thumbnail = $('', {src: metadata('thumbnail'), height: 72});

            thumbnails = [];

            thumbnailable().map(function(){
                var canvas,
                  ctx,
                  uri;

                try{
                    switch(this.tagName.toLowerCase()){
                      case 'canvas':
                        canvas = this;
                        uri = canvas.toDataURL();
                        break;
                      case 'img':
                        canvas = $('<canvas/>').css({display: 'none'});
                        ctx = canvas[0].getContext('2d');
                        ctx.canvas.width = this.clientWidth;
                        ctx.canvas.height = this.clientHeight;
                        ctx.drawImage(this, 0, 0);
                        uri = canvas[0].toDataURL();
                        canvas.remove();
                        break;
                      default:
                        return;
                    }
                }catch (err){
                    console.log("couldn't snapshot", this, "perhaps execute the cell, perhaps?", err);
                    return;
                }

                thumbnails.push($('
', {value: uri}).append(
                    $('')
                        .on('click', function(){
                            metadata('thumbnail', uri);
                            thumbnail.attr({src: uri})
                        })
                        .append($('', {src: uri, height: 100}))));
            });

            if(thumbnails.length){
              $('
', {'class': 'form-group'}).append(
                  $('', {'class': 'control-label col-sm-3'})
                      .text('Thumbnail'),
                  $('
', {'class': 'col-sm-9'}).append(
                      $('
', {'class': 'dropdown'}).append(
                          $('<button/>', {
                              'class': 'btn btn-default dropdown-toggle',
                              'type': 'button',
                              'data-toggle': 'dropdown'
                          }).append(thumbnail),
                          $('
', {'class': 'dropdown-menu'})
                            .append(thumbnails)
                  )))
              .appendTo(form);
            }

            $('
', {'class': 'form-group'}).append(
                $('
', {'class': 'col-sm-9 col-sm-offset-3'}).append(
                    $('<button/>', {'class': 'btn btn-lg btn-success'})
                      .on('click', function(){
                        modal.modal('hide');
                        publishNotebook();
                      })
                      .append(
                        $('', {'class': 'fa fa-cloud-upload'}),
                        $('').text(' Publish')
                      )))
            .appendTo(form);

            // revert notebook CSS customizations to bootstrap default
            form.find('.control-label label')
                .css({'font-weight': 'bold'});
            form.find('.form-control')
                .css({margin: 0});
            form.find('.col-sm-3, .col-sm-9')
                .css({'padding-left': '15px', 'padding-right': '15px'});

            modal = dialog.modal({
                body: body,
                buttons: {
                    'Close': {}
                }
            });

            modal.find('.modal-title').append(
                $('').text('Publish '),
                $('')
                  .text(name),
                $('').text(' to '),
                $('', {href: 'https://anaconda.org', target: '_blank'})
                  .append($('', {src: LOGO_URL, height: 32}))
            );

        }).fail(showError);
    }

    function showError(jqXHR, textStatus, label) {
        var notif, title, body, showLoginForm=false;

        console.log(arguments)

        switch(jqXHR.status){
          case 401:
            title = 'Unauthorized';
            showLoginForm = true;
            break;
          case 500:
            title = label;
            notif = [
              $('
').text('An error ocurred in the Notebook Server'),
              $('
').text('You may need to re-install nb_anacondacloud')
            ];
            break;
          default:
            title = 'Error: ' + label;
            notif = [
              $('
').text('An error ocurred in the Notebook Server'),
            ]
        }

        Jupyter.notification_area.get_widget('notebook').
            danger(title, 4000);

        if (showLoginForm) {
            promptLogin();
        } else {
            body = $('
').append(notif);

            dialog.modal({
                title: title,
                body: body,
                buttons : {
                    OK: {}
                }
            });
        }
    }

    function promptLogin(withError) {
        var body,
            form,
            username,
            password,
            modal;
        body = $('
');

        // avoid any surprises with user events firing in the background
        Jupyter.notebook.keyboard_manager.register_events(body);
        if (withError) {
            $('
', {'class': 'alert alert-danger', 'role': 'alert'})
                .html(
                    'Invalid username or password.
' +
                    'Did you forget your ' +
                    'username or ' +
                    'password?'
                )
                .appendTo(body);
        }

        // warning about SSL
        $('
', {'class': 'alert alert-warning', 'role': 'alert'})
            .html('If you are not under a secure connection we strongly recommend to ' +
                  'login through the command line with:
anaconda login
')
            .appendTo(body);

        // actually build the form
        form = $('
', {
            'class': 'form-horizontal',
            'role': 'form'
        }).appendTo(body);

        username = $('<input/>', {
            'class': 'form-control',
            type: 'text',
            id: 'anaconda-username',
            placeholder: 'username'
        }).on('input', function() {
            credentials['username'] = username.val();
        });

        password = $('<input/>', {
            'class': 'form-control',
            type: 'password',
            id: 'anaconda-password'
        }).on('input', function() {
            credentials['password'] = password.val();
        });

        $('
', {'class': 'form-group'}).append(
            $('', {'for': 'anaconda-username'})
                .text('Username'),
            $('
').append(username))
        .appendTo(form);

        $('
', {'class': 'form-group'}).append(
            $('', {'for': 'anaconda-password'})
                .text('Password'),
            $('
').append(password))
        .appendTo(form);

        $('
', {'class': 'form-group'}).append(
            $('').html(
                'If you don\'t have an account you sign up in ' +
                'Anaconda.org.'
            )
        ).appendTo(form);

        modal = dialog.modal({
            body: body,
            buttons: {
                'OK': {class: 'btn-primary', click: loginIntoAnaconda},
                'Close': {}
            }
        });

        modal.find('.modal-title').append(
            $('').text('Sign in to '),
            $('', {'href': 'https://anaconda.org', 'target': '_blank'})
              .append($('', {'src': LOGO_URL, 'height': 32}))
        );
    }

    function loginIntoAnaconda() {
        $.ajax({
            url: api('login'),
            method: 'POST',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(credentials)
        }).done(function(data) {
            console.log(data);
            Jupyter.notification_area.get_widget('notebook').
                set_message('Welcome ' + data['username'], 2000);
            configureUpload();
        }).fail(function(jqXHR, textStatus, label) {
            Jupyter.notification_area.get_widget('notebook').
                danger('Unauthorized: Please verify your credentials', 4000);
            promptLogin(true);
        }).always(function() {
            credentials = {};
        });
    }

    function updateToolbar() {
        if (!Jupyter.toolbar) {
            $([Jupyter.events])
              .on('app_initialized.NotebookApp', updateToolbar);
            return;
        }
        if ($('#publish_notebook').length === 0) {
            Jupyter.toolbar.add_buttons_group([{
                label: 'Publish your notebook into Anaconda.org',
                icon: 'fa-cloud-upload',
                callback: configureUpload,
                id: 'publish_notebook'
            }, {
                label: 'Visit your notebook',
                icon: 'fa-cloud',
                callback: visitNotebook,
                id: 'visit_notebook'
            }]);
        }
        updateVisitLink();
    }

    function load_ipython_extension() {
        updateToolbar();
    }

    // export new and old API entrypoints
    return {
      load_ipython_extension: load_ipython_extension
    };
});
<|endoftext|>


<commit_before>/**
 * @class CM_FormField_Set_Select
 * @extends CM_FormField_Set
 */
var CM_FormField_Set_Select = CM_FormField_Set.extend({
  _class: 'CM_FormField_Set_Select',

  events: {
    'change select': function() {
      this.trigger('change');
    }
  },

  getInput: function() {
    return this.$('input, select');
  },

  /**
   * @returns {String}
   */
  getValue: function() {
    if (this._isRadio()) {
      return this.getInput().filter(':checked').val();
    } else {
      return this.getInput().val();
    }
  },

  /**
   * @param {String} value
   */
  setValue: function(value) {
    if (this._isRadio()) {
      this.getInputByValue(value).prop('checked', 'checked');
    } else {
      this.getInput().val(value);
      this.getInput().trigger('fancyselect:update');
    }
  },

  _isRadio: function() {
    return this.getInput().is('[type=radio]');
  }
});
<commit_msg>Fix Set.getValue() for radios<commit_after>/**
 * @class CM_FormField_Set_Select
 * @extends CM_FormField_Set
 */
var CM_FormField_Set_Select = CM_FormField_Set.extend({
  _class: 'CM_FormField_Set_Select',

  events: {
    'change select': function() {
      this.trigger('change');
    }
  },

  getInput: function() {
    return this.$('input, select');
  },

  /**
   * @returns {String|Null}
   */
  getValue: function() {
    if (this._isRadio()) {
      var $checked = this.getInput().filter(':checked');
      if (0 === $checked.length) {
        return null;
      } else {
        return $checked.val();
      }
    } else {
      return this.getInput().val();
    }
  },

  /**
   * @param {String|Null} value
   */
  setValue: function(value) {
    if (this._isRadio()) {
      this.getInputByValue(value).prop('checked', 'checked');
    } else {
      this.getInput().val(value);
      this.getInput().trigger('fancyselect:update');
    }
  },

  _isRadio: function() {
    return this.getInput().is('[type=radio]');
  }
});
<|endoftext|>


<commit_before><commit_msg>Fix embed of production ReCAPTCHA in build<commit_after><|endoftext|>


<commit_before>/*
 * ************************************************************************
 * Copyright (c), 2013 Next Century Corporation. All Rights Reserved.
 *
 * This software code is the exclusive property of Next Century Corporation and is
 * protected by United States and International laws relating to the protection
 * of intellectual property.  Distribution of this software code by or to an
 * unauthorized party, or removal of any of these notices, is strictly
 * prohibited and punishable by law.
 *
 * UNLESS PROVIDED OTHERWISE IN A LICENSE AGREEMENT GOVERNING THE USE OF THIS
 * SOFTWARE, TO WHICH YOU ARE AN AUTHORIZED PARTY, THIS SOFTWARE CODE HAS BEEN
 * ACQUIRED BY YOU "AS IS" AND WITHOUT WARRANTY OF ANY KIND.  ANY USE BY YOU OF
 * THIS SOFTWARE CODE IS AT YOUR OWN RISK.  ALL WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE HEREBY EXPRESSLY
 * DISCLAIMED.
 *
 * PROPRIETARY AND CONFIDENTIAL TRADE SECRET MATERIAL NOT FOR DISCLOSURE OUTSIDE
 * OF NEXT CENTURY CORPORATION EXCEPT BY PRIOR WRITTEN PERMISSION AND WHEN
 * RECIPIENT IS UNDER OBLIGATION TO MAINTAIN SECRECY.
 */

$(document).ready(function () {

    OWF.ready(function () {

        var datasource;
        var datasetId;
        var filterId;

        var messageHandler = new neon.eventing.MessageHandler({
            activeDatasetChanged: populateAttributeDropdowns,
            filtersChanged: updateFilterId

        });
        var eventPublisher = new neon.eventing.OWFEventPublisher(messageHandler);

        function configureButtons() {
            configureResetFilterButton();
        }

        function getResetFilterButton() {
            return $('#reset-filter');
        }

        function disableResetFilterButton() {
            getResetFilterButton().attr('disabled', 'disabled');
        }

        function configureResetFilterButton() {
            // initially disabled until filter added
            disableResetFilterButton();
            getResetFilterButton().click(function () {
                eventPublisher.removeFilter(filterId);
            });
        }

        function updateFilterId(message) {

            if (message._source === messageHandler.id) {
                if (message.addedIds.length) {
                    // keep track of own filter so we can just replace it rather than keep adding new ones
                    filterId = message.addedIds[0];
                    getResetFilterButton().removeAttr('disabled');
                }
                else if (message.removedIds.length) {
                    filterId = undefined;
                    drawChart();
                    disableResetFilterButton();
                }
            }
        }

        function populateAttributeDropdowns(message) {
            datasource = message.database;
            datasetId = message.table;
            neon.query.getFieldNames(datasource, datasetId, doPopulateAttributeDropdowns);
        }

        function doPopulateAttributeDropdowns(data) {
            ['x', 'y'].forEach(function (selectId) {
                var select = $('#' + selectId);
                select.empty();
                select.append($('<option></option>').attr('value', '').text('(Select Field)'));
                data.fieldNames.forEach(function (field) {
                    select.append($('<option></option>').attr('value', field).text(field));
                });
                select.change(drawChart);
            });
        };

        function getXAttribute() {
            return $('#x option:selected').val();
        }

        function getYAttribute() {
            return $('#y option:selected').val();
        }

        /**
         * Redraws the chart based on the user selected attribtues
         * @method drawChart
         */
        function drawChart() {

            var xAttr = getXAttribute();
            var yAttr = getYAttribute();

            if (!xAttr || !yAttr) {
                doDrawChart({data: []});
                return;
            }

            var groupByHourClause = new neon.query.GroupByFunctionClause(neon.query.HOUR, xAttr, 'hour');
            var groupByDayClause = new neon.query.GroupByFunctionClause(neon.query.DAY, xAttr, 'day');
            var groupByMonthClause = new neon.query.GroupByFunctionClause(neon.query.MONTH, xAttr, 'month');
            var groupByYearClause = new neon.query.GroupByFunctionClause(neon.query.YEAR, xAttr, 'year');

            var query = new neon.query.Query()
                .selectFrom(datasource, datasetId)
                .groupBy(groupByYearClause, groupByMonthClause, groupByDayClause, groupByHourClause)
                .aggregate(neon.query.SUM, yAttr, yAttr);

            neon.query.executeQuery(query, doDrawChart);
        }

        function doDrawChart(data) {

            $('#chart').empty();

            var xAttr = getXAttribute();
            var yAttr = getYAttribute();

            var dataByDate = data.data.map(function (el) {
                //month is 1-based
                var date = new Date(el.year, el.month - 1, el.day, el.hour);
                var count = el[yAttr];
                var result = {};
                result[xAttr] = date;
                result[yAttr] = count;
                return result;
            });

            var granularity = $('#time-granularity option:selected').val();
            var opts = { "data": dataByDate, "x": xAttr, "y": yAttr,
                "interval": granularity, width: 600, height: 400};

            var timeline = new charts.Timeline('#chart', opts);
            configureFiltering(timeline, xAttr);
            timeline.draw();
            // make sure the reset button is aligned with the chart and has some spacing between it and the chart
            $('#reset-filter').css({'margin-left': timeline.margin.left + 'px', 'margin-top': '20px'});
        }

        function configureFiltering(timeline, xAttr) {
            timeline.onFilter(function (startDate, endDate) {
                var startFilterClause = neon.query.where(xAttr, '>=', startDate);
                var endFilterClause = neon.query.where(xAttr, '<', endDate);
                var filterClause = neon.query.and(startFilterClause, endFilterClause);
                var filter = new neon.query.Filter().selectFrom(datasource, datasetId).where(filterClause);

                if (filterId) {
                    eventPublisher.replaceFilter(filterId, filter)
                }
                else {
                    eventPublisher.addFilter(filter);
                }
            });
        }

        function populateTimeGranularityDropdown() {
            var dropdown = $('#time-granularity');
            charts.Timeline.GRANULARITIES_.forEach(function (el) {
                var displayText = el.charAt(0).toUpperCase() + el.slice(1);
                var option = $('<option></option>').attr('value', el).text(displayText);
                if (el === charts.Timeline.MONTH) {
                    option.attr('selected', true);
                }
                dropdown.append(option);
            });
            dropdown.change(drawChart);
        }

        populateTimeGranularityDropdown();
        configureButtons();
        drawChart();

    });

});<commit_msg>NEON-384<commit_after>/*
 * ************************************************************************
 * Copyright (c), 2013 Next Century Corporation. All Rights Reserved.
 *
 * This software code is the exclusive property of Next Century Corporation and is
 * protected by United States and International laws relating to the protection
 * of intellectual property.  Distribution of this software code by or to an
 * unauthorized party, or removal of any of these notices, is strictly
 * prohibited and punishable by law.
 *
 * UNLESS PROVIDED OTHERWISE IN A LICENSE AGREEMENT GOVERNING THE USE OF THIS
 * SOFTWARE, TO WHICH YOU ARE AN AUTHORIZED PARTY, THIS SOFTWARE CODE HAS BEEN
 * ACQUIRED BY YOU "AS IS" AND WITHOUT WARRANTY OF ANY KIND.  ANY USE BY YOU OF
 * THIS SOFTWARE CODE IS AT YOUR OWN RISK.  ALL WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE HEREBY EXPRESSLY
 * DISCLAIMED.
 *
 * PROPRIETARY AND CONFIDENTIAL TRADE SECRET MATERIAL NOT FOR DISCLOSURE OUTSIDE
 * OF NEXT CENTURY CORPORATION EXCEPT BY PRIOR WRITTEN PERMISSION AND WHEN
 * RECIPIENT IS UNDER OBLIGATION TO MAINTAIN SECRECY.
 */

$(document).ready(function () {

    OWF.ready(function () {

        var datasource;
        var datasetId;
        var filterId;

        var messageHandler = new neon.eventing.MessageHandler({
            activeDatasetChanged: populateAttributeDropdowns,
            filtersChanged: updateFilterId

        });
        var eventPublisher = new neon.eventing.OWFEventPublisher(messageHandler);

        function configureButtons() {
            configureResetFilterButton();
        }

        function getResetFilterButton() {
            return $('#reset-filter');
        }

        function disableResetFilterButton() {
            getResetFilterButton().attr('disabled', 'disabled');
        }

        function configureResetFilterButton() {
            // initially disabled until filter added
            disableResetFilterButton();
            getResetFilterButton().click(function () {
                eventPublisher.removeFilter(filterId);
            });
        }

        function updateFilterId(message) {

            if (message._source === messageHandler.id) {
                if (message.addedIds.length) {
                    // keep track of own filter so we can just replace it rather than keep adding new ones
                    filterId = message.addedIds[0];
                    getResetFilterButton().removeAttr('disabled');
                }
                else if (message.removedIds.length) {
                    filterId = undefined;
                    drawChart();
                    disableResetFilterButton();
                }
            }
        }

        function populateAttributeDropdowns(message) {
            datasource = message.database;
            datasetId = message.table;
            neon.query.getFieldNames(datasource, datasetId, doPopulateAttributeDropdowns);
        }

        function doPopulateAttributeDropdowns(data) {
            ['x', 'y'].forEach(function (selectId) {
                var select = $('#' + selectId);
                select.empty();
                select.append($('<option></option>').attr('value', '').text('(Select Field)'));
                data.fieldNames.forEach(function (field) {
                    select.append($('<option></option>').attr('value', field).text(field));
                });
                select.change(drawChart);
            });
        };

        function getXAttribute() {
            return $('#x option:selected').val();
        }

        function getYAttribute() {
            return $('#y option:selected').val();
        }

        /**
         * Redraws the chart based on the user selected attribtues
         * @method drawChart
         */
        function drawChart() {

            var xAttr = getXAttribute();
            var yAttr = getYAttribute();

            if (!xAttr || !yAttr) {
                doDrawChart({data: []});
                return;
            }

            var groupByHourClause = new neon.query.GroupByFunctionClause(neon.query.HOUR, xAttr, 'hour');
            var groupByDayClause = new neon.query.GroupByFunctionClause(neon.query.DAY, xAttr, 'day');
            var groupByMonthClause = new neon.query.GroupByFunctionClause(neon.query.MONTH, xAttr, 'month');
            var groupByYearClause = new neon.query.GroupByFunctionClause(neon.query.YEAR, xAttr, 'year');

            var query = new neon.query.Query()
                .selectFrom(datasource, datasetId)
                .where(xAttr, '!=', null)
                .groupBy(groupByYearClause, groupByMonthClause, groupByDayClause, groupByHourClause)
                .aggregate(neon.query.SUM, yAttr, yAttr);

            neon.query.executeQuery(query, doDrawChart);
        }

        function doDrawChart(data) {

            $('#chart').empty();

            var xAttr = getXAttribute();
            var yAttr = getYAttribute();

            var dataByDate = data.data.map(function (el) {
                //month is 1-based
                var date = new Date(el.year, el.month - 1, el.day, el.hour);
                var count = el[yAttr];
                var result = {};
                result[xAttr] = date;
                result[yAttr] = count;
                return result;
            });

            var granularity = $('#time-granularity option:selected').val();
            var opts = { "data": dataByDate, "x": xAttr, "y": yAttr,
                "interval": granularity, width: 600, height: 400};

            var timeline = new charts.Timeline('#chart', opts);
            configureFiltering(timeline, xAttr);
            timeline.draw();
            // make sure the reset button is aligned with the chart and has some spacing between it and the chart
            $('#reset-filter').css({'margin-left': timeline.margin.left + 'px', 'margin-top': '20px'});
        }

        function configureFiltering(timeline, xAttr) {
            timeline.onFilter(function (startDate, endDate) {
                var startFilterClause = neon.query.where(xAttr, '>=', startDate);
                var endFilterClause = neon.query.where(xAttr, '<', endDate);
                var filterClause = neon.query.and(startFilterClause, endFilterClause);
                var filter = new neon.query.Filter().selectFrom(datasource, datasetId).where(filterClause);

                if (filterId) {
                    eventPublisher.replaceFilter(filterId, filter)
                }
                else {
                    eventPublisher.addFilter(filter);
                }
            });
        }

        function populateTimeGranularityDropdown() {
            var dropdown = $('#time-granularity');
            charts.Timeline.GRANULARITIES_.forEach(function (el) {
                var displayText = el.charAt(0).toUpperCase() + el.slice(1);
                var option = $('<option></option>').attr('value', el).text(displayText);
                if (el === charts.Timeline.MONTH) {
                    option.attr('selected', true);
                }
                dropdown.append(option);
            });
            dropdown.change(drawChart);
        }

        populateTimeGranularityDropdown();
        configureButtons();
        drawChart();

    });

});<|endoftext|>


<commit_before>/* Copyright 2013-2018 Reahl Software Services (Pty) Ltd. All rights reserved. */
/*
    This file is part of Reahl.

    Reahl is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation; version 3 of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

(function($) {
"use strict";

$.widget('reahl.hashchange', {
    options: {
            url: '',
            cache: true,
            errorMessage: 'Ajax error',
            timeoutMessage: 'Ajax timeout',
            params: []
    },

    _create: function() {
        var o = this.options;
        var element = this.element;
        var _this = this;

        _this.options.previousHashValues = $.extend(true, {}, _this.options.params);
        $(window).on( 'hashchange', function(e) {
            var currentFragment = _this.getTraditionallyNamedFragment();
            var changedRelevantHashValues = _this.calculateChangedRelevantHashValues(currentFragment);
            if (_this.hasChanged(changedRelevantHashValues)) {
                _this.triggerChange(currentFragment, changedRelevantHashValues);
            };
            return true;
        });

        $(window).trigger( 'hashchange' );
    },
    getTraditionallyNamedFragment: function() {
        var untraditionallyNamedFragment = $.deparam.fragment(window.location.hash);
        var traditionallyNamedFragment = {};
        for (var cleanName in untraditionallyNamedFragment) {
            var value = untraditionallyNamedFragment[cleanName];
            var traditionalName;
            if (Array.isArray(value)) {
                traditionalName = cleanName+'[]';
            } else {
                traditionalName = cleanName;
            }
            traditionallyNamedFragment[traditionalName] = value;
        }
        return traditionallyNamedFragment;
    },
    getIsList: function(name) {
        return name.match('\\[\\]$');
    },
    getEmptyListSentinel: function(name) {
        return name+'-';
    },
    isEmptyListSentinel: function(name) {
        return name.match('\\[\\]-$');
    },
    getNameFromSentinel: function(name) {
        return name.match('(.*\\[\\])-$')[1];
    },
    getArgumentNames: function() {
        var names = [];
        for (var name in this.options.previousHashValues) {
            if (this.isEmptyListSentinel(name)) {
                name = this.getNameFromSentinel(name);
            }
            names.push(name);
        }
        return names;
    },
    triggerChange: function(currentHashValues, changedHashValues) {
        var _this = this;
        var updatedHashValues = $.extend({}, currentHashValues, changedHashValues);

        var loading = _this.element.block({overlayCSS: {backgroundColor: '#fff', opacity: 0.3}, message: '', fadeIn: 0, fadeout: 0});
        $.ajax({url:     _this.options.url,
                cache:   _this.options.cache,
                data:    updatedHashValues,
                success: function(data){
                    _this.element.html(data);
                    _this.options.previousHashValues = changedHashValues;
                },
                complete: function(data){
                    _this.element.unblock();
                },
                traditional: true
        });
    },
    hasChanged: function(newHashValues){
        var _this = this;
        var changed = false;
        for (var name in _this.options.previousHashValues) {
            if ( ! _.isEqual(newHashValues[name], _this.options.previousHashValues[name])) {
                changed = true;
            };
            if (_this.getIsList(name)) {
                var emptySentinelName = _this.getEmptyListSentinel(name);
                if (!_.isEqual(newHashValues[emptySentinelName], _this.options.previousHashValues[emptySentinelName])) {
                    changed = true;
                }
            }
        };
        console.log("hasChanged", changed);
        return changed;
    },
    calculateChangedRelevantHashValues: function(currentHashValues) {
        var _this = this;
        var changedRelevantHashValues = {};
        var argumentNames = _this.getArgumentNames();
        for (var i=0; i<argumentNames.length; i++) {
            var name = argumentNames[i];

            var currentValue = currentHashValues[name];
            if (currentValue) {
                changedRelevantHashValues[name]=currentValue;
            } else if (_this.getIsList(name)) {
                var emptySentinelName = _this.getEmptyListSentinel(name);
                if (currentHashValues[emptySentinelName] != undefined) {
                    changedRelevantHashValues[emptySentinelName] = "";
                } else {
                    changedRelevantHashValues[name]=[];
                }
            } else {
                changedRelevantHashValues[name]=_this.options.previousHashValues[name];
            }
        };
        return changedRelevantHashValues;
    },
});

$.extend($.reahl.hashchange, {
    version: '1.8'
});

})(jQuery);

<commit_msg>Finalised refactorinf hashchange js code<commit_after>/* Copyright 2013-2018 Reahl Software Services (Pty) Ltd. All rights reserved. */
/*
    This file is part of Reahl.

    Reahl is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation; version 3 of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

(function($) {
"use strict";

function getTraditionallyNamedFragment() {
    var untraditionallyNamedFragment = $.deparam.fragment(window.location.hash);
    var traditionallyNamedFragment = {};
    for (var cleanName in untraditionallyNamedFragment) {
        var value = untraditionallyNamedFragment[cleanName];
        var traditionalName;
        if (Array.isArray(value)) {
            traditionalName = cleanName+'[]';
        } else {
            traditionalName = cleanName;
        }
        traditionallyNamedFragment[traditionalName] = value;
    }
    return traditionallyNamedFragment;
}

class HashArgument {

    constructor(name, defaultValue) {
        this.name = name;
        this.value = defaultValue;
        this.changed = false;
    }

    changeValue(value) {
        if (!_.isEqual(this.value, value)) {
            this.changed = true;
            this.value = value;
        }
    }

    get isList() {
        return this.name.match('\\[\\]$');
    }

    get isEmptyList() {
        return this.isList && (_.isEqual(this.value, []));
    }

    get emptyListSentinelName() {
        return this.name+'-';
    }

    updateFromHashObject(hashObject) {
        this.changed = false;
        var currentValue = hashObject[this.name];
        if (currentValue) {
            this.changeValue(currentValue);
        } else if (this.isList) {
            if (hashObject[this.emptyListSentinelName] != undefined) {
                this.changeValue([]);
            }
        }
    }

    updateHashObject(hashObject) {
        delete hashObject[this.name];
        delete hashObject[this.emptyListSentinelName];

        var nameInHash;
        var valueInHash;
        if (this.isEmptyList) {
            nameInHash = this.emptyListSentinelName;
            valueInHash = "";
        } else {
            nameInHash = this.name;
            valueInHash = this.value;
        }

        hashObject[nameInHash] = valueInHash;
    }

    isEmptyListSentinel(sentinelName) {
        return sentinelName.match('\\[\\]-$');
    }

    get nameFromSentinel() {
        return this.name.match('(.*\\[\\])-$')[1];
    }
}

$.widget('reahl.hashchange', {
    options: {
            url: '',
            cache: true,
            errorMessage: 'Ajax error',
            timeoutMessage: 'Ajax timeout',
            params: [],
            arguments: []
    },

    _create: function() {
        var o = this.options;
        var element = this.element;
        var _this = this;

        _this.options.previousHashValues = $.extend(true, {}, _this.options.params);
        _this.options.arguments = [];
        for (name in _this.options.params) {
            _this.options.arguments.push(new HashArgument(name, _this.options.params[name]))
        }
        $(window).on( 'hashchange', function(e) {
            var currentFragment = getTraditionallyNamedFragment();
            var changedArguments = _this.calculateChangedArguments(currentFragment);
            if (_this.hasChanged(changedArguments)) {
                _this.triggerChange(currentFragment, changedArguments);
            };
            return true;
        });

        $(window).trigger( 'hashchange' );
    },
    getArguments: function() {
        return this.options.arguments;
    },
    calculateQueryStringValues(currentHashValues, hashArguments) {
        var values = $.extend(true, {}, currentHashValues);
        for (var i=0; i<hashArguments.length; i++) {
            var argument = hashArguments[i];
            argument.updateHashObject(values);
        }
        return values;
    },
    triggerChange: function(currentHashValues, newArguments) {
        var _this = this;
        _this.element.block({overlayCSS: {backgroundColor: '#fff', opacity: 0.3}, message: '', fadeIn: 0, fadeout: 0});
        $.ajax({url:     _this.options.url,
                cache:   _this.options.cache,
                data:    _this.calculateQueryStringValues(currentHashValues, newArguments),
                success: function(data){
                    _this.element.html(data);
                    _this.options.arguments = newArguments;
                },
                complete: function(data){
                    _this.element.unblock();
                },
                traditional: true
        });
    },
    hasChanged: function(newArguments){
        var _this = this;
        var changed = false;
        for (var i=0; i<newArguments.length; i++) {
            var argument = newArguments[i];
            if (argument.changed) {
                changed = true;
            };
        }
        return changed;
    },
    calculateChangedArguments: function(currentHashValues) {
        var _this = this;
        var hashArguments = $.extend(true, [], _this.getArguments());
        for (var i=0; i<hashArguments.length; i++) {
            var argument = hashArguments[i];
            argument.updateFromHashObject(currentHashValues);
        };
        return hashArguments;
    },
});

$.extend($.reahl.hashchange, {
    version: '1.8'
});

})(jQuery);

<|endoftext|>


<commit_before>/*! https://mths.be/scrollingelement v1.5.2 by @diegoperini & @mathias | MIT license */
if (!('scrollingElement' in document)) (function() {
	// Note: standards mode / quirks mode can be toggled at runtime via
	// `document.write`.
	var isCompliantCached;

	function isCompliant() {
		var isStandardsMode = /^CSS1/.test(document.compatMode);
		if (!isStandardsMode) {
			// In quirks mode, the result is equivalent to the non-compliant
			// standards mode behavior.
			return false;
		}
		if (isCompliantCached === void 0) {
			// When called for the first time, check whether the browser is
			// standard-compliant, and cache the result.
			var iframe = document.createElement('iframe');
			iframe.style.height = '1px';
			(document.body || document.documentElement || document).appendChild(iframe);
			var doc = iframe.contentWindow.document;
			doc.write('<!DOCTYPE html>
x
');
			doc.close();
			isCompliantCached = doc.documentElement.scrollHeight > doc.body.scrollHeight;
			iframe.parentNode.removeChild(iframe);
		}
		return isCompliantCached;
	}

	function scrollingElement() {
		return isCompliant() ? document.documentElement : document.body ;
	}

	if (Object.defineProperty) {
		// Support modern browsers that lack a native implementation.
		Object.defineProperty(document, 'scrollingElement', {
			'get': scrollingElement
		});
	} else {
		document.scrollingElement = scrollingElement();
	}
}());
<commit_msg>Comments<commit_after>
// A reduced version of
// https://mths.be/scrollingelement v1.5.2 by @diegoperini & @mathias | MIT license
// Leaves out frameset detection and really old browsers

if (!('scrollingElement' in document)) (function() {
	// Note: standards mode / quirks mode can be toggled at runtime via
	// `document.write`.
	var isCompliantCached;

	function isCompliant() {
		var isStandardsMode = /^CSS1/.test(document.compatMode);
		if (!isStandardsMode) {
			// In quirks mode, the result is equivalent to the non-compliant
			// standards mode behavior.
			return false;
		}
		if (isCompliantCached === void 0) {
			// When called for the first time, check whether the browser is
			// standard-compliant, and cache the result.
			var iframe = document.createElement('iframe');
			iframe.style.height = '1px';
			(document.body || document.documentElement || document).appendChild(iframe);
			var doc = iframe.contentWindow.document;
			doc.write('<!DOCTYPE html>
x
');
			doc.close();
			isCompliantCached = doc.documentElement.scrollHeight > doc.body.scrollHeight;
			iframe.parentNode.removeChild(iframe);
		}
		return isCompliantCached;
	}

	function scrollingElement() {
		return isCompliant() ? document.documentElement : document.body ;
	}

	if (Object.defineProperty) {
		// Support modern browsers that lack a native implementation.
		Object.defineProperty(document, 'scrollingElement', {
			'get': scrollingElement
		});
	} else {
		document.scrollingElement = scrollingElement();
	}
}());
<|endoftext|>


<commit_before>define(module, function(exports, require) {

  var qp = require('qp-utility');

  function default_string() { return ''; }
  function default_number() { return 0; }
  function default_boolean() { return false; }
  function default_datetime() { return new Date(); }
  function default_date() {
    var date = new Date();
    date.setUTCHours(12, 0, 0, 0);
    return date;
  }

  qp.module(exports, {

    ns: 'qp-model/schema',

    build: function(_exports, schema) {
      schema.create = this.create.bind(this, schema.columns);
      schema.table = { name: schema.table };
      schema.fields = { managed: [], all: [] };
      qp.each_own(schema.columns, function(column, name) {
        column.name = name;
        if (column.managed) schema.fields.managed.push(name); else schema.fields.all.push(name);
      });
      _exports(schema);
    },

    create: function(fields, data, options) {
      options = qp.options(options, { internal: false });
      if (qp.is(data, 'array')) {
        return qp.map(data, item => this.create_item(fields, item, {}, options));
      } else if (qp.is(data, 'object')) {
        return this.create_item(fields, data, options.instance || {}, options);
      } else {
        return null;
      }
    },

    create_item: function(fields, source, target, options) {
      if (qp.is(source, 'object')) {
        qp.each_own(fields, function(v, k) {
          if (options.internal || !v.internal) {
            target[k] = source[k] || v.default();
          }
        });
      }
      return target || {};
    },

    field: function(type, size, options) {
      if (qp.is(size, 'object')) options = size; size = 0;
      var field;
      if (type === 'text') {
        if (size) {
          field = { type: 'varchar', size: size, default: default_string };
        } else {
          field = { type: 'text', default: default_string };
        }
      } else if (type === 'int' || type === 'integer') {
        if (size === 2) {
          field = { type: 'smallint', default: default_number };
        } else if (size === 8) {
          field = { type: 'bigint', default: default_number };
        } else {
          field = { type: 'integer', default: default_number };
        }
      } else if (type === 'bool' || type === 'boolean') {
        field = { type: 'boolean', default: default_boolean };
      } else if (type === 'datetime') {
        field = { type: 'date', default: default_datetime };
      } else if (type === 'date') {
        field = { type: 'date', default: default_date };
      } else {
        field = { type: '', default: qp.noop };
      }
      return qp.options(field, options);
    },

    primary: function() {
      return this.field('int', 64, { primary: true, managed: true });
    },

    foreign: function(table) {
      return this.field('int', 64, { foreign: true, table: table });
    },

    foreign_ids: function(table) {
      return this.field('int', 64, { foreign: true, table: table, array: true });
    },

    created: function() {
      return this.field('datetime', { managed: true });
    },

    modified: function() {
      return this.field('datetime', { managed: true });
    }

  });

});
<commit_msg>schema; set date & datetime to timestamp with time zone<commit_after>define(module, function(exports, require) {

  var qp = require('qp-utility');

  function default_string() { return ''; }
  function default_number() { return 0; }
  function default_boolean() { return false; }
  function default_datetime() { return new Date(); }
  function default_date() {
    var date = new Date();
    date.setUTCHours(12, 0, 0, 0);
    return date;
  }

  qp.module(exports, {

    ns: 'qp-model/schema',

    build: function(_exports, schema) {
      schema.create = this.create.bind(this, schema.columns);
      schema.table = { name: schema.table };
      schema.fields = { managed: [], all: [] };
      qp.each_own(schema.columns, function(column, name) {
        column.name = name;
        if (column.managed) schema.fields.managed.push(name); else schema.fields.all.push(name);
      });
      _exports(schema);
    },

    create: function(fields, data, options) {
      options = qp.options(options, { internal: false });
      if (qp.is(data, 'array')) {
        return qp.map(data, item => this.create_item(fields, item, {}, options));
      } else if (qp.is(data, 'object')) {
        return this.create_item(fields, data, options.instance || {}, options);
      } else {
        return null;
      }
    },

    create_item: function(fields, source, target, options) {
      if (qp.is(source, 'object')) {
        qp.each_own(fields, function(v, k) {
          if (options.internal || !v.internal) {
            target[k] = source[k] || v.default();
          }
        });
      }
      return target || {};
    },

    field: function(type, size, options) {
      if (qp.is(size, 'object')) options = size; size = 0;
      var field;
      if (type === 'text') {
        if (size) {
          field = { type: 'varchar', size: size, default: default_string };
        } else {
          field = { type: 'text', default: default_string };
        }
      } else if (type === 'int' || type === 'integer') {
        if (size === 2) {
          field = { type: 'smallint', default: default_number };
        } else if (size === 8) {
          field = { type: 'bigint', default: default_number };
        } else {
          field = { type: 'integer', default: default_number };
        }
      } else if (type === 'bool' || type === 'boolean') {
        field = { type: 'boolean', default: default_boolean };
      } else if (type === 'datetime') {
        field = { type: 'timestamp with time zone', default: default_datetime };
      } else if (type === 'date') {
        field = { type: 'timestamp with time zone', default: default_date };
      } else {
        field = { type: '', default: qp.noop };
      }
      return qp.options(field, options);
    },

    primary: function() {
      return this.field('int', 64, { primary: true, managed: true });
    },

    foreign: function(table) {
      return this.field('int', 64, { foreign: true, table: table });
    },

    foreign_ids: function(table) {
      return this.field('int', 64, { foreign: true, table: table, array: true });
    },

    created: function() {
      return this.field('datetime', { managed: true });
    },

    modified: function() {
      return this.field('datetime', { managed: true });
    }

  });

});
<|endoftext|>


<commit_before>/**
 * The Date Field class
 *
 * @constructor
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  1.1.0
 */
var DateField = Function.inherits('Alchemy.Field', function Date(schema, name, options) {
	Date.super.call(this, schema, name, options);
});

/**
 * Set the datatype name
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  1.1.0
 */
DateField.setDatatype('date');

/**
 * Dates are self-contained objects
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
DateField.setSelfContained(true);

/**
 * Cast the given value to this field's type
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  0.5.0
 *
 * @param    {Mixed}   value
 *
 * @return   {Date}
 */
DateField.setMethod(function cast(value) {

	// Don't cast falsy values,
	// that'll result in a date around 1970
	if (!value) {
		return null;
	}

	if (this.options.store_units && value.timestamp) {
		return Date.create(value.timestamp);
	}

	// Leave the time in
	return Date.create(value);
});

/**
 * Split date into multiple fields
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.5.0
 * @version  0.5.0
 *
 * @param    {Mixed}        value       The field's own value
 * @param    {Object}       data        The main record
 * @param    {Datasource}   datasource  The datasource instance
 *
 * @return   {Mixed}
 */
DateField.setMethod(function _toDatasource(value, data, datasource, callback) {

	value = this.cast(value);

	if (this.options.second_format) {
		value /= this.options.second_format;
	}

	if (this.options.store_units) {

		let day = value.getDay();

		if (day == 0) {
			day = 7;
		}

		value = {
			timestamp  : value.valueOf(),
			year       : value.getFullYear(),
			month      : value.getMonth() + 1,
			week       : Number(value.format('W')),
			date       : value.getDate(),
			day        : day
		};
	}

	Blast.nextTick(function() {
		callback(null, value);
	});
});

/**
 * Convert from database to app
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Object}   query     The original query
 * @param    {Object}   options   The original query options
 * @param    {Mixed}    value     The field value, as stored in the DB
 * @param    {Function} callback
 */
DateField.setMethod(function _toApp(query, options, value, callback) {

	if (this.options.second_format && value) {
		value *= this.options.second_format;
	}

	return callback(null, this.cast(value, false));
});

/**
 * Cast the given value to this field's type for search in a db
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.5.0
 * @version  1.1.0
 *
 * @param    {Mixed}             value
 * @param    {FieldExpression}   expression
 *
 * @return   {Mixed}
 */
DateField.setMethod(function castCondition(value, expression) {

	if (!this.options.store_units) {
		return castCondition.super.call(this, value, expression);
	}

	if (expression && expression.db_property) {
		return value;
	}

	expression.db_property = 'timestamp';

	if (!Object.isPlainObject(value)) {

		if (typeof value == 'string') {
			value = Date.create(value);
		}

		if (typeof value != 'number') {
			value = Number(value);
		}

		return value;
	}

	Object.walk(value, function eachEntry(value, key, parent) {

		if (typeof value == 'string') {
			value = Date.create(value);
		}

		if (Date.isDate(value)) {
			parent[key] = Number(value);
		}
	});

	return value;
});<commit_msg>Also apply second_format to conditions<commit_after>/**
 * The Date Field class
 *
 * @constructor
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  1.1.0
 */
var DateField = Function.inherits('Alchemy.Field', function Date(schema, name, options) {
	Date.super.call(this, schema, name, options);
});

/**
 * Set the datatype name
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  1.1.0
 */
DateField.setDatatype('date');

/**
 * Dates are self-contained objects
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
DateField.setSelfContained(true);

/**
 * Cast the given value to this field's type
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  0.5.0
 *
 * @param    {Mixed}   value
 *
 * @return   {Date}
 */
DateField.setMethod(function cast(value) {

	// Don't cast falsy values,
	// that'll result in a date around 1970
	if (!value) {
		return null;
	}

	if (this.options.store_units && value.timestamp) {
		return Date.create(value.timestamp);
	}

	// Leave the time in
	return Date.create(value);
});

/**
 * Split date into multiple fields
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.5.0
 * @version  0.5.0
 *
 * @param    {Mixed}        value       The field's own value
 * @param    {Object}       data        The main record
 * @param    {Datasource}   datasource  The datasource instance
 *
 * @return   {Mixed}
 */
DateField.setMethod(function _toDatasource(value, data, datasource, callback) {

	value = this.cast(value);

	if (this.options.second_format) {
		value /= this.options.second_format;
	}

	if (this.options.store_units) {

		let day = value.getDay();

		if (day == 0) {
			day = 7;
		}

		value = {
			timestamp  : value.valueOf(),
			year       : value.getFullYear(),
			month      : value.getMonth() + 1,
			week       : Number(value.format('W')),
			date       : value.getDate(),
			day        : day
		};
	}

	Blast.nextTick(function() {
		callback(null, value);
	});
});

/**
 * Convert from database to app
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Object}   query     The original query
 * @param    {Object}   options   The original query options
 * @param    {Mixed}    value     The field value, as stored in the DB
 * @param    {Function} callback
 */
DateField.setMethod(function _toApp(query, options, value, callback) {

	if (this.options.second_format && value) {
		value *= this.options.second_format;
	}

	return callback(null, this.cast(value, false));
});

/**
 * Cast the given value to this field's type for search in a db
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.5.0
 * @version  1.1.0
 *
 * @param    {Mixed}             value
 * @param    {FieldExpression}   expression
 *
 * @return   {Mixed}
 */
DateField.setMethod(function castCondition(value, expression) {

	if (this.options.second_format && value) {
		value /= this.options.second_format;
		return value;
	}

	if (!this.options.store_units) {
		return castCondition.super.call(this, value, expression);
	}

	if (expression && expression.db_property) {
		return value;
	}

	expression.db_property = 'timestamp';

	if (!Object.isPlainObject(value)) {

		if (typeof value == 'string') {
			value = Date.create(value);
		}

		if (typeof value != 'number') {
			value = Number(value);
		}

		return value;
	}

	Object.walk(value, function eachEntry(value, key, parent) {

		if (typeof value == 'string') {
			value = Date.create(value);
		}

		if (Date.isDate(value)) {
			parent[key] = Number(value);
		}
	});

	return value;
});<|endoftext|>