Commit b8d15e83 authored by techird's avatar techird

Merge tag 'v1.0.1'

fix issue #2, #6 of png export
parents c905a391 e221b6e4
.idea
*.sublime-project
*.sublime-workspace
node_modules/
\ No newline at end of file
[submodule "kity"]
path = kity
url = https://github.com/kitygraph/kity.git
{
"indent_with_tabs": false,
"preserve_newlines": true,
"max_preserve_newlines": 4,
"space_in_paren": true,
"jslint_happy": true,
"brace_style": "collapse",
"keep_array_indentation": false,
"keep_function_indentation": false,
"eval_code": false,
"unescape_strings": false,
"break_chained_methods": false,
"e4x": false,
"wrap_line_length": 0
}
\ No newline at end of file
{
"undef" : true,
"unused" : false,
"strict" : false,
"curly" : false,
"newcap" : true,
"trailing" : true,
"white": false,
"quotmark": false,
"predef" : [
"module",
"require",
"console",
"kity",
"KityMinder",
"KM",
"Minder",
"MinderNode",
"MinderEvent",
"Command",
"KITYMINDER_CONFIG",
"keymap",
"Utils",
"utils",
"$",
"KM",
"keymap",
"baidu"
]
}
\ No newline at end of file
/*-----------------------------------------------------
* livereload Default Setting
*-----------------------------------------------------*/
'use strict';
var path = require( 'path' );
var lrSnippet = require( 'grunt-contrib-livereload/lib/utils' ).livereloadSnippet;
/*-----------------------------------------------------
* Module Setting
*-----------------------------------------------------*/
module.exports = function ( grunt ) {
var banner = '/*!\n' +
' * ====================================================\n' +
' * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
' * GitHub: <%= pkg.repository.url %> \n' +
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n' +
' * ====================================================\n' +
' */\n\n',
buildPath = 'dev/import.php';
var getPath = function ( readFile ) {
var sources = require( "fs" ).readFileSync( readFile );
sources = /Array\(([^)]+)\)/.exec( sources );
sources = sources[ 1 ].replace( /\/\/.*\n/g, '\n' ).replace( /'|"|\n|\t|\s/g, '' );
sources = sources.split( "," );
sources.forEach( function ( filepath, index ) {
sources[ index ] = filepath;
} );
return sources;
};
// Project configuration.
grunt.initConfig( {
// Metadata.
pkg: grunt.file.readJSON( 'package.json' ),
concat: {
js: {
options: {
banner: banner + '(function(kity, window) {\n\n',
footer: '\n\n})(kity, window)',
process: function ( src, filepath ) {
return src + "\n";
}
},
src: getPath( buildPath ),
dest: 'dist/kityminder.all.js'
}
},
uglify: {
minimize: {
options: {
banner: banner
},
files: {
'dist/kityminder.all.min.js': 'dist/kityminder.all.js'
}
}
},
/* Start [Task liverload] ------------------------------------*/
livereload: {
port: 35729 // Default livereload listening port.
},
connect: {
livereload: {
options: {
hostname: '*',
port: 9001,
base: '.',
middleware: function ( connect, options, middlewares ) {
return [
lrSnippet,
connect.static( options.base.toString() ),
connect.directory( options.base.toString() )
];
}
}
}
},
regarde: {
js: {
files: 'src/**/*.js',
tasks: [ 'default', 'livereload' ]
}
}
/* End [Task liverload] ------------------------------------*/
} );
// These plugins provide necessary tasks.
/* [Build plugin & task ] ------------------------------------*/
grunt.loadNpmTasks( 'grunt-contrib-concat' );
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
// Build task(s).
grunt.registerTask( 'default', [ 'concat:js', 'uglify:minimize' ] );
/* [liverload plugin & task ] ------------------------------------*/
grunt.loadNpmTasks( 'grunt-regarde' );
grunt.loadNpmTasks( 'grunt-contrib-connect' );
grunt.loadNpmTasks( 'grunt-contrib-livereload' );
grunt.registerTask( 'live', [ 'livereload-start', 'connect', 'regarde' ] );
};
\ No newline at end of file
The MIT License (MIT)
Copyright (c) 2013 kitygraph
Copyright (c) 2013 KityMinder
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
......
kityminder
Kity Minder
==========
在线脑图编辑器
## 简介
KityMinder 是百度 FEX 团队的 f-cube 小组(原UEditor小组)的又一力作。作为一款在线的脑图编辑工具,它有着很多Native编辑工具的交互体验。KM与UE有着一样的宗旨,就是注重最终用户的使用体验。同时,它充分发挥了Web云存储的优势,可以直接将编辑中的脑图同步到云端。此外,借由独创的 “云盘分享”功能,用户可以一键将当前编辑的脑图直接生成在线链接共享给其他用户,实现无缝沟通。
![Alt text](summary.jpg "简介图")
KM是基于SVG技术实现,使用JavaScript+html实现。支持绝大多数的主流浏览器。
支持列表如下
1. Chrome
2. Firefox
3. Safari
4. IE9+
## 项目链接
[直接使用链接](http://fex-team.github.io/kityminder/dist/)
## 联系我们
邮件: kity@baidu.com
讨论群: 374918234
<?php
$dependency = Array(
'src/core/kityminder.js'
,'src/core/utils.js'
,'src/core/command.js'
,'src/core/node.js'
,'src/core/module.js'
,'src/core/event.js'
,'src/core/minder.js'
,'src/core/minder.data.js'
,'src/core/minder.event.js'
,'src/core/minder.module.js'
,'src/core/minder.command.js'
,'src/core/minder.node.js'
,'src/core/keymap.js'
,'src/core/minder.lang.js'
,'src/core/minder.defaultoptions.js'
,'src/module/geometry.js'
,'src/module/history.js'
,'src/module/icon.js'
,'src/module/layout.js'
,'src/module/layout.default.js'
,'src/module/layout.bottom.js'
,'src/core/minder.select.js'
,'src/module/hand.js'
,'src/module/dragtree.js'
,'src/module/dropfile.js'
,'src/module/keyboard.js'
,'src/module/select.js'
,'src/module/history.js'
,'src/module/editor.js'
,'src/module/editor.range.js'
,'src/module/editor.receiver.js'
,'src/module/editor.selection.js'
,'src/module/basestyle.js'
,'src/module/font.js'
,'src/module/zoom.js'
,'src/ui/jquery-ui-1.10.4.custom.min.js'
,'src/ui/widget.js'
,'src/ui/button.js'
,'src/ui/toolbar.js'
,'src/ui/menu.js'
,'src/ui/dropmenu.js'
,'src/ui/splitbutton.js'
,'src/ui/colorsplitbutton.js'
,'src/ui/popup.js'
,'src/ui/scale.js'
,'src/ui/colorpicker.js'
,'src/ui/combobox.js'
,'src/ui/buttoncombobox.js'
,'src/ui/modal.js'
,'src/ui/tooltip.js'
,'src/ui/tab.js'
,'src/ui/separator.js'
,'src/ui/scale.js'
,'src/adapter/utils.js'
,'src/adapter/adapter.js'
,'src/adapter/button.js'
,'src/adapter/combobox.js'
,'src/adapter/saveto.js'
,'src/adapter/view.js'
,'src/adapter/tooltips.js'
,'src/adapter/layout.js'
,'src/adapter/node.js'
,'src/adapter/contextmenu.js'
,'src/adapter/dialog.js'
,'src/protocal/plain.js'
,'src/protocal/json.js'
,'src/protocal/png.js'
,'src/protocal/svg.js'
);
$content = "";
header('Content-Type: text/javascript; charset=utf-8');
foreach ($dependency as $index => $dep) {
if( $_GET['join'] != null || $argv[1] == 'join') {
echo file_get_contents("../$dep")."\n\n";
} else {
echo "document.write('<script charset=utf-8 src=\"../$dep\"></script>');";
}
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../lib/jquery-2.1.0.min.js" charset="utf-8"></script>
<script src="../kity/dist/kitygraph.all.js" charset="utf-8"></script>
<script src="../dev/import.php" charset="utf-8"></script>
<script src="../kityminder.config.js" charset="utf-8"></script>
<script src="../lang/zh-cn/zh-cn.js" charset="utf-8"></script>
<script src="../lib/baidu-frontia-js-full-1.0.0.js" charset="utf-8"></script>
<script src="../social/social.js" charset="utf-8"></script>
<link href="../social/social.css" rel="stylesheet">
<link href="../themes/default/css/import.css" type="text/css" rel="stylesheet" />
<link href="../dialogs/dialogs.css" rel="stylesheet" type="text/css" />
<script>
$(function () {
// create km instance
window.km = KM.getKityMinder('kityminder');
});
</script>
</head>
<body>
<div id="kityminder" onselectstart="return false"></div>
<body>
</html>
\ No newline at end of file
.priority .icon {background:url(../dialogs/icons/iconpriority.png) 0 0}
.progress .icon{background:url(../dialogs/icons/iconprogress.png) 0 0}
.icon.p2{background-position: -20px 0}
.icon.p3{background-position: -40px 0}
.icon.p4{background-position: -60px 0}
.icon.p5{background-position: -80px 0}
\ No newline at end of file
( function () {
var utils = KM.utils;
KM.registerWidget( 'markers', {
tpl: "<ul class='icon-list priority'>" +
"<li value='1' type='priority'><span class='icon p1'></span><span><%= priority %>1</span></li>" +
"<li value='2' type='priority'><span class='icon p2'></span><span><%= priority %>2</span></li>" +
"<li value='3' type='priority'><span class='icon p3'></span><span><%= priority %>3</span></li>" +
"<li value='4' type='priority'><span class='icon p4'></span><span><%= priority %>4</span></li>" +
"<li value='5' type='priority'><span class='icon p5'></span><span><%= priority %>5</span></li>" +
"</ul>" +
"<ul class='icon-list progress'>" +
"<li value='1' type='progress'><span class='icon p1'></span><span><%= progress.notdone %></span></li>" +
"<li value='2' type='progress'><span class='icon p2'></span><span><%= progress.quarterdone %></span></li>" +
"<li value='3' type='progress'><span class='icon p3'></span><span><%= progress.halfdone %></span></li>" +
"<li value='4' type='progress'><span class='icon p4'></span><span><%= progress.threequartersdone %></span></li>" +
"<li value='5' type='progress'><span class='icon p5'></span><span><%= progress.done %></span></li>" +
"</ul>",
initContent: function ( km ) {
var lang = km.getLang( 'dialogs.markers' );
if ( lang ) {
var html = $.parseTmpl( this.tpl, lang );
}
this.root().html( html );
},
initEvent: function ( km, $w ) {
$w.on( "click", "li", function () {
var $this = $( this );
$this.siblings().removeClass( "active" );
$this.toggleClass( "active" );
var val = $this.val();
if ( !$this.hasClass( "active" ) ) {
val = null;
}
var type = $this.attr( "type" );
km.execCommand( type, val );
} );
km.on( 'interactchange', function ( e ) {
var valPri = this.queryCommandValue( "priority" );
var valPro = this.queryCommandValue( "progress" );
$w.find( "li[type='priority']" ).removeClass( "active" );
$w.find( "li[type='priority'][value='" + valPri + "']" ).addClass( "active" );
$w.find( "li[type='progress']" ).removeClass( "active" );
$w.find( "li[type='progress'][value='" + valPro + "']" ).addClass( "active" );
} );
},
buttons: {
'ok': {
exec: function ( km, $w ) {
var href = $( '#kmui-link-Jhref' ).val().replace( /^\s+|\s+$/g, '' );
if ( href ) {
km.execCommand( 'link', {
'href': href,
'target': $( "#kmui-link-Jtarget:checked" ).length ? "_blank" : '_self',
'title': $( "#kmui-link-Jtitle" ).val().replace( /^\s+|\s+$/g, '' ),
'_href': href
} );
}
}
},
'cancel': {}
},
width: 200
} )
} )();
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../lib/jquery-2.1.0.min.js" charset="utf-8"></script>
<script src="../kity/dist/kitygraph.all.min.js" charset="utf-8"></script>
<script src="../dist/kityminder.all.min.js" charset="utf-8"></script>
<script src="../kityminder.config.js" charset="utf-8"></script>
<script src="../lang/zh-cn/zh-cn.js" charset="utf-8"></script>
<script src="../lib/baidu-frontia-js-full-1.0.0.js" charset="utf-8"></script>
<script src="../social/social.js" charset="utf-8"></script>
<link href="../social/social.css" rel="stylesheet">
<link href="../themes/default/css/import.css" type="text/css" rel="stylesheet" />
<link href="../dialogs/dialogs.css" rel="stylesheet" type="text/css" />
<script>
$(function () {
// create km instance
window.km = KM.getKityMinder('kityminder');
});
</script>
</head>
<body>
<div id="kityminder" onselectstart="return false"></div>
<body>
</html>
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
# Kity Minder 目标设定
## 第一期目标
* 架构搭建
* 自动布局
* 双击节点文字编辑
* 节点之间的连线(子节点向父节点)
* 导入和导出(JSON格式)
* 基本键盘导航:基于位置的选择导航;Tab插入子级;Enter插入同级
* 上述功能的撤销操作
## 第二期目标
* 自由布局
* 拖动修改子级
* 子节点展开/收起
* 思路连接线
* 外观模板支持
## 第三期目标
* 协同操作
* 云存储
* 应用推广
# Kity Minder 整体设计
## `namespace` KityMinder
暴露的命名空间,所有公开类都会放在该命名空间下。还会暴露一个简写的命名空间:KM。
## `abstract` Command
表示一条在 KityMinder 上执行的命令,以class的方式定义,命令必须依附于模块,不允许单独存在。
## 命令定义结构:
```js
var MyCommand = kity.createClass({
base: Command,
execute: function(Minder minder [,args...]){},
revert: function(Minder minder){},
// 基类缺省实现:
queryState: function(Minder minder){},
queryValue: function(Minder minder){},
// 基类实现:
setContentChanged: function( bool ),
isContentChanged: function() {},
setSelectionChanged: function( bool ) {},
isSelectionChanged: function() {}
}
```
### `method` execute(Minder minder [,args...] )
定义command执行时的一些操作,不可缺省
### `method` revert(Minder minder)
定义revert操作,可缺省,如果没有则为不可revert
### `method` queryState(Minder minder)
todo:用于返回当前命令的state,分为
* -1:不可执行
* 0:可执行
* 1:已执行
可缺省,默认返回0
### `method` queryValue(Minder minder)
todo:用于返回当前命令的状态相关值,(例如:进度条的进度百分比值等)
可缺省
### `method` isContentChanged()
返回命令是否对内容产生影响(true/false)
缺省为 true
### `method` isContentChanged()
返回命令是否对选区产生影响(true/false)
缺省为 false
## Module
Module定义一个模块,表示控制脑图中一个功能的模块(布局、渲染、输入文字、图标叠加等)
### 模块定义
下面代码简单展示了模块的定义方式
```js
KityMinder.registerModule("ModuleName", function() {
// 此处可以进行命令的定义、设置模块常量、工具函数等
return {
// 模块可能使用到的配置项,提供一个默认值
"defaultOpitons": {
},
// Minder 实例化的时候会调用 init 方法,this 指向正在实例化的 Minder 对象
// options 是 Minder 对象最终的配置(经过配置文件和用户设定改写)
"init": function( options ){
},
// 注册模块需要使用到的命令
"commands": {
"mycommand": CommandClass
},
// 模块需要关注的事件处理函数
// 处理函数中 this 指向事件发生的 Minder 对象
// e 参数为 MinderEvent 对象
"events": {
"click": function(e){
},
"keydown keyup": function(e){
}
},
// Minder 被卸载的时候会调用 destroy 方法,模块自行回收自己的资源(事件由 Minder 自动回收)
// destroy 方法中的 this 指向 Minder 实例
"destroy": function() {
},
// Minder 被重设是会调用 reset 方法,模块自行
// reset 方法中的 this 指向 Minder 实例
"reset" : function() {
}
}
});
```
## MinderNode
MinderNode 是 Kity Minder 需要展示和控制的树的一个节点。节点上提供了*树遍历**数据存取*的功能。并且提供对节点对应的渲染容器(Kity.Group)的访问
节点上提供公开字段,任何模块可以读取和修改,这些字段会提供给 KityMinder 作为渲染的依据。
公开的字段和存放的数据都会在导出、保存现场的时候被保留。
MinderTreeNode 维护的树关系和数据只是作为一个脑图的结构和数据,不具有任何渲染和交互的能力。
### 树遍历
通过 6 个接口来进行树的访问和修改操作
`node.getParent()` 返回当前节点的父节点
`node.getChildren()` 返回当前节点的子节点
`node.getIndex()` 返回当前节点在父节点中的位置,如果没有父节点,返回 -1
`node.insertChild( node, index )` 插入一个子节点到当前节点上,插入的位置为 index
`node.removeChild( node | index )` 移除一个子节点或指定位置的子节点
`node.getChild( index )` 获得指定位置的子节点
### 数据存取
`node.getData(name)` 获得指定字段的数据
`node.setData(name, value)` 设定指定字段的数据
### 公开字段
`node.setData( "x", value )` 设置节点的 x 坐标
`node.setData( "y", value )` 设置节点的 y 坐标
`node.getData( "x", value )` 获取节点的 x 坐标
`node.getData( "y", value )` 获取节点的 y 坐标
`node.setData( "text", value )` 设置节点的文本
`node.getData( "text", value )` 获取节点的文本
### 渲染容器
`node.getRenderContainer()` 返回当前节点的渲染容器
## Minder
脑图使用类
### `static method` registerModule( name, module )
注册一个模块
### 构造函数
`constructor` KityMinder(id, option)
创建脑图画布。KityMinder 实例化的时候,会从模块池中取出模块,并且实例化这些模块,然后加载。
`id` 实例的 id
`option` 其他选项(当前没有)
### 公开接口
`.getRoot() : MinderNode`
获取脑图根节点
`.execCommand( name [, params...] ) : this`
执行指定的命令。该方法执行的时候,会实例化指定类型的命令,并且把命令参数传给命令执行
`.queryCommandState( name )`
查询命令的当前状态
`.queryCommandValue( name )`
查询命令的当前结果
`.update(MinderNode node) : this`
更新指定节点及其子树的呈现,如果不指定节点,则更新跟节点的呈现(整棵树)
`.export() : object`
以导出节点以及所有子树的数据(data上所有的字段会被导出)
`.import(object data) : this`
导入节点数据,会节点以及所有子树结构以及子树数据
`.getSelectedNodes() : MinderNode[]`
返回选中的节点列表
`.select(MinderNode[] nodes | MinderNode node) : this`
添加一个或多个节点到节点选择列表中
`.selectSingle(Minder node) : this`
唯一选中指定节点
`.toggleSelect(MinderNode[] nodes | MinderNode node)`
切换一个或多个节点的选中状态
`.clearSelect(MinderNode[] nodes | MinderNode node) : this`
从节点选择列表中移除一个或多个节点,如果不传节点,全部取消选择
### 事件机制
#### 事件分类
KityMinder 的事件分为:
* 交互事件: `click`, `dblclick`, `mousedown`, `mousemove`, `mouseup`, `keydown`, `keyup`, `keypress`, `touchstart`, `touchend`, `touchmove`
* Command 事件: `beforecommand`, `precommand`, `aftercommand`
* 交互事件:`selectionchange`, `contentchange`, `interactchange`
* 模块事件:模块自行触发与上述不同名的事件
#### 事件接口
`.on(event, callback)` 侦听指定事件
`.once(event, callback)` 侦听指定事件一次,当 callback 被调用之后,后面再发生该事件不再被调用
`.off(event, callback)` 取消对事件的侦听
`.fire(event, params)` 触发指定的事件,params 是自定义的 JSON 数据,会合并到事件对象
#### 回调函数接口
回调函数接收唯一的参数 e
对于交互事件,e 是原生 event 对象的一个拓展;对于需要坐标的事件,用 e.getPosition() 可以获得在 Kity Paper 上的坐标值
对 command 事件:
* `e.commandName` 获取执行的命令的类型
* `e.commandArgs` 获取命令执行的参数列表
对 import 事件:
* `e.getImportData()` 获取导入的数据
对 selectionchange 事件:
* `e.currentSelection` 获取当前选择的节点列表
* `e.additionNodes` 添加到选择节点列表的那部分节点
* `e.removalNodes` 从选择节点列表移除的那部分节点
#### 事件触发时机
`command` 事件只在顶级 command 执行的时候触发(Command 里调用 Command 不触发)
`contentchange` 事件在顶级 command 之后会查询是否发生了内容的变化,如果发生了变化,则会触发;
`selectionchange` 事件在顶级 command 之后会查询是否发生了选区的变化,如果发生了变化,则会触发
`interactchange` 事件会在所有的鼠标、键盘、触摸操作后发生,并且会进行稀释;command 可以手动触发该事件,此时不会被稀释
# 导入导出功能设计
## 名词
* 本地格式
指一种公开的脑图编码格式,如 XMind、FreeMind、MinderManager、PDF等。下文代码中,local 表示本地格式字符串或二进制流(Blob)。
* Json格式
指 KityMinder 自身使用的 JS 内存对象,是带数据的树结构。数据结构如下:
```js
// A <MinderNode> is:
{
"data" : {...},
"children" : [<MinderNode>, <MinderNode>, ...]
}
```
下文代码中,json 表示 json 格式字符串。
* 编码
把 Json 格式转换为一种本地格式的过程
* 解码
把一种本地格式解析回 Json 格式的过程
* 协议
协议包含名称(作为标识)、编码方法(encode)、解码方法(decode)、识别判断(recognize)。解码方法是可选项,因为对于某些协议可以只支持导出而不需支持导入(如 PDF )。识别判断也是可选的,识别判断用于快速判断一个字符串或 Blob 是否改协议的本地数据,这个方法用于自动识别未知格式的协议。如果不提供这个方法,那么将不能把未知格式识别为该协议的格式,所以建议提供。
## 协议注册
使用 `KityMinder` 上的静态方法 `registerProtocal()` 来注册协议。
```js
KityMinder.registerProtocal( "xmind", function() {
return {
encode: function( json ) {
// return local;
},
decode: function( local ) {
// return json;
},
recognize: function( local ) {
// return bool;
}
}
});
```
## 协议使用
使用 `KityMinder` 上的静态方法 `findProtocal()` 来获取协议。
```js
var pXMind = KityMinder.findProtocal( "xmind" );
if (pXMind && pXMind.encode) {
local = pXMind.encode( json );
}
```
## 协议枚举
使用 `KityMinder` 上的静态方法 `getSupportedProtocals()` 来获取支持的协议列表。
```js
var supported = KityMinder.getSupportedProtocals();
// supported == [ 'xmind', 'txt', 'pdf', ... ]
```
## 导入导出接口
导入导出接口名称与原来架构的保持一致,只是参数有所调整。
### 导入
```js
minder.importData( local [, protocalName] );
```
导入数据需要提供读取到的本地数据,如果指明协议,则直接用指明的协议来解析;否则尝试去识别本地数据的协议格式。
### 导出
```js
var exported = minder.exportData( [protocalName] );
```
使用指定的协议来导出数据,如果不指定,则导出成 Json 格式。
Subproject commit 26f9836718affd92c95196be698b14b1c6da4a95
( function () {
function getKMBasePath( docUrl, confUrl ) {
return getBasePath( docUrl || self.document.URL || self.location.href, confUrl || getConfigFilePath() );
}
function getConfigFilePath() {
var configPath = document.getElementsByTagName( 'script' );
return configPath[ configPath.length - 1 ].src;
}
function getBasePath( docUrl, confUrl ) {
var basePath = confUrl;
if ( /^(\/|\\\\)/.test( confUrl ) ) {
basePath = /^.+?\w(\/|\\\\)/.exec( docUrl )[ 0 ] + confUrl.replace( /^(\/|\\\\)/, '' );
} else if ( !/^[a-z]+:/i.test( confUrl ) ) {
docUrl = docUrl.split( "#" )[ 0 ].split( "?" )[ 0 ].replace( /[^\\\/]+$/, '' );
basePath = docUrl + "" + confUrl;
}
return optimizationPath( basePath );
}
function optimizationPath( path ) {
var protocol = /^[a-z]+:\/\//.exec( path )[ 0 ],
tmp = null,
res = [];
path = path.replace( protocol, "" ).split( "?" )[ 0 ].split( "#" )[ 0 ];
path = path.replace( /\\/g, '/' ).split( /\// );
path[ path.length - 1 ] = "";
while ( path.length ) {
if ( ( tmp = path.shift() ) === ".." ) {
res.pop();
} else if ( tmp !== "." ) {
res.push( tmp );
}
}
return protocol + res.join( "/" );
}
window.KITYMINDER_CONFIG = {
'KITYMINDER_HOME_URL': getKMBasePath(),
//定义工具栏
toolbars: [
'hand zoom-in zoom-out | undo redo | bold italic | fontfamily fontsize forecolor | saveto | markers | node | switchlayout'
]
//设置主题
//,defaultlayoutstyle : 'default' //设置默认的主题
//,layoutstyle : [] //添加有那些主图
//回退相关选项
//,maxUndoCount:20 //最大可回退的次数,默认20
//语言默认是zh-cn
//,lang:'zh-cn'
//设置km整体的z-index大小
//,zIndex : 1000
};
} )()
\ No newline at end of file
KityMinder.LANG[ 'zh-cn' ] = {
'maintopic': '中心主题',
'topic': '分支主题',
'tooltips': {
'undo': '撤销',
'redo': '重做',
'bold': '加粗',
'italic': '斜体',
'forecolor': '字体颜色',
'fontfamily': '字体',
'fontsize': '字号',
'layoutstyle': '主题',
'node': '节点操作',
'saveto': '导出',
'hand': '允许拖拽',
'zoom-in': '放大',
'zoom-out': '缩小',
'markers': '添加标签',
'switchlayout': '切换主题'
},
'popupcolor': {
'clearColor': '清空颜色',
'standardColor': '标准颜色',
'themeColor': '主题颜色'
},
'dialogs': {
'markers': {
'static': {
'lang_input_text': '文本内容:',
'lang_input_url': '链接地址:',
'lang_input_title': '标题:',
'lang_input_target': '是否在新窗口打开:'
},
'priority': '优先级',
'progress': {
'notdone': "未完成",
'quarterdone': '完成1/4',
'halfdone': '完成1/2',
'threequartersdone': '完成3/4',
'done': '已完成'
}
}
},
'node': {
'appendsiblingnode': '插入同级节点',
'appendchildnode': '插入子节点',
'removenode': '删除节点'
}
};
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
{
"name": "kityminder",
"title": "kityminder",
"description": "Kity Minder",
"version": "1.0.0",
"homepage": "https://github.com/fex-team/kityminder",
"author": {
"name": "f-cube @ FEX",
"url": "http://fex.baidu.com"
},
"repository": {
"type": "git",
"url": "https://github.com/fex-team/kityminder.git"
},
"keywords": [
"kityminder",
"kity",
"minder",
"svg",
"graphic",
"javascript"
],
"bugs": {
"url": "https://github.com/fex-team/kityminder/issues"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/fex-team/kityminder/blob/dev/LICENSE"
}
],
"dependencies": {},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-uglify": "~0.2.6",
"grunt-regarde": "latest",
"grunt-contrib-connect": "latest",
"grunt-contrib-livereload": "latest"
}
}
\ No newline at end of file
#social {
position: absolute;
right: 10px;
top: 10px;
line-height: 20px;
text-align: right;
overflow: hidden;
}
#social button {
font-family: Arial, "Heiti SC", "Microsoft Yahei";
outline: none;
display: inline-block;
padding: 0 15px;
height: 35px;
font-size: 13px;
line-height: 35px;
text-align: center;
border-radius: 5px;
color: #ffffff;
text-decoration: none;
border: none;
margin-left: 5px;
cursor: pointer;
background: #0099f2;
/* Old browsers */
/* IE9 SVG, needs conditional override of 'filter' to 'none' */
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwOTlmMiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNDA5NmVlIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwNzZkZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=);
background: -moz-linear-gradient(top, #0099f2 0%, #4096ee 0%, #0076dd 100%);
/* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #0099f2), color-stop(0%, #4096ee), color-stop(100%, #0076dd));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #0099f2 0%, #4096ee 0%, #0076dd 100%);
/* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #0099f2 0%, #4096ee 0%, #0076dd 100%);
/* Opera 11.10+ */
background: -ms-linear-gradient(top, #0099f2 0%, #4096ee 0%, #0076dd 100%);
/* IE10+ */
background: linear-gradient(to bottom, #0099f2 0%, #4096ee 0%, #0076dd 100%);
/* W3C */
}
#social button:hover {
background: #009fff;
}
#social button[disabled] {
background: #AAA;
}
#social button.baidu-cloud {
padding-left: 35px;
position: relative;
}
#social button.baidu-cloud:before {
content: ' ';
display: block;
width: 24px;
height: 24px;
background: url(../themes/default/images/baiducloud.png);
position: absolute;
left: 7px;
top: 5px;
}
#social button.share {
padding-left: 35px;
position: relative;
}
#social button.share:before {
content: ' ';
display: block;
width: 24px;
height: 24px;
background: url(../themes/default/images/share.png) no-repeat;
position: absolute;
left: 7px;
top: 5px;
}
#social button img {
position: relative;
top: 3px;
border-radius: 2px;
margin-right: 7px;
}
#social button.user-file {
padding-right: 28px;
position: relative;
}
#social button.user-file:after {
content: ' ';
display: block;
position: absolute;
right: 10px;
top: 15px;
width: 0;
height: 0;
border: solid;
border-width: 4px 5px;
border-color: #FFFFFF transparent transparent transparent;
}
.user-file-menu {
margin-top: 20px;
margin-left: 1px;
}
This diff is collapsed.
#social {
position: absolute;
right: 10px;
top: 10px;
line-height: 20px;
text-align: right;
overflow: hidden;
button {
font-family: Arial, "Heiti SC", "Microsoft Yahei";
outline: none;
display: inline-block;
padding: 0 15px;
height: 35px;
font-size: 13px;
line-height: 35px;
text-align: center;
border-radius: 5px;
color: #ffffff;
text-decoration: none;
border: none;
margin-left: 5px;
cursor: pointer;background: #0099f2; /* Old browsers */
/* IE9 SVG, needs conditional override of 'filter' to 'none' */
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwOTlmMiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNDA5NmVlIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwNzZkZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=);
background: -moz-linear-gradient(top, #0099f2 0%, #4096ee 0%, #0076dd 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#0099f2), color-stop(0%,#4096ee), color-stop(100%,#0076dd)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #0099f2 0%,#4096ee 0%,#0076dd 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #0099f2 0%,#4096ee 0%,#0076dd 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #0099f2 0%,#4096ee 0%,#0076dd 100%); /* IE10+ */
background: linear-gradient(to bottom, #0099f2 0%,#4096ee 0%,#0076dd 100%); /* W3C */
&:hover {
background: #009fff;
}
&[disabled] {
background: #AAA;
}
&.baidu-cloud {
padding-left: 35px;
position: relative;
&:before {
content: ' ';
display: block;
width: 24px;
height: 24px;
background: url(../themes/default/images/baiducloud.png);
position: absolute;
left: 7px;
top: 5px;
}
}
&.share {
padding-left: 35px;
position: relative;
&:before {
content: ' ';
display: block;
width: 24px;
height: 24px;
background: url(../themes/default/images/share.png) no-repeat;
position: absolute;
left: 7px;
top: 5px;
}
}
img {
position: relative;
top: 3px;
border-radius: 2px;
margin-right: 7px;
}
&.user-file {
padding-right: 28px;
position: relative;
&:after {
content: ' ';
display: block;
position: absolute;
right: 10px;
top: 15px;
width: 0;
height: 0;
border: solid;
border-width: 4px 5px;
border-color: #FFFFFF transparent transparent transparent;
}
}
}
}
.user-file-menu {
margin-top: 20px;
margin-left: 1px;
}
\ No newline at end of file
{
"undef" : true,
"unused" : false,
"strict" : false,
"curly" : false,
"newcap" : true,
"trailing" : true,
"white": false,
"quotmark": false,
"predef" : [
"require",
"console",
"kity",
"KityMinder",
"KM",
"Minder",
"MinderNode",
"MinderEvent",
"Command",
"KITYMINDER_CONFIG",
"Utils",
"utils",
"describe",
"it",
"beforeEach",
"expect"
]
}
\ No newline at end of file
//beforeEach( function () {
// // customMatcher 例子
// this.addMatchers( {
// //用的时候这么用:
// //expect('***').customMatchers(true);
// //expect('***').not.customMatchers(true);
//// customMatchers: function ( expected ) {
//// return expected === true;
//// },
//
// } );
//} );
This diff is collapsed.
describe("command", function () {
it('',function(){
})
});
\ No newline at end of file
describe("minder.command", function () {
it('',function(){
})
});
\ No newline at end of file
describe("node", function () {
var root = new KM.MinderNode('root');
var first = new KM.MinderNode('first');
first.appendChild(new KM.MinderNode('first.first'));
first.setData({
'layout':{
x:1,
y:1
}
})
var second = new KM.MinderNode('second');
second.appendChild(new KM.MinderNode('second.first'));
root.appendChild(first);
root.appendChild(second);
describe('clone',function(){
var _tmp = root.clone();
it('克隆的root有2级孩子',function(){
expect(_tmp.getFirstChild()).not.toBeNull();
expect(_tmp.getFirstChild().getFirstChild()).not.toBeNull();
expect(_tmp.getFirstChild().getData('text')).toBe('first');
expect(_tmp.getFirstChild().getFirstChild().getData('text')).toBe('first.first');
});
it('检测属性的深度复制',function(){
first.getData('layout').x = 2;
expect(_tmp.getFirstChild().getData('layout').x).toBe(1);
})
});
describe('contains',function(){
it('root contain first',function(){
expect(root.contains(first)).toBeTruthy();
});
it('root contain first.first',function(){
expect(root.contains(first.getFirstChild())).toBeTruthy();
});
it('first not contain second',function(){
expect(root.contains(first.getFirstChild())).toBeTruthy();
});
it('first contain first',function(){
expect(first.contains(first)).toBeTruthy();
});
});
describe('getCommonAncestor',function(){
it('first second commonAncestor is root',function(){
expect(first.getCommonAncestor(second)).toBe(root);
});
it('root first.first commonAncestor is root',function(){
expect(first.getFirstChild().getCommonAncestor(root)).toBe(root);
});
it('second.first first.first commonAncestor is root',function(){
var a = first.getFirstChild(),b=second.getFirstChild();
expect(a.getCommonAncestor(b)).toBe(root);
});
});
describe('setData',function(){
it('name and value both exist',function(){
root.setData('test',1);
expect(root.getData('test')).toBe(1);
});
it('name only exist clear property',function(){
root.setData('test');
expect(root.getData('test')).toBeUndefined();
});
it('name is object',function(){
root.setData({
'test':1
});
expect(root.getData('test')).toBe(1);
});
it('name and value both empty',function(){
root.setData('test',1);
root.setData('test1',2);
root.setData();
expect(root.getData('test')).toBeUndefined();
expect(root.getData('test1')).toBeUndefined();
});
it('layout:{x:1,y:1}',function(){
root.setData({
'layout':{
x:1,
y:1
}
});
expect(root.getData('layout').x).toBe(1);
});
});
});
\ No newline at end of file
describe("utils", function () {
describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});
});
\ No newline at end of file
/**
* Created by dongyancen on 13-12-27.
*/
///import core/kityminder;
///import core/utils;
///import core/command;
///import core/node;
///import core/module;
///import core/event;
///import core/minder;
///import core/minder.data;
///import core/minder.event;
///import core/minder.module;
///import core/minder.command;
///import core/minder.node;
///import core/minder.select;
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: dongyancen
* Date: 14-1-15
* Time: 下午6:50
*/
Header('Location:../spec/tools/list.php');
?>
\ No newline at end of file
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-12-10
* Time: 下午7:24
* To change this template use File | Settings | File Templates.
/**
* Created by dongyancen on 13-12-30.
*/
describe("connect", function () {
it("KityMinder 已定义", function () {
expect(KityMinder).toBeDefined();
});
});
describe( "protocal/plain", function () {
var json, local, protocal;
beforeEach( function () {
protocal = KM.findProtocal( 'plain' );
} );
it( '协议存在', function () {
expect( protocal ).toBeDefined();
} );
it( '正确 encode', function () {
json = {
data: {
text: 'root',
anyway: 'omg'
},
children: [ {
data: {
text: 'l1c1'
}
}, {
data: {
text: 'l1c2'
},
children: [ {
data: {
text: 'l2c1'
}
}, {
data: {
text: 'l2c2'
}
} ]
}, {
data: {
text: 'l1c3'
}
} ]
};
local = protocal.encode( json );
expect( local ).toBe(
'root\n' +
'\tl1c1\n' +
'\tl1c2\n' +
'\t\tl2c1\n' +
'\t\tl2c2\n' +
'\tl1c3\n'
);
} );
} );
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-10
* Time: 上午1:20
* To change this template use File | Settings | File Templates.
*/
require_once 'config.php';
class Kiss
{
public $projroot ;
public $name;
public $srcPath;
public $testPath;
public $empty = false;
public $case_id;
function __construct( $name = '' )
{
$this->projroot = Config::$projroot;
$this->srcPath = Config::$projroot.Config::$src_PATH;
$this->testPath = Config::$projroot.Config::$test_PATH;
$this->name = $name;
$this->case_id = 'id_case_' . join( '_' , explode( '.' , $name ) );
}
public function print_js( $cov)
{
if($cov){
$basePath = '../../spec/coverage';
}
else{
$basePath = '../../src';
}
// print "<script src='../../dist/dev.php'></script>";
print "<script type='text/javascript' src='./js/UserAction.js' ></script>\n";
/* load case and case dependents*/
$ps = explode( '/' , $this->name );
/*load helper*/
foreach(Config::$helperFiles as $f){
if ( file_exists( $this->testPath . $f ) ) {
print '<script type="text/javascript" src="' . $this->testPath . $f . '"></script>' . "\n";
}
}
//先引用kity
print "<script src='../../kity/dist/kitygraph.all.js'></script>\n";
//分成两部分:一部分默认加载(可配置),一部分针对文件加载(例如在文件头部有注释标注依赖文件,根据依赖文件动态加载)
// core里面的文件全部加载,module加载用例对应的src文件,最后加载与用例同名的原文件
$importurl = "{$this->testPath}tools/import.php?f=$this->name";
if ( $cov ) $importurl .= '^&cov=true';
print "<script type='text/javascript' src='".$importurl."' ></script>\n";
//引用测试文件
print '<script type="text/javascript" src="' .$this->testPath.$this->name. '.js"></script>' . "\n";
}
public function match( $matcher )
{
if ( $matcher == '*' )
return true;
$len = strlen( $matcher );
/**
* 处理多选分支,有一个成功则成功,filter后面参数使用|切割
* @var unknown_type
*/
$ms = explode( ',' , $matcher );
if ( sizeof( $ms ) > 1 ) {
foreach ( $ms as $matcher1 ) {
if ( $this->match( $matcher1 ) )
return true;
}
return false;
}
/**
* 处理反向选择分支
*/
if ( substr( $matcher , 0 , 1 ) == '!' ) {
$m = substr( $matcher , 1 );
if ( substr( $this->name , 0 , strlen( $m ) ) == $m )
return false;
return true;
}
if ( $len > strlen( $this->name ) ) {
return false;
}
return substr( $this->name , 0 , $len ) == $matcher;
}
public static function listcase( $matcher = "*" ,$cov)
{
require_once 'fileHelper.php';
/*get files both in src path and test path*/
$caselist = getSameFile(Config::$projroot.Config::$src_PATH , Config::$projroot.Config::$test_PATH , '' );
sort($caselist,SORT_STRING);
foreach ( $caselist as $caseitem ) {
/*remove '.js' */
$name = substr( $caseitem , 0 , -3 );
$c = new Kiss( $name );
if ( $c->empty )
continue;
if ( $c->match( $matcher ) ) {
$newName = explode( '\\.' , $name );
$newName = $newName[ count( $newName ) - 1 ];
if($cov){
$covMsg = "&cov=true";
}else{
$covMsg="";
}
print( "<a href=\"run.php?case=$name".$covMsg."\" id=\"$c->case_id\" target=\"_blank\" title=\"$name\" onclick=\"run('$name');return false;\">". $newName . "</a>" );
}
}
}
public static function listSrcOnly( $print = true )
{
$srcpath = Config::$projroot.Config::$src_PATH;
$testpath = Config::$projroot.Config::$test_PATH;
require_once 'fileHelper.php';
$caselist = getSameFile( $srcpath , $testpath , '' );
$srclist = getSrcOnlyFile( $srcpath , $testpath , '' );
$srcList = array();
foreach ( $srclist as $case ) {
if ( in_array( $case , $caselist ) )
continue;
$name = str_replace( '/' , '.' , substr( $case , 0 , -3 ) );
$tag = "<a title=\"$name\">" . ( strlen( $name ) > 20 ? substr( $name , 6 )
: $name ) . "</a>";
array_push( $srcList , $tag );
if ( $print )
echo $tag;
}
return $srcList;
}
}
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-10
* Time: 上午1:50
* To change this template use File | Settings | File Templates.
*/
class Config
{
public static $projroot = "../../";
//相对于projroot的路径
public static $src_PATH = "src/" ;
public static $test_PATH = "spec/";
public static $helperFiles = array( "SpecHelper.js" );
}
\ No newline at end of file
* {
margin: 0;
padding: 0;
}
html {
border: 0;
height: 100%;
}
body {
font: 12px/1.5 Lucida Grande, Helvetica, Arial, sans-serif;
background: #F3F1F1;
color: #41464D;
}
body,#container {
width: 100%;
height: 100%;
}
.clear { /* generic container (i.e. div) for floating buttons */
overflow: hidden;
width: 100%;
}
a {
text-decoration: none;
overflow: hidden;
}
#title {
top: 0;
left: 0;
width: 100%;
padding: 5px 0;
background: #aaa;
background: #41464D;
color: #F3F1F1;
height: 30px;
}
a:link,a:visited {
color: #528CE0;
}
a:hover,a:active {
color: #41464D !important;
cursor: pointer !important;
}
#title h1 {
height: 30px;
font: 25px/1.1 Arial, sans-serif;
font-weight: bolder;
float: left;
margin: 1px 0 2px 20px;
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.4);
}
h3 {
font-size: 14px;
padding: 3px 5px 1px;
}
.control {
background: #d5ded7;
width: 99%;
}
.testlist {
max-height: 200px;
overflow-y: scroll;
border-style: double;
}
.testlist a {
display: block;
width: 150px;
color: #657528;
background: #d5dea7;
border: 1px solid #c8dc7b;
margin: 5px 0 0 5px;
text-indent: 5px;
line-height: 24px;
font-size: 14px;
float: left;
}
a.button {
background: transparent url('bg_button_a.gif') no-repeat scroll top
right;
color: #444;
display: block;
float: left;
font: normal 12px arial, sans-serif;
height: 24px;
margin-right: 6px;
padding-right: 18px; /* sliding doors padding */
text-decoration: none;
}
a.button span {
background: transparent url('bg_button_span.gif') no-repeat;
display: block;
line-height: 14px;
padding: 5px 0 5px 18px;
}
a.button:active {
background-position: bottom right;
color: #000;
outline: none; /* hide dotted outline in Firefox */
}
a.button:active span {
background-position: bottom left;
padding: 6px 0 4px 18px; /* push text down 1px */
}
.testlist a:link {
}
.testlist a:visited {
}
.testlist a:hover {
background: #c8dc7b;
}
.testlist a.jsframe_jsspec {
background: #DDDDDD
}
.testlist a.running_case {
color: yellow;
}
.testlist a.fail_case {
color: red;
}
.testlist a.pass_case {
color: green;
}
.runningarea {
height: 60%;
}
.runningmaindiv {
height: 99%;
}
.runningframe {
height: 99.99%;
width: 99.99%;
}
.runningstatus {
clear: both;
height: 10%;
border: solid
}
.reportarea {
padding: 10px;
border: 10px blue;
max-height: 200px;
overflow-y: scroll;
}
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午5:31
* To change this template use File | Settings | File Templates.
*///获取两个目录下的相同路径的文件数
function getSameFile($src, $test, $path=''){
$result = array();
$as = listFile($src.$path);
$ts = listFile($test.$path);
$ds = array_intersect($as, $ts);
foreach($ds as $item){
$si = $src.$path.$item;
$ti = $test.$path.$item;
if(is_dir($si) && is_dir($ti)){
$result = array_merge($result, getSameFile($src, $test, $path.$item.'/'));
}else if(is_file($si) && is_file($ti)){
if(substr($si, -3) == '.js')
array_push($result, $path.$item);
}
}
return $result;
}
//获取只在src中存在的文件,防止遗漏用例
function getSrcOnlyFile($src, $test, $path=''){
$result = array();
$as = listFile($src.$path);
$ts = listFile($test.$path);
foreach($as as $item){
$si = $src.$path.$item;
$ti = $test.$path.$item;
if(is_dir($si) && is_dir($ti)){
$result = array_merge($result, getSrcOnlyFile($src, $test, $path.$item.'/'));
}else if(is_file($si) && !is_file($ti)){
if(substr($si, -3) == '.js')
array_push($result,$path.$item);
}
else{
// print("error : $si");
}
}
return $result;
}
function listFile($dir){
$as = array();
if($dh = opendir($dir)){
while(($file = readdir($dh))!==false){
if(substr(basename($file), 0, 1) == '.')
continue;
array_push($as, basename($file));
}
closedir($dh);
}
return $as;
}
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-12-10
* Time: 上午1:48
* To change this template use File | Settings | File Templates.
*/
header('Content-Type: text/javascript');
$import = 'import.js';
function custom_strEmpty($s){
$str = strlen(trim($s));
if(empty($str)){
return true;
}
return false;
}
function importSrc(){
require_once 'config.php';
global $import;
if(file_exists(Config::$projroot.Config::$test_PATH.$import)){
$cnt = file_get_contents(Config::$projroot.Config::$test_PATH.$import);
}
if($cnt == ''){
if(Config::$DEBUG)
print "fail read file : ".Config::$test_PATH.$import;
return '';
}
$is = array();
$flag_ownSrc = 1;
$caseName = $_GET[ 'f' ];
$this_src = Config::$projroot.Config::$src_PATH.$caseName.".js";
//正则匹配,提取所有(///import xxx;)中的xxx
preg_match_all('/\/\/\/import\s+([^;]+);?/ies', $cnt, $is, PREG_PATTERN_ORDER);
foreach($is[1] as $i) {
if(strcasecmp($i,$caseName)==0){
$flag_ownSrc = 0;
}
$path = $i . '.js';
$srcFile = Config::$projroot . Config::$src_PATH . $path;
if (file_exists($srcFile)) {
echo "document.write('<script charset=utf-8 src=\"$srcFile\"></script>');";
}
}
if(file_exists($this_src)){
$file=fopen($this_src,"r");
while(!feof($file))
{
$statment = fgets($file);
if(custom_strEmpty($statment)){
continue ;
}else if(preg_match('/\/\/\/import\s+([^;]+);?/ies', $statment,$r)){
echo "document.write('<script charset=utf-8 src=\"".Config::$projroot . Config::$src_PATH.$r[1].".js\"></script>');";
}else{
break;
}
}
fclose($file);
}
//加载与用例同名的原文件,并避免重复加载
if($flag_ownSrc){
echo "document.write('<script charset=utf-8 src=\"".$this_src."\"></script>');";
}
}
importSrc();
\ No newline at end of file
This diff is collapsed.
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-17
* Time: 上午2:24
* To change this template use File | Settings | File Templates.
*/
/**
* rewrite jasmine function to support batchrun
*/
(function() {
if (!jasmine)
return;
var s = jasmine.Queue.prototype.start
// ,n = jasmine.Queue.prototype.next_
,f = jasmine.Runner.prototype.finishCallback;
function _f(self,args /* failures, total */) {
//todo 写到调用HtmlReporter后
/*another way to apply:
*
* var reporterView = self.env.reporter.subReporters_[0].getReporterView();
*totalSpecCount,completeSpecCount,failedCount,passedCount
*reporterView.views.specs[0].detail
* */
var totalSpecCount = 0,failedCount = 0,passedCount = 0;
var tmpSpec = null;
for(var i=0;i<self.suites_.length;i++){
for(var j=0;j<self.suites_[i].specs_.length;j++){
totalSpecCount++;
tmpSpec = self.suites_[i].specs_[j].results_.items_;
for(var k=0;k<tmpSpec.length;k++){
if(tmpSpec[k].passed_){
passedCount++;
}else{
failedCount++;
}
}
}
}
//display failed Suite
// $('li.fail ol').toggle();
if (parent && parent.brtest) {
parent.brtest.customTrigger('done', [ new Date().getTime(), {
failed : failedCount,
passed : passedCount,
detail : self.suites_,
total : totalSpecCount
//todo jscoverage
}, window._$jscoverage || null ]);
}
}
jasmine.Runner.prototype.finishCallback = function(){
f.apply(this, arguments);
_f(this,arguments);
};
jasmine.Queue.prototype.start =function(){
//todo
/* wait for import.php return */
// var h = setInterval(function() {
// if (window && window['baidu']) {
// clearInterval(h);
s.apply(this, arguments);
// }
// }, 20);
};
// function _n(self,args /* failures, total */) {
/* // do not delete the following lines:
// the last Queue in the file has done ,there is no more Suite or Queue
if(self.index == self.blocks.length || (this.abort && !this.ensured[self.index])){
}
*/
// }
// jasmine.Queue.prototype.next_ = function() {
// _n(this,arguments);
// n.apply(this, arguments);
// };
})();
\ No newline at end of file
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午6:52
* To change this template use File | Settings | File Templates.
*/
/**
* 为批量运行提供入口,参数携带batchrun=true
*/
function run(kiss,runnext) {
window.document.title = kiss;
var wb = window.brtest = window.brtest || {};
triggerEvent.call(wb);
wb.timeout = wb.timeout || 60000;
wb.breakOnError = /breakonerror=true/gi.test(location.search)
|| document.getElementById('id_control_breakonerror').checked;
wb.runnext = /batchrun=true/gi.test(location.search) || runnext
|| document.getElementById('id_control_runnext').checked;
wb.kiss = kiss;
var cid = 'id_case_' + kiss.split('.').join('_');
/* 只有参数有showsrconly的时候才显示div */
if (/showsrconly=true/gi.test(location.search)) {
var div = document.getElementById('id_showSrcOnly');
div.style.display = 'block';
}
/* id中由于嵌入用例名称,可能存在导致通过id直接$无法正确获取元素的情况 */
wb.kissnode = document.getElementById(cid);
wb.kisses = wb.kisses || {};
// 把没有用例的情况加入到报告中
if (!wb.kisslost) {
var as = document.getElementById('id_showSrcOnly').getElementsByTagName('a');
for (var i = 0; i < as.length; i++) {
wb.kisses[this.title] = '0;0;_;0;0';
}
wb.kisslost = true;
}
wb.kisscov = wb.kisscov || {};
var wbkiss = wb.kisses[wb.kiss] = wb.kisses[wb.kiss] || '';
/**
* 超时处理
*/
var toh = setTimeout(function () {
if (!window.brtest.breakOnError)
wb.customTrigger('done', [ new Date().getTime(), {
failed: 1,
passed: 1,
detail: null,
total: 0
}, frames[0].$_jscoverage, 'timeout' ]);
}, wb.timeout);
/**
* 为当前用例绑定一个一次性事件
*/
wb.customOne('done', function (time, result, covinfo) {
clearTimeout(toh);
var wb = window.brtest, errornum = result.failed, allnum = result.total;
wb.kissend = new Date().getTime();
//todo jscoverage
// if ( covinfo !== null )// 如果支持覆盖率
// {
// wb.kisscov[wb.kiss] = covinfo;
// }
removeClass(wb.kissnode, 'running_case');
wb.kisses[wb.kiss] = errornum + ';' + allnum + ';_;' + wb.kissstart + ';' + wb.kissend;
//todo log
// var args = kiss + ': 失败/所有:' + errornum + '/' + allnum + ',耗时:' + (wb.kissend - wb.kissstart);
// var html = upath + '../br/log.php?loginfo=' + args;
// html += '&detail='+result.detail;
// if ( errornum > 0 )
// html += '&fail=true';
if (errornum > 0) {
addClass(wb.kissnode, 'fail_case');
} else
addClass(wb.kissnode, 'pass_case');
if (wb.runnext && (!wb.breakOnError || parseInt(wb.kisses[wb.kiss].split(',')[0]) == 0)) {
var nextA = wb.kissnode.nextSibling;
if (nextA.tagName.toLowerCase() == 'a') {
if (wb.kisses[nextA.title] === undefined) {
run(nextA.title, wb.runnext);
}
// html += "&next=" + nextA.title;
} else {
//
// /* ending 提交数据到后台 */
// html += '&next=@_@end';
wb.kisses['config'] = location.search.substring(1);
var url = 'report.php';
//todo jscoverage
// covcalc();
// /**
// * 启动时间,结束时间,校验点失败数,校验点总数
// */
$.ajax({
url: url,
type: 'post',
data: wb.kisses,
success: function (msg) {
/* 展示报告区 */
// $('#id_reportarea').show().html(msg);
},
error: function (xhr, msg) {
alert('fail' + msg);
}
});
}
}
//todo log
// te.log( html );
});
/**
* 初始化执行区并通过嵌入iframe启动用例执行
*/
var url = 'run.php?case=' + kiss + '&time=' + new Date().getTime() + "&"
+ location.search.substring(1);
var fdiv = 'id_div_frame_' + kiss.split('.').join('_');
var fid = 'id_frame_' + kiss.split('.').join('_');
addClass(wb.kissnode, 'running_case');
/* 隐藏报告区 */
// $( 'div#id_reportarea' ).empty().hide();
/* 展示执行区 */
var runningarea = document.getElementById('id_runningarea');
empty(runningarea).style.display = 'block';
var iframe = document.createElement('iframe');
iframe.id = fid;
iframe.src = url;
addClass(iframe, "runningframe");
runningarea.appendChild(iframe);
wb.kissstart = new Date().getTime();
};
// 需要根据一次批量执行整合所有文件的覆盖率情况
//function covcalc() {
// function covmerge(cc, covinfo) {
// for (var key in covinfo) {//key :每个文件
// for (var idx in covinfo[key]) {
// if (idx != 'source') {
//
// cc[key] = cc[key] || [];
// cc[key][idx] = (cc[key][idx] || 0) + covinfo[key][idx];
// }
// }
// }
// return cc;
// }
//
// var cc = {};
// var brkisses = window.brtest.kisses;
// for (var key in window.brtest.kisscov) {
// covmerge(cc, window.brtest.kisscov[key]);//key:每个用例
//// brkisses[kiss]= brkisses[kiss] + ',' + key;
// }
// var file;
// var files = [];
// var filter = '';
// var ls = location.search.split('&');
// for (var i = 0; i < ls.length; i++) {
// if (ls[i].indexOf('filter') != -1) {
// filter = ls[i].split('=')[1];
// }
//
// }
// for (file in cc) {
// if (!cc.hasOwnProperty(file)) {
// continue;
// }
// if (file.indexOf(filter) != -1)
// files.push(file);
// }
// files.sort();
// for (var f = 0; f < files.length; f++) {
// file = files[f];
// var lineNumber;
// var num_statements = 0;
// var num_executed = 0;
// var missing = [];
// var fileCC = cc[file];
// var length = fileCC.length;
// var currentConditionalEnd = 0;
// var conditionals = null;
//
// if (fileCC.conditionals) {
// conditionals = fileCC.conditionals;
// }
// var recordCovForBrowser = null;//
// for (lineNumber = 0; lineNumber < length; lineNumber++) {
// var n = fileCC[lineNumber];
//
// if (lineNumber === currentConditionalEnd) {
// currentConditionalEnd = 0;
// } else if (currentConditionalEnd === 0 && conditionals
// && conditionals[lineNumber]) {
// currentConditionalEnd = conditionals[lineNumber];
// }
//
// if (currentConditionalEnd !== 0) {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '2') : (recordCovForBrowser += ',2');
//
// continue;
// }
//
// if (n === undefined || n === null) {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '2') : (recordCovForBrowser += ',2');
// continue;
// }
//
// if (n === 0) {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '0') : (recordCovForBrowser += ',0');
// missing.push(lineNumber);
// } else {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '1') : (recordCovForBrowser += ',1');
// num_executed++;
// }
// num_statements++;
// }
//
// var percentage = (num_statements === 0 ? 0 : ( 100 * num_executed / num_statements ).toFixed(1));
// var kiss = file.replace('.js', '');
// // 统计所有用例的覆盖率信息和测试结果
//
// if (brkisses[kiss] == undefined)
// brkisses[kiss] = '0;0;_;0;0';
// var info = brkisses[kiss].split(';_;');// 覆盖率的处理在最后环节加入到用例的测试结果中
// brkisses[kiss] = info[0] + ';' + percentage + ';' + info[1] + ';' + recordCovForBrowser;
// }
//}
window.onload =
function () {
if (location.href.search("[?&,]batchrun=true") > 0
|| document.getElementById('id_control_runnext').checked) {
run(document.getElementById('id_testlist').getElementsByTagName('a')[0].getAttribute('title'), true);
}
};
\ No newline at end of file
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午5:34
* To change this template use File | Settings | File Templates.
*/
function hasClass(obj, cls) {
return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(ele,cls) {
if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}
function removeClass(obj, cls) {
var clsArray= cls.split( " ");
for(var i=0;i<clsArray.length;i++){
if (hasClass(obj, clsArray[i])) {
var reg = new RegExp('(\\s|^)' + clsArray[i] + '(\\s|$)');
obj.className = obj.className.replace(reg, ' ');
}
}
}
function empty(obj){
var childs = obj.childNodes;
if(childs.length==0)return obj;
for(var i=0;i<childs.length;i++){
obj.removeChild(childs[i]);
}
return obj
}
function slideToggle(obj){
//todo 先写个大意,待完成
if(obj.style.display=='none'){
}else{
obj.style.display='block';
}
}
var triggerEvent = function () {
this.listeners = [];
this.customOne = function (type, listener) {
this.listeners[type] = listener;
for (var i = 0, l = this.listeners.length; i < l; i++) {
if (this.listeners[i] === this.listeners[type]) {
this.listeners.splice(i, 1);
i--;
}
}
},
this.customTrigger = function (type,arguments) {
if(this.listeners[type]){
return this.listeners[type].apply(this, arguments);
}
return false;
}
};
@echo off
jscoverage.exe --encoding=UTF-8 ../../../src ../../coverage
\ No newline at end of file
Copyright (c) 2008-2011 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed.
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
#HTMLReporter a { text-decoration: none; }
#HTMLReporter a:hover { text-decoration: underline; }
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
#HTMLReporter .version { color: #aaaaaa; }
#HTMLReporter .banner { margin-top: 14px; }
#HTMLReporter .duration { color: #aaaaaa; float: right; }
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
#HTMLReporter .passingAlert { background-color: #a6b779; }
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
#HTMLReporter .failingAlert { background-color: #cf867e; }
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
#HTMLReporter .results { margin-top: 14px; }
#HTMLReporter #details { display: none; }
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter.showDetails .summary { display: none; }
#HTMLReporter.showDetails #details { display: block; }
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter .summary { margin-top: 14px; }
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
#HTMLReporter .description + .suite { margin-top: 0; }
#HTMLReporter .suite { margin-top: 14px; }
#HTMLReporter .suite a { color: #333333; }
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
#HTMLReporter .resultMessage span.result { display: block; }
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
#TrivialReporter .runner.running { background-color: yellow; }
#TrivialReporter .options { text-align: right; font-size: .8em; }
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
#TrivialReporter .suite .suite { margin: 5px; }
#TrivialReporter .suite.passed { background-color: #dfd; }
#TrivialReporter .suite.failed { background-color: #fdd; }
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
#TrivialReporter .spec.skipped { background-color: #bbb; }
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
#TrivialReporter .passed { background-color: #cfc; display: none; }
#TrivialReporter .failed { background-color: #fbb; }
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
#TrivialReporter .resultMessage .mismatch { color: black; }
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
This diff is collapsed.
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午5:17
* To change this template use File | Settings | File Templates.
*/
header( "Content-type: text/html; charset=utf-8" );
$filter = array_key_exists( 'filter' , $_GET ) ? $_GET[ 'filter' ] : '*';
$quirk = array_key_exists( 'quirk' , $_GET );
$cov = array_key_exists( 'cov' , $_GET );
if ( !$quirk ) {
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<?php } ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Kity Test Index Page</title>
<script type="text/javascript" src="js/tools.js"></script>
<!-- <script type="text/javascript" src="js/UserAction.js"></script>-->
<script type="text/javascript" src="js/run.js"></script>
<link media="screen" href="css/test.css" type="text/css"
rel="stylesheet"/>
</head>
<body>
<div id="title">
<h1>Kity Test Index Page</h1>
</div>
<!--浏览器插件,可调用windows api-->
<div>
<object id="plugin" type="application/x-plugintest" width="1" height="1">
<param name="onload" value="pluginLoaded"/>
</object>
</div>
<div id="id_control" class="control">
<input id="id_control_runnext" type="checkbox"/>自动下一个
<input id="id_control_breakonerror" type="checkbox"/>出错时终止
<input id="id_control_clearstatus" type="button" value="清除用例状态"
onclick="removeClass(document.getElementById('id_testlist'),'running_case pass_case fail_case');"/>
</div>
<div>
<a id="id_testlist_status" class="button"> <span
onclick="slideToggle(document.getElementById('id_testlist');"> 折叠用例 </span> </a>
<a id="id_srconly" class="button"><span
onclick="slideToggle(document.getElementById('id_runningarea');">折叠执行</span> </a>
</div>
<div style="clear: both"></div>
<div id="id_testlist" class="testlist">
<?php
/*分析所有源码与测试代码js文件一一对应的文件并追加到当前列表中*/
require_once "caseSource.php";
Kiss::listcase( $filter ,$cov);
?>
<div style="clear: both; overflow: hidden"></div>
</div>
<div id="id_runningarea" class="runningarea"
style="border: solid; display: none"></div>
<div id="id_reportarea" class="reportarea" style="display: none;"></div>
<div class='clear'></div>
<div id="id_showSrcOnly" class="testlist" style="display: none;">
<?php
require_once "caseSource.php";
Kiss::listSrcOnly( true );
?>
<div class="clear"></div>
</div>
</body>
</html>
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-17
* Time: 下午6:28
* To change this template use File | Settings | File Templates.
*/
error_reporting(E_ERROR|E_WARNING);
function report()
{
return;
}
report();
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-10
* Time: 上午1:17
* To change this template use File | Settings | File Templates.
*/
header( "Content-type: text/html; charset=utf-8" );
header( "Cache-Control: no-cache, max-age=10, must-revalidate" );
if ( !array_key_exists( 'quirk' , $_GET ) ) {
print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
}
;
require_once "caseSource.php";
$c = new Kiss( $_GET[ 'case' ] );
$title = $c->name;
$cov = array_key_exists( 'cov' , $_GET );
?>
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.3.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.3.0/jasmine.css">
<script type="text/javascript" src="lib/jasmine-1.3.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.3.0/jasmine-html.js"></script>
<script type="text/javascript" src="js/ext_jasmine.js"></script>
<?php $c->print_js($cov); ?>
</head>
<script type="text/javascript">
//todo
// if (parent && parent.brtest) {
// parent.$(parent.brtest).trigger('done', [ new Date().getTime(), {
// failed : args[0],
// passed : args[1],
// detail:args[2]
// }, window._$jscoverage || null ]);
// }
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
<body>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
KM.registerToolbarUI( 'bold italic redo undo',
function ( name ) {
var me = this;
var $btn = $.kmuibutton( {
icon: name,
click: function () {
me.execCommand( name );
},
title: this.getLang( 'tooltips' )[ name ] || ''
} );
this.on( 'interactchange', function () {
var state = this.queryCommandState( name );
$btn.kmui().disabled( state == -1 ).active( state == 1 );
} );
return $btn;
}
);
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment