<commit_before>/*
	??name??
	Copyright (C) 2014 Matthias Graf
	matthias.graf <a> eclasca.de

	This program 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, either version 3 of the License, or
	(at your option) any later version.

	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/>.
*/

ma = function() { // spans everything - not indented
var ma = {}

var svgViewboxWidth = 100
var svgViewboxHeight = 100
var svgViewboxX = -svgViewboxWidth/2
var svgViewboxY = -svgViewboxHeight/2
var svgWidth = 800
var svgHeight = 800

var keyPressed = { w:false, a:false, s:false, d:false }
const keyMap = { d:68, s:83, e:69, f:70, g:71, "+":107, "-":109 }

var svg
// r: 0 is North, -Math.PI/2 is West, ...
var turtleContext = {x: 0, y:0, r:0}
var turtleHomeStyle = {fill: "none", stroke: "#d07f00", "stroke-width": ".2", "stroke-linecap": "round"}
var turtleStyle = {fill: "#ffba4c", "fill-opacity": 0.6, stroke: "none"}
var paintingG
var previewLine
var previewArc
var tPath = []

ma.init = function() {
	svg = d3.select("#turtleSVG")
	svg.attr("viewBox", svgViewboxX+" "+svgViewboxY+" "+svgViewboxWidth+" "+svgViewboxHeight)
		.attr("width", svgWidth).attr("height", svgHeight)

	paintingG = svg.append("g").attr("id", "paintingG")

	var turtleHomeCursor = svg.append("g").attr("id", "turtleHomeCursor")
	turtleHomeCursor.append("path").attr("d", "M1,1 L0,-2 L-1,1 Z").style(turtleHomeStyle)

	var turtleCursor = svg.append("g").attr("id", "turtleCursor")
		.attr("transform", "translate("+turtleContext.x+", "+turtleContext.y+") rotate("+(turtleContext.r/Math.PI*180)+")")
	turtleCursor.append("path").attr("d", "M1,1 L0,-2 L-1,1 Z").style(turtleStyle)

	svg.call(d3.behavior.drag().on("drag", function (d) {
		if (false) {
			var x = toCanvasCoordsX(d3.event.x)
			var y = toCanvasCoordsY(d3.event.y)
			var oldX = x-toCanvasCoordsDX(d3.event.dx)
			var oldY = y-toCanvasCoordsDY(d3.event.dy)
			svg.append("line").attr("x1", x).attr("y1", y).attr("x2", oldX).attr("y2", oldY)
				.style({stroke: "#000", "stroke-width": ".25", "stroke-linecap": "round"})
		}
		svgViewboxX -= toCanvasCoordsDX(d3.event.dx)
		svgViewboxY -= toCanvasCoordsDY(d3.event.dy)
		svg.attr("viewBox", svgViewboxX+" "+svgViewboxY+" "+svgViewboxWidth+" "+svgViewboxHeight)

	}))

	svg.on("mousemove", function (d, i) {
		var mouse = d3.mouse(this)
		var x = mouse[0]
		var y = mouse[1]
		if (keyPressed.d) {
			previewLine.attr("x2", x).attr("y2", y)
			var dx = x-turtleContext.x
			var dy = y-turtleContext.y
			var lineLength = Math.sqrt(dx*dx+dy*dy)
			var alpha = Math.atan2(dy, dx)
			if (alpha > Math.PI/2)
				alpha -= Math.PI/2*3
			else
				alpha += Math.PI/2

			var arc = d3.svg.arc()
				.innerRadius(0)
				.outerRadius(Math.min(10, lineLength/2))
				.startAngle(turtleContext.r)
				.endAngle(alpha)

			previewArc.attr("d", arc)
		}
    })

	svg.on("click", function (d, i) {

    })

	d3.select("body")
		.on("keydown", function() { updateKeyDownAndUp(d3.event.keyCode, true) })
		.on("keyup", function() { updateKeyDownAndUp(d3.event.keyCode, false) })
}

function updateKeyDownAndUp(keyCode, down) {
	switch (keyCode) {
		case keyMap.d:
			if (down && !keyPressed.d) {
				var arc = d3.svg.arc()
					.innerRadius(0)
					.outerRadius(10)
					.startAngle(turtleContext.r)
					.endAngle(1)

				previewArc = paintingG.append("path")
					.attr("d", arc)
					.attr("transform", "translate(0,0)")
					.style({fill: "#000", "fill-opacity": 0.2})

				previewLine = paintingG.append("line")
					.attr("x1", turtleContext.x).attr("y1", turtleContext.y)
					.attr("x2", 0).attr("y2", 0)
					.style({stroke: "#000", "stroke-width": ".25", "stroke-linecap": "round"})
			}
			if (!down && keyPressed.d) {
				previewLine.remove()
				previewArc.remove()
			}
			keyPressed.d = down
			break
		case keyMap.s: keyPressed.s = down; break
		case keyMap.e: keyPressed.e = down; break
		case keyMap.f: keyPressed.f = down; break
		case keyMap.g: keyPressed.g = down; break
		default: break
	}
}

function toCanvasCoordsX(x) { return svgViewboxX+x*(svgViewboxWidth/svgWidth) }
function toCanvasCoordsY(y) { return svgViewboxY+y*(svgViewboxHeight/svgHeight) }
function toCanvasCoordsDX(x) { return x*(svgViewboxWidth/svgWidth) }
function toCanvasCoordsDY(y) { return y*(svgViewboxHeight/svgHeight) }

return ma
}()<commit_msg>commands list and manipulation of angles (propagates)<commit_after>/*
	Drawing Turtle Graphics
	Copyright (C) 2014 Matthias Graf
	matthias.graf <a> eclasca.de

	This program 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, either version 3 of the License, or
	(at your option) any later version.

	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/>.
*/

ma = function() { // spans everything - not indented
var ma = {}

var svgViewboxWidth = 100
var svgViewboxHeight = 100
var svgViewboxX = -svgViewboxWidth/2
var svgViewboxY = -svgViewboxHeight/2
var svgWidth = 800
var svgHeight = 800

var keyPressed = { w:false, a:false, s:false, d:false }
const keyMap = { d:68, s:83, e:69, f:70, g:71, "+":107, "-":109 }

var svg
var turtleHomeStyle = {fill: "none", stroke: "#d07f00", "stroke-width": ".2", "stroke-linecap": "round"}
var turtleStyle = {fill: "#ffba4c", "fill-opacity": 0.6, stroke: "none"}
var lineStyle = {stroke: "#000", "stroke-width": ".25", "stroke-linecap": "round"}
var arcStyle = {fill: "#000", "fill-opacity": 0.1}

var paintingG
var previewLine
var previewArc

var functions = []
var commands = [
	//	rotate(1), move(10), rotate(-2), move(10), rotate(-2), move(10), rotate(-2), move(10)
]

var turtleHomeCursor
var turtleCursor
// r: 0 is North, -Math.PI/2 is West. r is in [-Pi, Pi].
var state = {x: 0, y:0, r:0, addRadius: function(rr) {
		if (rr > Math.PI || rr < -Math.PI)
			console.log("Warning: addRadius: rr out of [-Pi, Pi]")
		this.r += rr
		this.r = correctRadius(this.r)
	}
}

function cloneS(state) {
	return {x: state.x, y: state.y, r: state.r, addRadius: state.addRadius}
}

ma.init = function() {
	svg = d3.select("#turtleSVG")
	svg.attr("viewBox", svgViewboxX+" "+svgViewboxY+" "+svgViewboxWidth+" "+svgViewboxHeight)
		.attr("width", svgWidth).attr("height", svgHeight)

	paintingG = svg.append("g").attr("id", "paintingG")

	turtleHomeCursor = svg.append("g").attr("id", "turtleHomeCursor")
	turtleHomeCursor.append("path").attr("d", "M1,1 L0,-2 L-1,1 Z").style(turtleHomeStyle)

	turtleCursor = svg.append("g").attr("id", "turtleCursor")
	updateTurtle()
	turtleCursor.append("path").attr("d", "M1,1 L0,-2 L-1,1 Z").style(turtleStyle)

//	svg.call(d3.behavior.drag().on("drag", function (d) {
//		if (false) {
//			var x = toCanvasCoordsX(d3.event.x)
//			var y = toCanvasCoordsY(d3.event.y)
//			var oldX = x-toCanvasCoordsDX(d3.event.dx)
//			var oldY = y-toCanvasCoordsDY(d3.event.dy)
//			svg.append("line").attr("x1", x).attr("y1", y).attr("x2", oldX).attr("y2", oldY)
//				.style({stroke: "#000", "stroke-width": ".25", "stroke-linecap": "round"})
//		}
//		svgViewboxX -= toCanvasCoordsDX(d3.event.dx)
//		svgViewboxY -= toCanvasCoordsDY(d3.event.dy)
//		svg.attr("viewBox", svgViewboxX+" "+svgViewboxY+" "+svgViewboxWidth+" "+svgViewboxHeight)
//
//	}))

	svg.on("mousemove", function (d, i) {
		if (keyPressed.d) {
			var mouse = d3.mouse(this)
			var x = mouse[0]
			var y = mouse[1]
			var dx = x-state.x
			var dy = y-state.y
			previewLine.attr("x2", x).attr("y2", y)
			var lineLength = Math.sqrt(dx*dx+dy*dy)
			updatePreviewAngle(dx, dy, lineLength)
		}
    })

	svg.on("click", function (d, i) {
		if (keyPressed.d) {
			var mouse = d3.mouse(this)
			var x = mouse[0]
			var y = mouse[1]
			var dx = x-state.x
			var dy = y-state.y
			var lineLength = Math.sqrt(dx*dx+dy*dy)

			var r = rotate(getAngleDeltaTo(dx, dy))
			commands.push(r)
			r.exec()
			var m = move(lineLength)
			commands.push(m)
			m.exec()

			updatePreviewAngle(dx, dy, lineLength)
			previewLine.attr("x1", state.x).attr("y1", state.y)
			updateTurtle()
		}
    })

	d3.select("body")
		.on("keydown", function() { updateKeyDownAndUp(d3.event.keyCode, true) })
		.on("keyup", function() { updateKeyDownAndUp(d3.event.keyCode, false) })

	for (var i=0; i<commands.length; i++) {
		commands[i].exec()
	}
	updateTurtle()
}

function updatePreviewAngle(dx, dy, lineLength) {
	var arc = d3.svg.arc()
		.innerRadius(0)
		.outerRadius(Math.min(7, lineLength/2))
		.startAngle(state.r)
		.endAngle(state.r + getAngleDeltaTo(dx, dy))

	previewArc.attr("d", arc).attr("transform", "translate("+state.x+", "+state.y+")")
}

function getAngleDeltaTo(dx, dy, r) {
	return correctRadius(Math.atan2(dy, dx) + Math.PI/2 - (r === undefined ? state.r : r))
}

function updateTurtle() {
	turtleCursor.attr("transform", "translate("+state.x+", "+state.y+") rotate("+(state.r/Math.PI*180)+")")
}

function updateKeyDownAndUp(keyCode, down) {
	switch (keyCode) {
		case keyMap.d:
			if (down && !keyPressed.d) {
				previewArc = paintingG.append("path")
					//.attr("d", arc) // TODO where do I get dy and dx from?
					.attr("transform", "translate("+state.x+","+state.y+")")
					.style(arcStyle)

				previewLine = paintingG.append("line")
					.attr("x1", state.x).attr("y1", state.y)
					.style(lineStyle)
			}
			if (!down && keyPressed.d) {
				previewLine.remove()
				previewArc.remove()
			}
			keyPressed.d = down
			break
		case keyMap.s: keyPressed.s = down; break
		case keyMap.e: keyPressed.e = down; break
		case keyMap.f: keyPressed.f = down; break
		case keyMap.g: keyPressed.g = down; break
		default: break
	}
}

function move(length) {
	var move = {}
	move.length = length
	move.line = undefined
	move.label = undefined
	move.exec = function() {
		var x1 = state.x
		var y1 = state.y
		state.x += Math.sin(state.r) * move.length
		state.y -= Math.cos(state.r) * move.length
		var x2 = state.x
		var y2 = state.y
		if (move.line === undefined) {
			move.line = paintingG.append("line").style(lineStyle)
		}
		move.line
			.attr("x1", x1).attr("y1", y1)
			.attr("x2", x2).attr("y2", y2)
	}
	return move
}

function rotate(angle) {
	var rotate = {}
	rotate.angle = angle
	rotate.arc = undefined
	rotate.label = undefined
	rotate.savedState = undefined
	rotate.exec = function() {
		if (rotate.savedState === undefined) { // clone state
			rotate.savedState = cloneS(state)
		}
		var arc = d3.svg.arc()
			.innerRadius(0)
			.outerRadius(7)
			.startAngle(state.r)
			.endAngle(state.r + angle)
		state.addRadius(angle)

		if (rotate.arc === undefined) {
			rotate.arc = paintingG.append("path").style(arcStyle)
			rotate.arc.on("mouseenter", function (d, i) {
				rotate.arc.style({fill: "#f00"})
			})
			rotate.arc.on("mouseleave", function (d, i) {
				rotate.arc.style(arcStyle)
			})
			rotate.arc.call(d3.behavior.drag().on("drag", function (d) {
				state = cloneS(rotate.savedState)

				var x = d3.event.x
				var y = d3.event.y
				var dx = x-state.x
				var dy = y-state.y
				var angleDelta = getAngleDeltaTo(dx, dy)
				var arc = d3.svg.arc()
					.innerRadius(0)
					.outerRadius(7)
					.startAngle(state.r)
					.endAngle(state.r + angleDelta)
				state.addRadius(angleDelta)

				rotate.arc.attr("d", arc)
				// propagate change
				for (var i=commands.indexOf(rotate)+1; i<commands.length; i++) {
					commands[i].savedState = undefined
					commands[i].exec()
				}
				updateTurtle()
			}))
		}

		rotate.arc
			.attr("d", arc)
			.attr("transform", "translate("+state.x+","+state.y+")")
	}
	return rotate
}

function correctRadius(r) {
	var isPositive = r > 0
	var divIsUneven = Math.floor(Math.abs(r / Math.PI)) % 2 === 1
	// into bounds
	r = r % Math.PI

	// it overshot into the opposite 180°
	if (divIsUneven)
		r = (isPositive ? -1 : 1)* Math.PI + r
	console.assert(r >= -Math.PI && r <= Math.PI)
	return r
}

function toCanvasCoordsX(x) { return svgViewboxX+x*(svgViewboxWidth/svgWidth) }
function toCanvasCoordsY(y) { return svgViewboxY+y*(svgViewboxHeight/svgHeight) }
function toCanvasCoordsDX(x) { return x*(svgViewboxWidth/svgWidth) }
function toCanvasCoordsDY(y) { return y*(svgViewboxHeight/svgHeight) }

return ma
}()<|endoftext|>


<commit_before>'use strict'

module.exports = function (param, property, scope) {
  if (!scope) {
    scope = property
    property = param
    param = `${property}_id`
  }
  this.param(param, (req, res, next, id) => {
    if (!id) return next()
    scope().find(id).then((model) => {
      if (!model) return res.status(404).render('404')
      req[property] = res.locals[property] = model
      next()
    })
  })
}
<commit_msg>Catch find errors.<commit_after>'use strict'

module.exports = function (param, property, scope) {
  if (!scope) {
    scope = property
    property = param
    param = `${property}_id`
  }
  this.param(param, (req, res, next, id) => {
    if (!id) return next()
    scope().find(id).then((model) => {
      if (!model) return res.status(404).render('404')
      req[property] = res.locals[property] = model
      next()
    }).catch(res.error)
  })
}
<|endoftext|>


<commit_before>var fis = module.exports = require('fis');

fis.cli.name = "fist";
fis.cli.info = fis.util.readJSON(__dirname + '/package.json');
fis.config.set('modules.postpackager', 'simple');
fis.config.set('settings.postpackager.simple.autoCombine', true);
fis.config.merge({
    roadmap : {
        path : [
            {
                //一级同名组件，可以引用短路径，比如sea-modules/jquery/juqery.js
                //直接引用为var $ = require('jquery');
                reg : /^\/sea-modules\/([^\/]+)\/\1\.(js|coffee|less|css)$/i,
                //是组件化的，会被jswrapper包装
                isMod : true,
                //less和css文件会做csssprite处理
                useSprite : true,
                //id为文件夹名
                id : '$1',
                release: '/static/$&'
            },
            {
                //sea-modules目录下的其他文件
                reg : /^\/sea-modules\/(.*)\.(js|coffee|less|css)$/i,
                //是组件化的，会被jswrapper包装
                isMod : true,
                //less和css文件会做csssprite处理
                useSprite : true,
                //id是去掉sea-modules和.js后缀中间的部分
                id : '$1',
                release: '/static/$&'
            },
            {
                //.mixin.less后缀的文件
                reg : /\.mixin\.less$/,
                //仅当做函数调用，不发布
                release : false
            },
            {
                //配置文件不发布
                reg : 'fis-conf.js',
                release : false
            },
            {
                //sea配置文件
                reg : 'sea-config.js',
                release : '/static/js/$&'
            },
            {
                //其他js、css、coffee、less文件
                reg : /\.(js|coffee|css|less)$/,
                //less和css文件会做csssprite处理
                useSprite : true,
                //不要放到js资源表里
                useMap : false
            },
            {
                //html文件
                reg : /^\/templates\/(.*)\.(html)$/i,
                release : '/thinkphp.project/$1.html'
            },
            {
                //readme文件，不要发布
                reg : /\/readme\.md$/i,
                release : false
            },
            {
                //map.json没什么用，就不要发布了
                reg : 'map.json',
                release : false
            }
        ],
        ext : {
            //less输出为css文件
            less : 'css',
            //coffee输出为js文件
            coffee : 'js'
        }
    },
    modules : {//fis插件配置
        parser : {
            //.coffee后缀的文件使用fis-parser-coffee-script插件编译
            coffee : 'coffee-script',
            //.less后缀的文件使用fis-parser-less插件编译
            less : 'less'
        },
        lint : {
            js : 'jshint'
        },
        postpackager : 'seajs'
    },
    settings : {
        parser : {
            'coffee-script' : {
                //不用coffee-script包装作用域
                bare : true
            }
        },
        lint : {
            jshint : {
                //排除对lib和jquery、backbone、underscore的检查
                ignored : [ 'lib/**', /jquery|backbone|underscore/i ],
                //使用中文报错
                i18n : 'zh-CN'
            }
        },
        postprocessor : {
            jswrapper : {
                //用fis的js包装器，更方便书写
                type : 'amd'
            }
        },
        optimizer : {
            'uglify-js' : {
                mangle : {
                    //不要压缩require关键字，否则seajs会识别不了require
                    except : [ 'require' ]
                }
            }
        }
    }
});
<commit_msg>add html.path set<commit_after>var fis = module.exports = require('fis');

fis.cli.name = "fist";
fis.cli.info = fis.util.readJSON(__dirname + '/package.json');
fis.config.set('modules.postpackager', 'simple');
fis.config.set('settings.postpackager.simple.autoCombine', true);

//html模板输出目录
fis.config.set('html.path', 'thinkphp.project');

fis.config.merge({
    roadmap : {
        path : [
            {
                //一级同名组件，可以引用短路径，比如sea-modules/jquery/juqery.js
                //直接引用为var $ = require('jquery');
                reg : /^\/sea-modules\/([^\/]+)\/\1\.(js|coffee|less|css)$/i,
                //是组件化的，会被jswrapper包装
                isMod : true,
                //less和css文件会做csssprite处理
                useSprite : true,
                //id为文件夹名
                id : '$1',
                release: '/static/$&'
            },
            {
                //sea-modules目录下的其他文件
                reg : /^\/sea-modules\/(.*)\.(js|coffee|less|css)$/i,
                //是组件化的，会被jswrapper包装
                isMod : true,
                //less和css文件会做csssprite处理
                useSprite : true,
                //id是去掉sea-modules和.js后缀中间的部分
                id : '$1',
                release: '/static/$&'
            },
            {
                //.mixin.less后缀的文件
                reg : /\.mixin\.less$/,
                //仅当做函数调用，不发布
                release : false
            },
            {
                //配置文件不发布
                reg : 'fis-conf.js',
                release : false
            },
            {
                //sea配置文件
                reg : 'sea-config.js',
                release : '/static/js/$&'
            },
            {
                //其他js、css、coffee、less文件
                reg : /\.(js|coffee|css|less)$/,
                //less和css文件会做csssprite处理
                useSprite : true,
                //不要放到js资源表里
                useMap : false
            },
            {
                //html文件
                reg : /^\/templates\/(.*)\.(html)$/i,
                release : '/${html.path}/$1.html'
            },
            {
                //readme文件，不要发布
                reg : /\/readme\.md$/i,
                release : false
            },
            {
                //map.json没什么用，就不要发布了
                reg : 'map.json',
                release : false
            }
        ],
        ext : {
            //less输出为css文件
            less : 'css',
            //coffee输出为js文件
            coffee : 'js'
        }
    },
    modules : {//fis插件配置
        parser : {
            //.coffee后缀的文件使用fis-parser-coffee-script插件编译
            coffee : 'coffee-script',
            //.less后缀的文件使用fis-parser-less插件编译
            less : 'less'
        },
        lint : {
            js : 'jshint'
        },
        postpackager : 'seajs'
    },
    settings : {
        parser : {
            'coffee-script' : {
                //不用coffee-script包装作用域
                bare : true
            }
        },
        lint : {
            jshint : {
                //排除对lib和jquery、backbone、underscore的检查
                ignored : [ 'lib/**', /jquery|backbone|underscore/i ],
                //使用中文报错
                i18n : 'zh-CN'
            }
        },
        postprocessor : {
            jswrapper : {
                //用fis的js包装器，更方便书写
                type : 'amd'
            }
        },
        optimizer : {
            'uglify-js' : {
                mangle : {
                    //不要压缩require关键字，否则seajs会识别不了require
                    except : [ 'require' ]
                }
            }
        }
    }
});
<|endoftext|>


<commit_before>/**
 * Metro configuration for React Native
 * https://github.com/facebook/react-native
 *
 * @format
 */

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};
<commit_msg>metro [nfc]: Drop comment that made better sense in the template.<commit_after>// @format

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};
<|endoftext|>


<commit_before>/* global require, ResearchItemTypes */
'use strict';

const _ = require('lodash');

const BaseModel = require("../lib/BaseModel.js");

module.exports = _.merge({}, BaseModel, {
    DEFAULT_SORTING: {},
    migrate: 'safe',
    tableName: 'project',
    autoUpdatedAt: false,
    autoCreatedAt: false,
    attributes: {
        type: {
            model: 'researchitemtype'
        },
        code: 'STRING',
        acronym: 'STRING',
        title: 'STRING',
        abstract: 'STRING',
        startDate: {
            type: 'STRING',
            columnName: 'start_date'
        },
        endDate: {
            type: 'STRING',
            columnName: 'end_date'
        },
        projectType: {
            type: 'STRING',
            columnName: 'project_type'
        },
        role: 'STRING',
        status: 'STRING',
        url: 'STRING',
        members: 'JSON',
        researchLines: {
            type: 'JSON',
            columnName: 'research_lines'
        },
        logos: 'JSON',
        projectData: {
            type: 'JSON',
            columnName: 'project_data'
        },
        toJSON() {
            const project = this.toObject();
            project.pi = project.members
                .filter(m => ['pi', 'co_pi'].includes(m.role))
                .map(m => ({
                    email: m.email,
                    name: m.name,
                    surname: m.surname
                }));
            project.lines = project.researchLines.map(rl => ({
                code: rl.code,
                description: rl.description
            }));
            project.searchPi = project.pi.map(p => `${p.email}-${p.name} ${p.surname}`).join(',');
            project.type = ResearchItemTypes.getType(project.type);
            delete project.projectData;
            delete project.members;
            delete project.researchLines;
            return project
        }
    }
});

<commit_msg>Removed type from the public projects<commit_after>/* global require, ResearchItemTypes */
'use strict';

const _ = require('lodash');

const BaseModel = require("../lib/BaseModel.js");

module.exports = _.merge({}, BaseModel, {
    DEFAULT_SORTING: {},
    migrate: 'safe',
    tableName: 'project',
    autoUpdatedAt: false,
    autoCreatedAt: false,
    attributes: {
        type: {
            model: 'researchitemtype'
        },
        code: 'STRING',
        acronym: 'STRING',
        title: 'STRING',
        abstract: 'STRING',
        startDate: {
            type: 'STRING',
            columnName: 'start_date'
        },
        endDate: {
            type: 'STRING',
            columnName: 'end_date'
        },
        projectType: {
            type: 'STRING',
            columnName: 'project_type'
        },
        role: 'STRING',
        status: 'STRING',
        url: 'STRING',
        members: 'JSON',
        researchLines: {
            type: 'JSON',
            columnName: 'research_lines'
        },
        logos: 'JSON',
        projectData: {
            type: 'JSON',
            columnName: 'project_data'
        },
        toJSON() {
            const project = this.toObject();
            project.pi = project.members
                .filter(m => ['pi', 'co_pi'].includes(m.role))
                .map(m => ({
                    email: m.email,
                    name: m.name,
                    surname: m.surname
                }));
            project.lines = project.researchLines.map(rl => ({
                code: rl.code,
                description: rl.description
            }));
            project.searchPi = project.pi.map(p => `${p.email}-${p.name} ${p.surname}`).join(',');
            delete project.projectData;
            delete project.members;
            delete project.researchLines;
            return project
        }
    }
});

<|endoftext|>


<commit_before>define(["Ti/_/declare", "Ti/_/lang", "Ti/_/style", "Ti/_/UI/Widget", "Ti/UI"],
	function(declare, lang, style, Widget, UI) {

	var setStyle = style.set,
		on = require.on,
		InternalImageView = declare(Widget, {

			domType: "img",
			onload: null,
			onerror: null,

			constructor: function() {
				this.domNode.ondragstart = function() { return false; }; // Prevent images from being dragged
			},

			_getContentSize: function() {
				return {
					width: this.domNode.width,
					height: this.domNode.height
				}
			},

			_preLayout: function(boundingWidth, boundingHeight, isParentWidthSize, isParentHeightSize) {

				// We have to remove the old style to get the image to scale to its default size,
				// otherwise we are just reading in whatever we set in the last doLayout(), which is
				// 0 if the image was not loaded...thus always clamping it to 0.
				this.domNode.style.width = "";
				this.domNode.style.height = "";

				var imageRatio = this._imageRatio,
					values = this.properties.__values__,
					oldWidth = values.width,
					oldHeight = values.height;

				values.width = boundingHeight;
				values.height = boundingHeight;
				if (!isParentWidthSize && !isParentHeightSize) {
					if (boundingWidth / boundingHeight > imageRatio) {
						values.width *= imageRatio;
					} else {
						values.height /= imageRatio;
					}
				} else if (!isParentWidthSize) {
					values.height /= imageRatio;
				} else if (!isParentHeightSize) {
					values.width *= imageRatio;
				} else {
					values.width = UI.SIZE;
					values.height = UI.SIZE;
				}

				return oldWidth !== values.width || oldHeight !== values.height;
			},

			_imageRatio: 1,

			properties: {
				src: {
					set: function(value) {
						var node = this.domNode,
							disp = "none";
							onerror = lang.hitch(this, function(e) {
								this._triggerLayout();
								this.onerror && this.onerror(e);
							});

						if (value) {
							disp = "inherit";
							on(node, "load", this, function() {
								this.domNode.style.width = "";
								this.domNode.style.height = "";
								var imageRatio = this.domNode.width / this.domNode.height;
								isNaN(imageRatio) && (imageRatio = this.domNode.width === 0 ? 1 : Infinity);
								this._imageRatio = imageRatio;

								this.container._triggerLayout();
								this.onload && this.onload();
							});
							on(node, "error", onerror);
							on(node, "abort", onerror);
							node.src = require.cache(value) || value;
						}

						setStyle(node, "display", disp);
						return value;
					}
				}
			}
		});

	return declare("Ti.UI.ImageView", Widget, {

		_createImage: function(src, onload, onerror) {
			switch (src && src.declaredClass) {
				case "Ti.Filesystem.File":
					src = src.read();
				case "Ti.Blob":
					src = src.toString();
			}
			return new InternalImageView({
				onload: onload,
				onerror: onerror,
				src: src,
				container: this
			});
		},

		_defaultWidth: UI.SIZE,

		_defaultHeight: UI.SIZE,

		_slideshowCount: 0,

		_setSlideshowInterval: function() {
			var self = this,
				imgs = self._images;
			clearInterval(this._slideshowTimer);

			this._slideshowTimer = setInterval(function(){
				var rollover = false;

				setStyle(imgs[self._currentIndex].domNode, "display", "none");

				if (self.reverse) {
					if (--self._currentIndex === 0) {
						self._currentIndex = self.images.length - 1;
						rollover = true;
					}
				} else if (++self._currentIndex === self.images.length) {
					self._currentIndex = 0;
					rollover = true;
				}

				setStyle(imgs[self._currentIndex].domNode, "display", "inherit");

				if (self.repeatCount && rollover && ++self._slideshowCount === self.repeatCount) {
					self.stop();
					return;
				}

				self.fireEvent("change", {
					index: self._currentIndex
				});
			}, this.duration);
		},

		start: function(){
			if (this._images) {
				this._setState(1, 0);
				this._slideshowCount = 0;
				this._setSlideshowInterval();
				this.fireEvent("start");
			}
		},

		stop: function(){
			var imgs = this._images;
			if (imgs) {
				clearInterval(this._slideshowTimer);
				if (imgs.length) {
					var start = 0;
					this.reverse && (start = imgs.length - 1);
					this._currentIndex && setStyle(imgs[this._currentIndex].domNode, "display", "none");
					setStyle(imgs[start].domNode, "display", "inherit");
					this._currentIndex = start;
				}
				this._setState(0, 0);
				this.fireEvent("stop");
			}
		},

		pause: function(){
			if (this._images) {
				clearInterval(this._slideshowTimer);
				this._setState(1, 0);
				this.fireEvent("pause");
			}
		},

		resume: function() {
			if (this._images) {
				this._setSlideshowInterval();
				this._setState(0, 1);
			}
		},

		_setState: function(paused, animating) {
			this.constants.paused = !!paused;
			this.constants.animating = !!animating;
		},

		constants: {
			animating: false,
			paused: false
		},

		properties: {
			duration: 30,

			image: {
				set: function(value) {
					this._removeAllChildren();
					this._images = void 0;
					this.add(this._createImage(value, function() {
						this.fireEvent("load", {
							state: "image"
						});
					}, function(e) {
						this.fireEvent("error", e);
					}));
					return value;
				}
			},

			images: {
				set: function(value) {
					var imgs = void 0,
						counter = 0,
						errored = 0;
					this._removeAllChildren();
					if (require.is(value, "Array")) {
						imgs = [];
						value.forEach(function(val) {
							var img = this._createImage(val, function() {
								!errored && ++counter === value.length && this.fireEvent("load", {
									state: "image"
								});
							}, function(e) {
								errored || (errored = 1) && this.fireEvent("error", e);
							});
							setStyle(img.domNode, "display", "none");
							imgs.push(img);
							this.add(img);
						}, this);
					}
					this._images = imgs;
					return value;
				},

				post: function() {
					this.stop();
				}
			},

			repeatCount: 0,

			reverse: false
		}

	});

});<commit_msg>[TIMOB-8275] Bug fix in image view.<commit_after>define(["Ti/_/declare", "Ti/_/lang", "Ti/_/style", "Ti/_/UI/Widget", "Ti/UI"],
	function(declare, lang, style, Widget, UI) {

	var setStyle = style.set,
		on = require.on,
		InternalImageView = declare(Widget, {

			domType: "img",
			onload: null,
			onerror: null,

			constructor: function() {
				this.domNode.ondragstart = function() { return false; }; // Prevent images from being dragged
			},

			_getContentSize: function() {
				return {
					width: this.domNode.width,
					height: this.domNode.height
				}
			},

			_preLayout: function(boundingWidth, boundingHeight, isParentWidthSize, isParentHeightSize) {

				// We have to remove the old style to get the image to scale to its default size,
				// otherwise we are just reading in whatever we set in the last doLayout(), which is
				// 0 if the image was not loaded...thus always clamping it to 0.
				this.domNode.style.width = "";
				this.domNode.style.height = "";

				var imageRatio = this.domNode.width / this.domNode.height,
					values = this.properties.__values__
					oldWidth = values.width,
					oldHeight = values.height;

				if (!isParentWidthSize && !isParentHeightSize) {
					if (boundingWidth / boundingHeight > imageRatio) {
						values.width = boundingHeight * imageRatio;
						values.height = boundingHeight;
					} else {
						values.width = boundingWidth;
						values.height = boundingWidth / imageRatio;
					}
				} else if (!isParentWidthSize) {
					values.width = boundingWidth;
					values.height = boundingWidth / imageRatio;
				} else if (!isParentHeightSize) {
					values.width = boundingHeight * imageRatio;
					values.height = boundingHeight;
				} else {
					values.width = UI.SIZE;
					values.height = UI.SIZE;
				}

				return oldWidth !== values.width || oldHeight !== values.height;
			},

			_imageRatio: 1,

			properties: {
				src: {
					set: function(value) {
						var node = this.domNode,
							disp = "none";
							onerror = lang.hitch(this, function(e) {
								this._triggerLayout();
								this.onerror && this.onerror(e);
							});

						if (value) {
							disp = "inherit";
							on(node, "load", this, function() {
								this.domNode.style.width = "";
								this.domNode.style.height = "";
								var imageRatio = this.domNode.width / this.domNode.height;
								isNaN(imageRatio) && (imageRatio = this.domNode.width === 0 ? 1 : Infinity);
								this._imageRatio = imageRatio;

								this.container._triggerLayout();
								this.onload && this.onload();
							});
							on(node, "error", onerror);
							on(node, "abort", onerror);
							node.src = require.cache(value) || value;
						}

						setStyle(node, "display", disp);
						return value;
					}
				}
			}
		});

	return declare("Ti.UI.ImageView", Widget, {

		_createImage: function(src, onload, onerror) {
			switch (src && src.declaredClass) {
				case "Ti.Filesystem.File":
					src = src.read();
				case "Ti.Blob":
					src = src.toString();
			}
			return new InternalImageView({
				onload: onload,
				onerror: onerror,
				src: src,
				container: this
			});
		},

		_defaultWidth: UI.SIZE,

		_defaultHeight: UI.SIZE,

		_slideshowCount: 0,

		_setSlideshowInterval: function() {
			var self = this,
				imgs = self._images;
			clearInterval(this._slideshowTimer);

			this._slideshowTimer = setInterval(function(){
				var rollover = false;

				setStyle(imgs[self._currentIndex].domNode, "display", "none");

				if (self.reverse) {
					if (--self._currentIndex === 0) {
						self._currentIndex = self.images.length - 1;
						rollover = true;
					}
				} else if (++self._currentIndex === self.images.length) {
					self._currentIndex = 0;
					rollover = true;
				}

				setStyle(imgs[self._currentIndex].domNode, "display", "inherit");

				if (self.repeatCount && rollover && ++self._slideshowCount === self.repeatCount) {
					self.stop();
					return;
				}

				self.fireEvent("change", {
					index: self._currentIndex
				});
			}, this.duration);
		},

		start: function(){
			if (this._images) {
				this._setState(1, 0);
				this._slideshowCount = 0;
				this._setSlideshowInterval();
				this.fireEvent("start");
			}
		},

		stop: function(){
			var imgs = this._images;
			if (imgs) {
				clearInterval(this._slideshowTimer);
				if (imgs.length) {
					var start = 0;
					this.reverse && (start = imgs.length - 1);
					this._currentIndex && setStyle(imgs[this._currentIndex].domNode, "display", "none");
					setStyle(imgs[start].domNode, "display", "inherit");
					this._currentIndex = start;
				}
				this._setState(0, 0);
				this.fireEvent("stop");
			}
		},

		pause: function(){
			if (this._images) {
				clearInterval(this._slideshowTimer);
				this._setState(1, 0);
				this.fireEvent("pause");
			}
		},

		resume: function() {
			if (this._images) {
				this._setSlideshowInterval();
				this._setState(0, 1);
			}
		},

		_setState: function(paused, animating) {
			this.constants.paused = !!paused;
			this.constants.animating = !!animating;
		},

		constants: {
			animating: false,
			paused: false
		},

		properties: {
			duration: 30,

			image: {
				set: function(value) {
					this._removeAllChildren();
					this._images = void 0;
					this.add(this._createImage(value, function() {
						this.fireEvent("load", {
							state: "image"
						});
					}, function(e) {
						this.fireEvent("error", e);
					}));
					return value;
				}
			},

			images: {
				set: function(value) {
					var imgs = void 0,
						counter = 0,
						errored = 0;
					this._removeAllChildren();
					if (require.is(value, "Array")) {
						imgs = [];
						value.forEach(function(val) {
							var img = this._createImage(val, function() {
								!errored && ++counter === value.length && this.fireEvent("load", {
									state: "image"
								});
							}, function(e) {
								errored || (errored = 1) && this.fireEvent("error", e);
							});
							setStyle(img.domNode, "display", "none");
							imgs.push(img);
							this.add(img);
						}, this);
					}
					this._images = imgs;
					return value;
				},

				post: function() {
					this.stop();
				}
			},

			repeatCount: 0,

			reverse: false
		}

	});

});<|endoftext|>


<commit_before>const __cacheName = 'SERVICE_WORKER_CACHE_VERSION';

self.addEventListener('install', (event) => {
    console.log('Service Worker install..');
    event.waitUntil(
        caches
        .open(__cacheName)
        .then((cache) => {
            return cache.addAll(`
                ./
                css/fonts.css
                css/style.css
                img/mk5-logo_matreshka.svg
                img/mk5-logo_text.svg
                img/logos/shooju.png
                img/logos/habrahabr.svg
                img/logos/browserstack.svg
                img/liqpay-donate-button.png
                fonts/Material-Design-Icons.ttf
                fonts/Roboto-Regular.ttf
                fonts/Roboto-Bold.ttf
                fonts/Roboto-Light.ttf
                js/app.js
                icons/favicon.ico
          `.trim().split(/\s+/));
        })
        .then(() => {
            return caches.keys().then((cacheNames) => {
                return Promise.all(
                    cacheNames.map((cacheName) => {
                        if (__cacheName !== cacheName) {
                            return caches.delete(cacheName);
                        }
                    })
                )
            })
        })
    )
});

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches
        .match(event.request)
        .then(cachedResponse => cachedResponse || fetch(event.request))
        .catch(() => fetch(event.request))
    );
});
<commit_msg>trying to fix service worker issue<commit_after>const __cacheName = 'test';

self.addEventListener('install', (event) => {
    console.log('Service Worker install..');
    event.waitUntil(
        caches
        .open(__cacheName)
        .then((cache) => {
            return cache.addAll(`
                ./
                css/fonts.css
                css/style.css
                img/mk5-logo_matreshka.svg
                img/mk5-logo_text.svg
                img/logos/shooju.png
                img/logos/habrahabr.svg
                img/logos/browserstack.svg
                img/liqpay-donate-button.png
                fonts/Material-Design-Icons.ttf
                fonts/Roboto-Regular.ttf
                fonts/Roboto-Bold.ttf
                fonts/Roboto-Light.ttf
                js/app.js
                icons/favicon.ico
          `.trim().split(/\s+/));
        })
        .then(() => {
            return caches.keys().then((cacheNames) => {
                return Promise.all(
                    cacheNames.map((cacheName) => {
                        if (__cacheName !== cacheName) {
                            return caches.delete(cacheName);
                        }
                    })
                )
            })
        })
    )
});

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches
        .match(event.request)
        .then(cachedResponse => cachedResponse || fetch(event.request))
        .catch(() => fetch(event.request))
    );
});
<|endoftext|>


<commit_before>function AI(grid) {

	this.grid = grid;
	this.moves = [0,1,2,3];
	this.brain = new deepqlearn.Brain(19,4, {
		epsilon_test_time: 0.0 // Shut off random guess
	});
	this.previousMove = 0;

}

AI.prototype.getMaxVal = function() {
	var max = 0;
	this.grid.cells.forEach(function(row){
		row.forEach( function( curVal ){
			if( curVal && curVal.value > max )
				max = curVal.value;
		});
	});
	return max;
}

AI.prototype.getEmptyCount = function() {

	var count = 0;
	this.grid.cells.forEach(function(row) {
		row.forEach( function( curVal ) {
			if( curVal )
				return;

			count++;
		});
	});

	return count;

}

AI.prototype.buildInputs = function(score, moved, timesMoved) {

	var inputs = [];

	var max = this.getMaxVal();

	this.grid.cells.forEach(function(row, index) {
		row.forEach( function( curVal ) {

			if( curVal ){
				inputs.push( ( 1 + ( -1 / curVal.value ) ) );
			}else{
				inputs.push(0);
			}
		});
	});

	inputs.push( ( this.previousMove > 0 ) ? this.previousMove / 4      : 0 );
	inputs.push( ( score > 0 )             ? ( 1 + ( -1 / score ) )     : 0 );
	inputs.push( ( moved )                 ? 1                          : 0 );
	inputs.push( ( timesMoved > 0 )        ? ( 1 + (-1 / timesMoved ) ) : 0 );

	return inputs;

}

AI.prototype.getBest = function(meta) {
	return {
		move: this.moves[Math.floor(Math.random()*this.moves.length)]
	};
	var inputs = this.buildInputs( meta.score, meta.moved );
	var action = this.brain.forward( inputs );

	return {
		move: this.moves[action]
	};

}

AI.prototype.reward = function(meta) {

	var max = this.getMaxVal();
	if( meta.over && meta.won ){

		reward = 1;

	}else if( meta.score != meta.previous ) {

		reward  = ( 1 + (-1 / ( meta.score - meta.previous ) ) );
		reward += ( 1 + ( (-1 * max) / meta.score ) );
		reward += ( ( meta.timesMoved > 0 ) ? ( 1 + (-1 / meta.timesMoved ) ) : 0 );
		reward += ( ( meta.empty > 0 ) ? ( 1 + (-1 / meta.empty ) ) : 0 );
		reward /= 4;

	}else{

		reward = 0;

	}

	if( meta.over && !meta.won )
		reward *= -1;

	this.brain.backward( reward );
	this.brain.visSelf(document.getElementById('brainInfo'));

}

AI.prototype.rewardMultiple = function(meta){

	var max = this.getMaxVal();
	var scoreReward = ( 1 + (-1 / (meta.score - meta.previous ) ) );
	var maxReward = ( 1 + ( ( -1 * max ) / meta.score ) );
	var movesReward = ( ( meta.timesMoved > 0 ) ? ( 1 + (-1 / meta.timesMoved ) ) : 0);
	var emptyReward = ( ( meta.empty > 0 ) ? ( 1 + (-1 / meta.empty ) ) : 0 );

	this.brain.backward( scoreReward );
	this.brain.backward( maxReward );
	this.brain.backward( movesReward );
	this.brain.backward( emptyReward );
	this.brain.visSelf(document.getElementById('brainInfo'));

}
<commit_msg>Remove random best move<commit_after>function AI(grid) {

	this.grid = grid;
	this.moves = [0,1,2,3];
	this.brain = new deepqlearn.Brain(19,4, {
		epsilon_test_time: 0.0 // Shut off random guess
	});
	this.previousMove = 0;

}

AI.prototype.getMaxVal = function() {
	var max = 0;
	this.grid.cells.forEach(function(row){
		row.forEach( function( curVal ){
			if( curVal && curVal.value > max )
				max = curVal.value;
		});
	});
	return max;
}

AI.prototype.getEmptyCount = function() {

	var count = 0;
	this.grid.cells.forEach(function(row) {
		row.forEach( function( curVal ) {
			if( curVal )
				return;

			count++;
		});
	});

	return count;

}

AI.prototype.buildInputs = function(score, moved, timesMoved) {

	var inputs = [];

	var max = this.getMaxVal();

	this.grid.cells.forEach(function(row, index) {
		row.forEach( function( curVal ) {

			if( curVal ){
				inputs.push( ( 1 + ( -1 / curVal.value ) ) );
			}else{
				inputs.push(0);
			}
		});
	});

	inputs.push( ( this.previousMove > 0 ) ? this.previousMove / 4      : 0 );
	inputs.push( ( score > 0 )             ? ( 1 + ( -1 / score ) )     : 0 );
	inputs.push( ( moved )                 ? 1                          : 0 );
	inputs.push( ( timesMoved > 0 )        ? ( 1 + (-1 / timesMoved ) ) : 0 );

	return inputs;

}

AI.prototype.getBest = function(meta) {

	var inputs = this.buildInputs( meta.score, meta.moved );
	var action = this.brain.forward( inputs );

	return {
		move: this.moves[action]
	};

}

AI.prototype.reward = function(meta) {

	var max = this.getMaxVal();
	if( meta.over && meta.won ){

		reward = 1;

	}else if( meta.score != meta.previous ) {

		reward  = ( 1 + (-1 / ( meta.score - meta.previous ) ) );
		reward += ( 1 + ( (-1 * max) / meta.score ) );
		reward += ( ( meta.timesMoved > 0 ) ? ( 1 + (-1 / meta.timesMoved ) ) : 0 );
		reward += ( ( meta.empty > 0 ) ? ( 1 + (-1 / meta.empty ) ) : 0 );
		reward /= 4;

	}else{

		reward = 0;

	}

	if( meta.over && !meta.won )
		reward *= -1;

	this.brain.backward( reward );
	this.brain.visSelf(document.getElementById('brainInfo'));

}

AI.prototype.rewardMultiple = function(meta){

	var max = this.getMaxVal();
	var scoreReward = ( 1 + (-1 / (meta.score - meta.previous ) ) );
	var maxReward = ( 1 + ( ( -1 * max ) / meta.score ) );
	var movesReward = ( ( meta.timesMoved > 0 ) ? ( 1 + (-1 / meta.timesMoved ) ) : 0);
	var emptyReward = ( ( meta.empty > 0 ) ? ( 1 + (-1 / meta.empty ) ) : 0 );

	this.brain.backward( scoreReward );
	this.brain.backward( maxReward );
	this.brain.backward( movesReward );
	this.brain.backward( emptyReward );
	this.brain.visSelf(document.getElementById('brainInfo'));

}
<|endoftext|>


<commit_before>var fblog = {
    $tagTop: $('.fblog-tag-top'),
    $articleListContainer: $('#fblog_article_list_container'),
    $containerWidgetTags: $('#container_widget_tags'),
    $containerWidgetCategories: $('#container_widget_categories'),
    colors: ["#23D160",
            "#FF3860",
            "#72D0EB",
            "#FFDD57",
            "#4A4A4A",
            "#DC6BDB",
            "#FFB11B",
            "#13CCAB",
            "#FF634B"]
};

(function (fblog) {

    fblog.loadTopTags = function () {
        $.getJSON("/tag/top?num=20", function (data) {
            if (!data) {
                return;
            }
            fblog.$containerWidgetTags.empty();
            fblog.$containerWidgetTags.parent().delay('fast').fadeTo(500, 1);

           $.each(data, function (i, tag) {
               var color = fblog.getRandomColor();

               var $tag = $('' +
                   '    ' + tag.name + '' +
                   '');
               fblog.$containerWidgetTags.append($tag);
               $tag.fadeIn(700);
           });
        })
    };

    /**
     * 获取随机颜色
     * @returns {*}
     */
    fblog.getRandomColor = function () {
        var randomIndex = Math.floor(Math.random() * fblog.colors.length);
        var color = fblog.colors[randomIndex];
        return color;
    };

    fblog.bind = function () {

        //搜索
        $(document).on('click', '#btn_fblog_search', function () {
            if (fblog.checkSearch()) {

                $('form[role=search]').submit();
            }
        });
    };

    fblog.loadCategorys = function () {
        $.getJSON("/category/list", {
            pageCurrent: 1,
            pageSize: 10
        }, function (data) {

            if (data) {
                fblog.$containerWidgetCategories.empty();
                fblog.$containerWidgetCategories.parent().fadeTo(300,1);
                $.each(data.list, function (i, category) {
                    var $category = $('' + category.name + '');
                    $category.hide();
                    fblog.$containerWidgetCategories.append($category);
                    $category.fadeIn(500);
                });
            }
        });
    };

    fblog.loadArticleTags = function () {
        var $articleDetailTagsContent = $('#article_detail_tags_content');
        var articleId = $('#hidden_article_detail_article_id').val();
        if ($articleDetailTagsContent) {
            $.getJSON("/article/tags?articleId=" + articleId, function (data) {
                if (!data) {
                    return;
                }
                $.each(data, function (i, tag) {
                    var color = fblog.getRandomColor();
                    var $tag = $('' +
                        '    ' + tag.name + '' +
                        '');

                    $articleDetailTagsContent.append($tag);
                    $tag.fadeIn();
                });
            });
        }
    };
    fblog.init = function () {

        fblog.bind();
        fblog.loadTopTags();
        fblog.loadCategorys();

        //detail
        fblog.loadArticleTags();
    };

    fblog.checkSearch = function () {
        var search = $('#input_fblog_search').val();
        if (!search) {
            return false;
        }
        return true;
    }

    fblog.init();
})(fblog);

<commit_msg>详情页标签:smile:<commit_after>var fblog = {
    $tagTop: $('.fblog-tag-top'),
    $articleListContainer: $('#fblog_article_list_container'),
    $containerWidgetTags: $('#container_widget_tags'),
    $containerWidgetCategories: $('#container_widget_categories'),
    colors: ["#23D160",
            "#FF3860",
            "#72D0EB",
            "#FFDD57",
            "#4A4A4A",
            "#DC6BDB",
            "#FFB11B",
            "#13CCAB",
            "#FF634B"]
};

(function (fblog) {

    fblog.loadTopTags = function () {
        $.getJSON("/tag/top?num=20", function (data) {
            if (!data) {
                return;
            }
            fblog.$containerWidgetTags.empty();
            fblog.$containerWidgetTags.parent().delay('fast').fadeTo(500, 1);

           $.each(data, function (i, tag) {
               var color = fblog.getRandomColor();

               var $tag = $('' +
                   '    ' + tag.name + '' +
                   '');
               fblog.$containerWidgetTags.append($tag);
               $tag.fadeIn(700);
           });
        })
    };

    /**
     * 获取随机颜色
     * @returns {*}
     */
    fblog.getRandomColor = function () {
        var randomIndex = Math.floor(Math.random() * fblog.colors.length);
        var color = fblog.colors[randomIndex];
        return color;
    };

    fblog.bind = function () {

        //搜索
        $(document).on('click', '#btn_fblog_search', function () {
            if (fblog.checkSearch()) {

                $('form[role=search]').submit();
            }
        });
    };

    fblog.loadCategorys = function () {
        $.getJSON("/category/list", {
            pageCurrent: 1,
            pageSize: 10
        }, function (data) {

            if (data) {
                fblog.$containerWidgetCategories.empty();
                fblog.$containerWidgetCategories.parent().fadeTo(300,1);
                $.each(data.list, function (i, category) {
                    var $category = $('' + category.name + '');
                    $category.hide();
                    fblog.$containerWidgetCategories.append($category);
                    $category.fadeIn(500);
                });
            }
        });
    };

    fblog.loadArticleTags = function () {
        var $articleDetailTagsContent = $('#article_detail_tags_content');
        var articleId = $('#hidden_article_detail_article_id').val();
        if ($articleDetailTagsContent) {
            $.getJSON("/article/tags?articleId=" + articleId, function (data) {
                if (data.statusCode != 200) {
                    return;
                }
                $.each(data.data, function (i, tag) {
                    var color = fblog.getRandomColor();
                    var $tag = $('' +
                        '    ' + tag.name + '' +
                        '');

                    $articleDetailTagsContent.append($tag);
                    $tag.fadeIn();
                });
            });
        }
    };
    fblog.init = function () {

        fblog.bind();
        fblog.loadTopTags();
        fblog.loadCategorys();

        //detail
        fblog.loadArticleTags();
    };

    fblog.checkSearch = function () {
        var search = $('#input_fblog_search').val();
        if (!search) {
            return false;
        }
        return true;
    }

    fblog.init();
})(fblog);

<|endoftext|>


<commit_before>/*
 * Copyright 2017 Alexandre Moreno <alex_moreno@tutk.com>
 *
 * This file is part of node-lwm2m
 *
 * node-lwm2m 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, either version 3 of the License,
 * or (at your option) any later version.
 *
 * node-lwm2m 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 node-lwm2m.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[contacto@tid.es]
 *
 */

'use strict';

function _matches(val, type) {
  function typeOf(val) {
    return Object.prototype.toString.call(val).slice(8, -1);
  }

  type = type.name || type;

  if (type === 'Buffer') {
    return Buffer.isBuffer(val);
  }

  if (!Array.isArray(type)) {
    return type === typeOf(val);
  }

  if (Array.isArray(val) && Array.isArray(type)) {
    return _matches(val[0], type[0]);
  }

  return false;
}

function _enum(values) {
  return function(val) {
    return values.indexOf(val) !== -1;
  };
}

function _range(values) {
  return function(val) {
    return values.min <= val && val <= values.max;
  };
}

function _validateResource(res, val) {
  var ok = _matches(val, res.type);
  var check;

  if (res.enum) {
    check = _enum(res.enum);
  } else if (res.range) {
    check = _range(res.range);
  }

  if (ok && check !== undefined) {
    return check(val);
  }

  return ok;
}

function _validateSchema(schema) {
  function _validResourceType(type) {
    if (Array.isArray(type)) {
      type = type[0];
    }

    type = type.name || type;

    return [
      'String',
      'Number',
      'Boolean',
      'Buffer',
    ].indexOf(type) > -1;
  }

  var keys = Object.keys(schema);

  for (var i = 0; i < keys.length; ++i) {

    var res = schema[keys[i]];
    var ok = true;

    if (typeof res !== 'object') {
      ok = false;
    }

    if (typeof res.id !== 'number') {
      ok = false;
    }

    if (!_validResourceType(res.type)) {
      ok = false;
    }

    if (res.range && typeof res.range !== 'object') {
      ok = false;
    }

    if (res.enum && !Array.isArray(res.enum)) {
      ok = false;
    }

    if (!ok) {
      throw new TypeError('Bad definiton `' + keys[i] + '`');
    }
  }
}

function _ids(schema) {
  return Object.keys(schema).reduce(function(acc, key) {
    var id = schema[key].id;
    acc[id] = key;
    return acc;
  }, {});
}

/**
 * Schema constructor.
 *
 * An `Schema` describes the shape of an LWM2M Object.
 * An Object is a collection of resources with the following properties:
 *
 * - `id`: the Resource ID
 * - `type`: String | Number | Boolean | Buffer; [type] for multiple instances
 * - `enum`: values are enumerated (Optional)
 * - `range`: values are within a range (Optional)
 * - `required`: the resource is mandatory. Defaults to `false`
 *
 * See [oma](lib/oma) directory for default definitions.
 *
 * @example
 *
 * // IPSO temperature sensor
 * var temperature = new Schema({
 *   sensorValue: {
 *     id: 5700,
 *     type: Number,
 *     required: true
 *   },
 *   units: {
 *     id: 5701,
 *     type: String
 *   }
 * });
 *
 * // IPSO light controller
 * var lightControl = new Schema({
 *   onOff: {
 *    id : 5850,
 *    type: Boolean,
 *    required: true
 *   },
 *   dimmer: {
 *     type: Number,
 *     id: 5851,
 *     range: { min: 0, max: 100 }
 *   },
 *   units: {
 *     id: 5701,
 *     type: String
 *   }
 * });
 *
 * // Bad schema
 * var schema = new Schema({
 *   a: { type: String, id: 0 },
 *   b: { type: Error, id: 1 },
 * }); // throws TypeError
 *
 * @param {Object} resources
 * @throws Will throw an error if fails to validate
 */
function Schema(resources) {
  if (!(this instanceof Schema)) {
    return new Schema(resources);
  }

  _validateSchema(resources);
  this.id = _ids(resources);
  this.resources = Object.assign({}, resources);

  if (this.constructor === Schema) {
    Object.freeze(this);
  }
}

/**
 * validates `obj` with `schema`.
 *
 * @param {Object} obj
 * @throws Will throw an error if fails to validate
 * @example
 *
 * var schema = new Schema({
 *   a: { type: String, id: 0 },
 *   b: { type: Buffer, id: 1 },
 * });
 *
 * schema.validate({
 *   a: 'foo',
 *   b: Buffer.from('bar'),
 * }); // OK
 *
 * schema.validate({
 *   a: 'foo',
 *   b: 'bar',
 * }); // Throws error
 *
 */
Schema.prototype.validate = function(obj) {
  var keys, ok, key, res, val;

  keys = Object.keys(obj);

  if (!keys.length) {
    throw new TypeError('Invalid object: `' + obj + '`');
  }

  if (keys.length > 1) { // not single resource
    keys = Object.keys(this.resources);
  }

  for (var i = 0; i < keys.length; ++i) {
    key = keys[i];

    if (!this.resources[key]) {
      throw new TypeError('Invalid resource: `' + key + '`');
    }

    res = Object.assign({ required: false },
      this.resources[key]);
    val = obj[key];

    ok = _validateResource(res, val);

    if (val !== undefined && !ok) {
      throw new TypeError('Invalid resource: `' + key + '`');
    }

    if (res.required && !ok) {
      throw new TypeError('Missing resource: `' + key + '`');
    }
  }
};

module.exports = Schema;
<commit_msg>schema: add custom inspect function<commit_after>/*
 * Copyright 2017 Alexandre Moreno <alex_moreno@tutk.com>
 *
 * This file is part of node-lwm2m
 *
 * node-lwm2m 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, either version 3 of the License,
 * or (at your option) any later version.
 *
 * node-lwm2m 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 node-lwm2m.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[contacto@tid.es]
 *
 */

'use strict';

function _matches(val, type) {
  function typeOf(val) {
    return Object.prototype.toString.call(val).slice(8, -1);
  }

  type = type.name || type;

  if (type === 'Buffer') {
    return Buffer.isBuffer(val);
  }

  if (!Array.isArray(type)) {
    return type === typeOf(val);
  }

  if (Array.isArray(val) && Array.isArray(type)) {
    return _matches(val[0], type[0]);
  }

  return false;
}

function _enum(values) {
  return function(val) {
    return values.indexOf(val) !== -1;
  };
}

function _range(values) {
  return function(val) {
    return values.min <= val && val <= values.max;
  };
}

function _validateResource(res, val) {
  var ok = _matches(val, res.type);
  var check;

  if (res.enum) {
    check = _enum(res.enum);
  } else if (res.range) {
    check = _range(res.range);
  }

  if (ok && check !== undefined) {
    return check(val);
  }

  return ok;
}

function _validateSchema(schema) {
  function _validResourceType(type) {
    if (Array.isArray(type)) {
      type = type[0];
    }

    type = type.name || type;

    return [
      'String',
      'Number',
      'Boolean',
      'Buffer',
    ].indexOf(type) > -1;
  }

  var keys = Object.keys(schema);

  for (var i = 0; i < keys.length; ++i) {

    var res = schema[keys[i]];
    var ok = true;

    if (typeof res !== 'object') {
      ok = false;
    }

    if (typeof res.id !== 'number') {
      ok = false;
    }

    if (!_validResourceType(res.type)) {
      ok = false;
    }

    if (res.range && typeof res.range !== 'object') {
      ok = false;
    }

    if (res.enum && !Array.isArray(res.enum)) {
      ok = false;
    }

    if (!ok) {
      throw new TypeError('Bad definiton `' + keys[i] + '`');
    }
  }
}

function _ids(schema) {
  return Object.keys(schema).reduce(function(acc, key) {
    var id = schema[key].id;
    acc[id] = key;
    return acc;
  }, {});
}

/**
 * Schema constructor.
 *
 * An `Schema` describes the shape of an LWM2M Object.
 * An Object is a collection of resources with the following properties:
 *
 * - `id`: the Resource ID
 * - `type`: String | Number | Boolean | Buffer; [type] for multiple instances
 * - `enum`: values are enumerated (Optional)
 * - `range`: values are within a range (Optional)
 * - `required`: the resource is mandatory. Defaults to `false`
 *
 * See [oma](lib/oma) directory for default definitions.
 *
 * @example
 *
 * // IPSO temperature sensor
 * var temperature = new Schema({
 *   sensorValue: {
 *     id: 5700,
 *     type: Number,
 *     required: true
 *   },
 *   units: {
 *     id: 5701,
 *     type: String
 *   }
 * });
 *
 * // IPSO light controller
 * var lightControl = new Schema({
 *   onOff: {
 *    id : 5850,
 *    type: Boolean,
 *    required: true
 *   },
 *   dimmer: {
 *     type: Number,
 *     id: 5851,
 *     range: { min: 0, max: 100 }
 *   },
 *   units: {
 *     id: 5701,
 *     type: String
 *   }
 * });
 *
 * // Bad schema
 * var schema = new Schema({
 *   a: { type: String, id: 0 },
 *   b: { type: Error, id: 1 },
 * }); // throws TypeError
 *
 * @param {Object} resources
 * @throws Will throw an error if fails to validate
 */
function Schema(resources) {
  if (!(this instanceof Schema)) {
    return new Schema(resources);
  }

  _validateSchema(resources);
  this.id = _ids(resources);
  this.resources = Object.assign({}, resources);

  if (this.constructor === Schema) {
    Object.freeze(this);
  }
}

/**
 * validates `obj` with `schema`.
 *
 * @param {Object} obj
 * @throws Will throw an error if fails to validate
 * @example
 *
 * var schema = new Schema({
 *   a: { type: String, id: 0 },
 *   b: { type: Buffer, id: 1 },
 * });
 *
 * schema.validate({
 *   a: 'foo',
 *   b: Buffer.from('bar'),
 * }); // OK
 *
 * schema.validate({
 *   a: 'foo',
 *   b: 'bar',
 * }); // Throws error
 *
 */
Schema.prototype.validate = function(obj) {
  var keys, ok, key, res, val;

  keys = Object.keys(obj);

  if (!keys.length) {
    throw new TypeError('Invalid object: `' + obj + '`');
  }

  if (keys.length > 1) { // not single resource
    keys = Object.keys(this.resources);
  }

  for (var i = 0; i < keys.length; ++i) {
    key = keys[i];

    if (!this.resources[key]) {
      throw new TypeError('Invalid resource: `' + key + '`');
    }

    res = Object.assign({ required: false },
      this.resources[key]);
    val = obj[key];

    ok = _validateResource(res, val);

    if (val !== undefined && !ok) {
      throw new TypeError('Invalid resource: `' + key + '`');
    }

    if (res.required && !ok) {
      throw new TypeError('Missing resource: `' + key + '`');
    }
  }
};

Schema.prototype.inspect = function() {
  return this.resources;
};

module.exports = Schema;
<|endoftext|>


<commit_before>/**
 * Created by Håkon Ødegård Løvdal on 30/04/15.
 */

var Subscribers = (function($) {

    // Private variable holding the subscribers array returned upon the ajax-request.
    var subscribers;

    var _PAGESIZE = 25; // Variable holding the size of each paginator page.
    var _CURRENTPAGE = 1; // Variable holding the last page showed in the paginator.

    /*
        This function sets up the pagination with the correct values.
        It also fills the new paginator with the correct table.
     */
    var setupPagination = function() {
        $('#pagination-selector').twbsPagination({
            totalPages: numberOfPages(),
            startPage: _CURRENTPAGE,
            visiblePages: 10,
            onPageClick: function(e, page) {
                _CURRENTPAGE = page
                var decrementedPage = (page - 1),
                    fromIndex = (_PAGESIZE * decrementedPage),
                    toIndex = (_PAGESIZE * decrementedPage) + _PAGESIZE
                $.okseDebug.logPrint("[Debug][Subscriber] Clicked page: " + page + " and trying to populate it with [" + fromIndex + "," + toIndex + "]")
                fillTable(fromIndex, toIndex)
            }
        })
        if (subscribers.length > 0) {
            var decrementedPage = (_CURRENTPAGE - 1),
                fromIndex = (_PAGESIZE * decrementedPage),
                toIndex = (_PAGESIZE * decrementedPage) + _PAGESIZE
            fillTable(fromIndex, toIndex)
        }
    }

    /*
        This function calculates the pages needed for the correct subscribers list.
     */
    var numberOfPages = function() {
        return Math.ceil(subscribers.length / _PAGESIZE);
    }

    /*
        This function does all checks required to find out the correct paginator to append (or remove)
        from the DOM. See each check to see what they do.
     */
    var checkIfPaginationIsNeeded = function() {
        var pageData = $('#pagination-selector').data(); // This variable holds the data-object for the paginator-element.

        // Do we need a paginator to populate the table?
        if (numberOfPages() < 2) {
            $.okseDebug.logPrint("[Debug][Subscriber] There is no need for the paginator; filling table without it")
            if ( typeof pageData.twbsPagination != 'undefined') {
                $.okseDebug.logPrint("[Debug][Subscriber] Paginator already exists, but we don't need it, so we destroy it")
                $('#pagination-selector').twbsPagination('destroy')
            }
            fillTable()
            return;
        }

        // If the data-object for twbsPagination is undefined, we create a new one; else we create one
        // based on the needed pages.
        if ( typeof pageData.twbsPagination == 'undefined' ) {
            $.okseDebug.logPrint("[Debug][Subscriber] Creating a new paginator!")
            _CURRENTPAGE = 1; // Need to reset the _CURRENTPAGE
            setupPagination()
        } else {
            // If _CURRENTPAGE is greater than needed pages, we decrement it to the needed numbers
            if (_CURRENTPAGE > numberOfPages()) {
                $.okseDebug.logPrint("[Debug][Subscriber] Decrementing the current page to needed number since _CURRENTPAGE > numberOfPages()")
                _CURRENTPAGE = numberOfPages()
            }
            $.okseDebug.logPrint("[Debug][Subscriber] Paginator were defined but destroyed to initiate with new values: {" +
                "startPage:" + _CURRENTPAGE + " totalPages: " + numberOfPages() + "}");
            $('#pagination-selector').twbsPagination('destroy')
            setupPagination()
        }
    }

    /*
        This function fills the #subscribers-table with the given input list
     */
    var fillTable = function(from, to) {
        unBindButtons()
        if (from === undefined || to === undefined) {
            $.okseDebug.logPrint("[Debug][Subscriber] Filling table with the complete list")
            $('#subscribers-table').html(createTableForSubscribers(subscribers))
        } else {
            $.okseDebug.logPrint("[Debug][Subscriber] Filling table with [" + from + "," + to + "]")
            var subscribersToPopulate = subscribers.slice(from, to)
            $('#subscribers-table').html(createTableForSubscribers(subscribersToPopulate))
        }
        bindButtons()
    }

    // Create a string of all filters to fill the table cell with
    var createFilterSetString = function(filterSet) {
        if ( ! filterSet.length == 0) {
            var returnString = ""
            $.each(filterSet, function(i, filter) {
               returnString += filter + "\n"
            });
            return returnString;
        } else {
            return "";
        }
    }

    /*
     Creates, fills and returns a
-element. The
-element is generated based on the subscribers
     list from the OKSE-RestAPI. It also adds all the buttons needed for deleting subscribers. It uses the id for
     this purpose. This function does not manipulate the DOM by checking if an element exists. It overwrites everything.
     */
    var createTableForSubscribers = function(subscribers) {
        var trHTML = '';
        $.each(subscribers, function (i, subscriber) {
            trHTML +=
                '
' +
                '' + subscriber.topic + '	' +
                '' + subscriber.originProtocol + '	' + // TODO: Add support for no protocol here when available
                '' + subscriber.host + '	' +
                '' + subscriber.port + '	' +
                '' + createFilterSetString(subscriber.filterSet) + '	' +
                'Delete	' +
                '
';
        });
        return trHTML
    }

    var unBindButtons = function() {
        $('.delete-subscriber').off('click')
    }

    var bindButtons = function() {
         $('.delete-subscriber').on('click', function(e) {
            e.preventDefault()

             if (confirm("Are you sure you want to delete this subscriber?")) {

                 var subscriberID = $(e.target).closest('tr').attr('id')
                 $(e.target).closest("tr").addClass("deleted")
                 $(e.target).addClass("disabled")

                 Main.ajax({
                    url: 'subscriber/delete/' + subscriberID,
                    type: 'DELETE',
                    success: function(subscriber) {
                        $.okseDebug.logPrint("[Debug][Subscriber] Callback from server; subscriber deleted")
                    },
                    error: function(xhr, status, error) {
                        $.okseDebug.logPrint("[Debug][Subscriber] Unable to remove subscriber with id: " + e.target.id)
                        $(e.target).closest("tr").removeClass("deleted")
                        $(e.target).removeClass("disabled")
                        Main.error(xhr, status, error)
                    }
                });
            }
         });
    }

    return {
        init: function() {
            $('#delete-all-subscribers').on('click', function(e) {
                e.preventDefault()

                if (confirm("Are you sure you want to delete all subscribers?")) {

                    Main.ajax({
                        url: 'subscriber/delete/all',
                        type: 'DELETE',
                        success: function(data) {
                            $.okseDebug.logPrint("[Debug][Topics] Callback from server; deleted all subscribers")
                            // Disable all subscribers and buttons
                            if (data.deleted == true) {
                                $('#subscribers-table').addClass('deleted')
                                $('#subscribers-table').find('a').each(function() {
                                    $(this).addClass('disabled')
                                });
                            }
                        },
                        error: function(xhr, status, error) {
                            Main.displayMessage('Unable to remove all subscribers!')
                            Main.error(xhr, status, error)
                        }
                    });
                }
            });
            /*
             * Add a listener to clear interval
             * */
            $("#subscribers-button-refresh").on("click", function(e) {
                e.preventDefault()
                if (!$(this).hasClass("active")) {
                    $(this).addClass("active")
                    $(this).text("Stop refresh")
                    Main.setIntervalForTab({
                        url: 'subscriber/get/all',
                        type: 'GET',
                        success: Subscribers.refresh
                    })
                } else {
                    $(this).removeClass("active")
                    $(this).text("Start refresh")
                    Main.clearIntervalForTab()
                }
            })
        },
        refresh: function(data) {
            subscribers = data;
            if (!subscribers.length == 0) {
                checkIfPaginationIsNeeded()
            } else {
                $('#subscribers-table').html('

No subscribers returned from SubscriptionsService

')
            }
            // Remove 'deleted class' if it exists
            if ($('#subscribers-table').hasClass('deleted')) { $('#subscribers-table').removeClass('deleted'); }
        }
    }

})(jQuery);

<commit_msg>Fixed bug that made paginator not disappear when it should<commit_after>/**
 * Created by Håkon Ødegård Løvdal on 30/04/15.
 */

var Subscribers = (function($) {

    // Private variable holding the subscribers array returned upon the ajax-request.
    var subscribers;

    var _PAGESIZE = 25; // Variable holding the size of each paginator page.
    var _CURRENTPAGE = 1; // Variable holding the last page showed in the paginator.

    /*
        This function sets up the pagination with the correct values.
        It also fills the new paginator with the correct table.
     */
    var setupPagination = function() {
        $('#pagination-selector').twbsPagination({
            totalPages: numberOfPages(),
            startPage: _CURRENTPAGE,
            visiblePages: 10,
            onPageClick: function(e, page) {
                _CURRENTPAGE = page
                var decrementedPage = (page - 1),
                    fromIndex = (_PAGESIZE * decrementedPage),
                    toIndex = (_PAGESIZE * decrementedPage) + _PAGESIZE
                $.okseDebug.logPrint("[Debug][Subscriber] Clicked page: " + page + " and trying to populate it with [" + fromIndex + "," + toIndex + "]")
                fillTable(fromIndex, toIndex)
            }
        })
        if (subscribers.length > 0) {
            var decrementedPage = (_CURRENTPAGE - 1),
                fromIndex = (_PAGESIZE * decrementedPage),
                toIndex = (_PAGESIZE * decrementedPage) + _PAGESIZE
            fillTable(fromIndex, toIndex)
        }
    }

    /*
        This function calculates the pages needed for the correct subscribers list.
     */
    var numberOfPages = function() {
        return Math.ceil(subscribers.length / _PAGESIZE);
    }

    /*
        This function does all checks required to find out the correct paginator to append (or remove)
        from the DOM. See each check to see what they do.
     */
    var checkIfPaginationIsNeeded = function() {
        var pageData = $('#pagination-selector').data(); // This variable holds the data-object for the paginator-element.

        // Do we need a paginator to populate the table?
        if (numberOfPages() < 2) {
            $.okseDebug.logPrint("[Debug][Subscriber] There is no need for the paginator; filling table without it")
            if ( typeof pageData.twbsPagination != 'undefined') {
                $.okseDebug.logPrint("[Debug][Subscriber] Paginator already exists, but we don't need it, so we destroy it")
                $('#pagination-selector').twbsPagination('destroy')
            }
            fillTable()
            return;
        }

        // If the data-object for twbsPagination is undefined, we create a new one; else we create one
        // based on the needed pages.
        if ( typeof pageData.twbsPagination == 'undefined' ) {
            $.okseDebug.logPrint("[Debug][Subscriber] Creating a new paginator!")
            _CURRENTPAGE = 1; // Need to reset the _CURRENTPAGE
            setupPagination()
        } else {
            // If _CURRENTPAGE is greater than needed pages, we decrement it to the needed numbers
            if (_CURRENTPAGE > numberOfPages()) {
                $.okseDebug.logPrint("[Debug][Subscriber] Decrementing the current page to needed number since _CURRENTPAGE > numberOfPages()")
                _CURRENTPAGE = numberOfPages()
            }
            $.okseDebug.logPrint("[Debug][Subscriber] Paginator were defined but destroyed to initiate with new values: {" +
                "startPage:" + _CURRENTPAGE + " totalPages: " + numberOfPages() + "}");
            $('#pagination-selector').twbsPagination('destroy')
            setupPagination()
        }
    }

    /*
        This function fills the #subscribers-table with the given input list
     */
    var fillTable = function(from, to) {
        unBindButtons()
        if (subscribers.length == 0) {
            $('#subscribers-table').html('

No subscribers returned from SubscriptionsService

')
            return;
        }
        if (from === undefined || to === undefined) {
            $.okseDebug.logPrint("[Debug][Subscriber] Filling table with the complete list")
            $('#subscribers-table').html(createTableForSubscribers(subscribers))
        } else {
            $.okseDebug.logPrint("[Debug][Subscriber] Filling table with [" + from + "," + to + "]")
            var subscribersToPopulate = subscribers.slice(from, to)
            $('#subscribers-table').html(createTableForSubscribers(subscribersToPopulate))
        }
        bindButtons()
    }

    // Create a string of all filters to fill the table cell with
    var createFilterSetString = function(filterSet) {
        if ( ! filterSet.length == 0) {
            var returnString = ""
            $.each(filterSet, function(i, filter) {
               returnString += filter + "\n"
            });
            return returnString;
        } else {
            return "";
        }
    }

    /*
     Creates, fills and returns a
-element. The
-element is generated based on the subscribers
     list from the OKSE-RestAPI. It also adds all the buttons needed for deleting subscribers. It uses the id for
     this purpose. This function does not manipulate the DOM by checking if an element exists. It overwrites everything.
     */
    var createTableForSubscribers = function(subscribers) {
        var trHTML = '';
        $.each(subscribers, function (i, subscriber) {
            trHTML +=
                '
' +
                '' + subscriber.topic + '	' +
                '' + subscriber.originProtocol + '	' + // TODO: Add support for no protocol here when available
                '' + subscriber.host + '	' +
                '' + subscriber.port + '	' +
                '' + createFilterSetString(subscriber.filterSet) + '	' +
                'Delete	' +
                '
';
        });
        return trHTML
    }

    var unBindButtons = function() {
        $('.delete-subscriber').off('click')
    }

    var bindButtons = function() {
         $('.delete-subscriber').on('click', function(e) {
            e.preventDefault()

             if (confirm("Are you sure you want to delete this subscriber?")) {

                 var subscriberID = $(e.target).closest('tr').attr('id')
                 $(e.target).closest("tr").addClass("deleted")
                 $(e.target).addClass("disabled")

                 Main.ajax({
                    url: 'subscriber/delete/' + subscriberID,
                    type: 'DELETE',
                    success: function(subscriber) {
                        $.okseDebug.logPrint("[Debug][Subscriber] Callback from server; subscriber deleted")
                    },
                    error: function(xhr, status, error) {
                        $.okseDebug.logPrint("[Debug][Subscriber] Unable to remove subscriber with id: " + e.target.id)
                        $(e.target).closest("tr").removeClass("deleted")
                        $(e.target).removeClass("disabled")
                        Main.error(xhr, status, error)
                    }
                });
            }
         });
    }

    return {
        init: function() {
            $('#delete-all-subscribers').on('click', function(e) {
                e.preventDefault()

                if (confirm("Are you sure you want to delete all subscribers?")) {

                    Main.ajax({
                        url: 'subscriber/delete/all',
                        type: 'DELETE',
                        success: function(data) {
                            $.okseDebug.logPrint("[Debug][Topics] Callback from server; deleted all subscribers")
                            // Disable all subscribers and buttons
                            if (data.deleted == true) {
                                $('#subscribers-table').addClass('deleted')
                                $('#subscribers-table').find('a').each(function() {
                                    $(this).addClass('disabled')
                                });
                            }
                        },
                        error: function(xhr, status, error) {
                            Main.displayMessage('Unable to remove all subscribers!')
                            Main.error(xhr, status, error)
                        }
                    });
                }
            });
            /*
             * Add a listener to clear interval
             * */
            $("#subscribers-button-refresh").on("click", function(e) {
                e.preventDefault()
                if (!$(this).hasClass("active")) {
                    $(this).addClass("active")
                    $(this).text("Stop refresh")
                    Main.setIntervalForTab({
                        url: 'subscriber/get/all',
                        type: 'GET',
                        success: Subscribers.refresh
                    })
                } else {
                    $(this).removeClass("active")
                    $(this).text("Start refresh")
                    Main.clearIntervalForTab()
                }
            })
        },
        refresh: function(data) {
            subscribers = data;
            checkIfPaginationIsNeeded()
            // Remove 'deleted class' if it exists
            if ($('#subscribers-table').hasClass('deleted')) { $('#subscribers-table').removeClass('deleted'); }
        }
    }

})(jQuery);

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 Robert Fotino.
 */

var ui = {
    /**
     * setCode(code);
     * Overwrites the contents of the code window.
     */
    setCode: function(code) { },
    /**
     * getCode();
     * Returns the contents of the code window.
     */
    getCode: function() { },
    /**
     * showCode();
     * Pops out the code window.
     */
    showCode: function() { },
    /**
     * hideCode();
     * Hides the code window.
     */
    hideCode: function() { },
    /**
     * scrollConsole();
     * Scrolls down to the bottom of the console.
     */
    scrollConsole: function() { },
    /**
     * writeConsole(line, color = 'black');
     * Writes the given text to the console window, optionally with the
     * given color.
     */
    writeConsole: function(line, color) { },
    /**
     * clearConsole();
     * Clears all text from the console window.
     */
    clearConsole: function() { },
    /**
     * showConsole();
     * Pops out the console window.
     */
    showConsole: function() { },
    /**
     * hideConsole();
     * Hides the console window.
     */
    hideConsole: function() { }
};

// Wrap local variables in a function so that we hide implementation
// details and don't pollute the global scope.
(function () {
    var codeWindow, consoleWindow, mainWindow,
        codeHidden = true, consoleHidden = true,
        codePosition, consolePosition,
        codeMirror, consoleContent;

    ui.setCode = function(code) {
        codeMirror.getDoc().setValue(code);
    };
    ui.getCode = function() {
        return codeMirror.getDoc().getValue();
    };
    ui.showCode = function() {
        codeHidden = false;
        codeWindow.removeClass('hidden');
        codeWindow.css('width', codePosition);
        consoleWindow.css('left', codePosition);
        consoleWindow.css('width', $(window).width() - codePosition);
        $('#code-popout-btn').text('<');
    };
    ui.hideCode = function() {
        codeHidden = true;
        codeWindow.addClass('hidden');
        codeWindow.css('width', '');
        consoleWindow.css('left', 0);
        consoleWindow.css('width', $(window).width());
        $('#code-popout-btn').text('>');
    };
    ui.scrollConsole = function() {
        consoleContent.scrollTop(consoleContent[0].scrollHeight);
    };
    ui.writeConsole = function(line, level) {
        if (undefined === level) {
            level = 'log';
        }
        var scrollBottom =
            consoleContent.scrollTop() + consoleContent[0].offsetHeight;
        var shouldScroll = scrollBottom === consoleContent[0].scrollHeight;
        switch (level) {
        case 'warn':
            consoleContent.append('Warning: ');
            break;
        case 'error':
            consoleContent.append('Error: ');
            ui.showConsole();
            shouldScroll = true;
            break;
        }
        consoleContent.append($('
').text(line + "\n").html());
        if (shouldScroll) {
            ui.scrollConsole();
        }
    };
    ui.clearConsole = function() {
        consoleContent.html('');
    };
    ui.showConsole = function() {
        consoleHidden = false;
        consoleWindow.removeClass('hidden');
        consoleWindow.css('height', $(window).height() - consolePosition);
        $('#console-popout-btn').text('v');
    };
    ui.hideConsole = function() {
        consoleHidden = true;
        consoleWindow.addClass('hidden');
        consoleWindow.css('height', '');
        $('#console-popout-btn').text('^');
    };

    $(document).ready(function() {
        codeWindow = $('#code-window');
        consoleWindow = $('#console-window');
        mainWindow = $('#main-window');
        consoleContent = $('#console');

        // Show/hide code and console windows when clicking their popout buttons
        $('#code-popout-btn').on('click', function(e) {
            e.preventDefault();
            if (codeHidden) {
                ui.showCode();
            } else {
                ui.hideCode();
            }
        });
        $('#console-popout-btn').on('click', function(e) {
            e.preventDefault();
            if (consoleHidden) {
                ui.showConsole();
            } else {
                ui.hideConsole();
            }
        });

        // Start repositioning code and console windows on mousedown on
        // their resize bars
        var codeDragging = false;
        var consoleDragging = false;
        $('#code-dragbar').on('mousedown', function(e) {
            if (!codeHidden) {
                codeDragging = true;
                codeWindow.addClass('notransition');
                consoleWindow.addClass('notransition');
            }
        });
        $('#console-dragbar').on('mousedown', function(e) {
            if (!consoleHidden) {
                consoleDragging = true;
                consoleWindow.addClass('notransition');
            }
        });

        // Reposition the code and console windows when dragging their resize bars
        codePosition = Math.round($(window).width() * 0.5);
        consolePosition = Math.round($(window).height() * 0.55);
        $(document).on('mouseup', function(e) {
            if (codeDragging) {
                codeDragging = false;
                codeWindow.removeClass('notransition');
                consoleWindow.removeClass('notransition');
            }
            if (consoleDragging) {
                consoleDragging = false;
                consoleWindow.removeClass('notransition');
            }
        });
        $(document).on('mousemove', function(e) {
            e.preventDefault();
            if (codeDragging) {
                codePosition = e.pageX;
                ui.showCode();
            }
            if (consoleDragging) {
                consolePosition = e.pageY;
                ui.showConsole();
            }
        });

        // Resize canvas, code window, and console window with the browser
        var windowWidth = $(window).width();
        var windowHeight = $(window).height();
        var resizeCanvas = function() {
            mainWindow.css('width', windowWidth);
            mainWindow.css('height', windowHeight - $('#menubar').height());
        }
        resizeCanvas();
        $(window).resize(function() {
            codePosition = (codePosition / windowWidth) * $(window).width();
            consolePosition = (consolePosition / windowHeight) * $(window).height();
            windowWidth = $(window).width();
            windowHeight = $(window).height();

            codeWindow.addClass('notransition');
            consoleWindow.addClass('notransition');

            resizeCanvas();

            if (codeHidden) {
                ui.hideCode();
            } else {
                ui.showCode();
            }

            if (consoleHidden) {
                ui.hideConsole();
            } else {
                ui.showConsole();
            }

            codeWindow[0].offsetHeight; // Flush cached CSS changes
            codeWindow.removeClass('notransition');
            consoleWindow.removeClass('notransition');
        });

        // Set up CodeMirror in the coding window
        var codeConfig = {
            mode: 'javascript',
            theme: 'elegant',
            lineNumbers: true,
            styleActiveLine: true,
            matchBrackets: true
        };
        codeMirror = CodeMirror(function(elem) {
            var textarea = document.getElementById('code');
            textarea.parentNode.replaceChild(elem, textarea);
            elem.id = 'code';
        }, codeConfig);
    });
})();
<commit_msg>Removes console lines after maximum is reached.<commit_after>/**
 * Copyright (c) 2015 Robert Fotino.
 */

var ui = {
    /**
     * setCode(code);
     * Overwrites the contents of the code window.
     */
    setCode: function(code) { },
    /**
     * getCode();
     * Returns the contents of the code window.
     */
    getCode: function() { },
    /**
     * showCode();
     * Pops out the code window.
     */
    showCode: function() { },
    /**
     * hideCode();
     * Hides the code window.
     */
    hideCode: function() { },
    /**
     * scrollConsole();
     * Scrolls down to the bottom of the console.
     */
    scrollConsole: function() { },
    /**
     * writeConsole(line, color = 'black');
     * Writes the given text to the console window, optionally with the
     * given color.
     */
    writeConsole: function(line, color) { },
    /**
     * clearConsole();
     * Clears all text from the console window.
     */
    clearConsole: function() { },
    /**
     * showConsole();
     * Pops out the console window.
     */
    showConsole: function() { },
    /**
     * hideConsole();
     * Hides the console window.
     */
    hideConsole: function() { }
};

// Wrap local variables in a function so that we hide implementation
// details and don't pollute the global scope.
(function () {
    var codeWindow, consoleWindow, mainWindow,
        codeHidden = true, consoleHidden = true,
        codePosition, consolePosition,
        codeMirror, consoleContent;

    ui.setCode = function(code) {
        codeMirror.getDoc().setValue(code);
    };
    ui.getCode = function() {
        return codeMirror.getDoc().getValue();
    };
    ui.showCode = function() {
        codeHidden = false;
        codeWindow.removeClass('hidden');
        codeWindow.css('width', codePosition);
        consoleWindow.css('left', codePosition);
        consoleWindow.css('width', $(window).width() - codePosition);
        $('#code-popout-btn').text('<');
    };
    ui.hideCode = function() {
        codeHidden = true;
        codeWindow.addClass('hidden');
        codeWindow.css('width', '');
        consoleWindow.css('left', 0);
        consoleWindow.css('width', $(window).width());
        $('#code-popout-btn').text('>');
    };
    ui.scrollConsole = function() {
        consoleContent.scrollTop(consoleContent[0].scrollHeight);
    };
    ui.writeConsole = function(line, level) {
        if (undefined === level) {
            level = 'log';
        }
        var maxLines = 300;
        var scrollBottom =
            consoleContent.scrollTop() + consoleContent[0].offsetHeight;
        var shouldScroll = scrollBottom === consoleContent[0].scrollHeight;
        var newContent = '
';
        switch (level) {
        case 'warn':
            newContent += 'Warning: ';
            break;
        case 'error':
            newContent += 'Error: ';
            ui.showConsole();
            shouldScroll = true;
            break;
        }
        newContent += $('
').text(line + "\n").html();
        newContent += '
';
        consoleContent.append(newContent);
        while (maxLines < consoleContent.children().length) {
            consoleContent.children().first().remove();
        }
        if (shouldScroll) {
            ui.scrollConsole();
        }
    };
    ui.clearConsole = function() {
        consoleContent.html('');
    };
    ui.showConsole = function() {
        consoleHidden = false;
        consoleWindow.removeClass('hidden');
        consoleWindow.css('height', $(window).height() - consolePosition);
        $('#console-popout-btn').text('v');
    };
    ui.hideConsole = function() {
        consoleHidden = true;
        consoleWindow.addClass('hidden');
        consoleWindow.css('height', '');
        $('#console-popout-btn').text('^');
    };

    $(document).ready(function() {
        codeWindow = $('#code-window');
        consoleWindow = $('#console-window');
        mainWindow = $('#main-window');
        consoleContent = $('#console');

        // Show/hide code and console windows when clicking their popout buttons
        $('#code-popout-btn').on('click', function(e) {
            e.preventDefault();
            if (codeHidden) {
                ui.showCode();
            } else {
                ui.hideCode();
            }
        });
        $('#console-popout-btn').on('click', function(e) {
            e.preventDefault();
            if (consoleHidden) {
                ui.showConsole();
            } else {
                ui.hideConsole();
            }
        });

        // Start repositioning code and console windows on mousedown on
        // their resize bars
        var codeDragging = false;
        var consoleDragging = false;
        $('#code-dragbar').on('mousedown', function(e) {
            if (!codeHidden) {
                codeDragging = true;
                codeWindow.addClass('notransition');
                consoleWindow.addClass('notransition');
            }
        });
        $('#console-dragbar').on('mousedown', function(e) {
            if (!consoleHidden) {
                consoleDragging = true;
                consoleWindow.addClass('notransition');
            }
        });

        // Reposition the code and console windows when dragging their resize bars
        codePosition = Math.round($(window).width() * 0.5);
        consolePosition = Math.round($(window).height() * 0.55);
        $(document).on('mouseup', function(e) {
            if (codeDragging) {
                codeDragging = false;
                codeWindow.removeClass('notransition');
                consoleWindow.removeClass('notransition');
            }
            if (consoleDragging) {
                consoleDragging = false;
                consoleWindow.removeClass('notransition');
            }
        });
        $(document).on('mousemove', function(e) {
            e.preventDefault();
            if (codeDragging) {
                codePosition = e.pageX;
                ui.showCode();
            }
            if (consoleDragging) {
                consolePosition = e.pageY;
                ui.showConsole();
            }
        });

        // Resize canvas, code window, and console window with the browser
        var windowWidth = $(window).width();
        var windowHeight = $(window).height();
        var resizeCanvas = function() {
            mainWindow.css('width', windowWidth);
            mainWindow.css('height', windowHeight - $('#menubar').height());
        }
        resizeCanvas();
        $(window).resize(function() {
            codePosition = (codePosition / windowWidth) * $(window).width();
            consolePosition = (consolePosition / windowHeight) * $(window).height();
            windowWidth = $(window).width();
            windowHeight = $(window).height();

            codeWindow.addClass('notransition');
            consoleWindow.addClass('notransition');

            resizeCanvas();

            if (codeHidden) {
                ui.hideCode();
            } else {
                ui.showCode();
            }

            if (consoleHidden) {
                ui.hideConsole();
            } else {
                ui.showConsole();
            }

            codeWindow[0].offsetHeight; // Flush cached CSS changes
            codeWindow.removeClass('notransition');
            consoleWindow.removeClass('notransition');
        });

        // Set up CodeMirror in the coding window
        var codeConfig = {
            mode: 'javascript',
            theme: 'elegant',
            lineNumbers: true,
            styleActiveLine: true,
            matchBrackets: true
        };
        codeMirror = CodeMirror(function(elem) {
            var textarea = document.getElementById('code');
            textarea.parentNode.replaceChild(elem, textarea);
            elem.id = 'code';
        }, codeConfig);
    });
})();
<|endoftext|>