Commit 2c60486b authored by Romain Courteaud's avatar Romain Courteaud Committed by Jérome Perrin

Migrate job gantt widget.

parent 0e39fb46
......@@ -12,3 +12,4 @@ outputJSON.json
trace*.xls
npm-debug.log
node_modules/
tmp/
......@@ -6,7 +6,7 @@ module.exports = function (grunt) {
var global_config = {
src: "dream/platform/src2/",
lib: "dream/platform/vendor/",
// tmp: "tmp",
tmp: "tmp",
dest: "dream/platform/static/"
};
......@@ -19,6 +19,7 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-curl');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-zip');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
......@@ -146,6 +147,18 @@ module.exports = function (grunt) {
relative_dest: 'lib/qunit.js',
dest: "<%= global_config.dest %>/<%= copy.qunitjs.relative_dest %>"
},
dhtmlxganttjs: {
src: "<%= global_config.lib %>/dhtmlxgantt.js",
// src: "<%= unzip.dhtmlxgantt.dest %>/codebase/dhtmlxgantt.js",
relative_dest: 'lib/dhtmlxgantt.js',
dest: "<%= global_config.dest %>/<%= copy.dhtmlxganttjs.relative_dest %>"
},
dhtmlxganttcss: {
src: "<%= global_config.lib %>/dhtmlxgantt.css",
// src: "<%= unzip.dhtmlxgantt.dest %>/codebase/dhtmlxgantt.css",
relative_dest: 'lib/dhtmlxgantt.css',
dest: "<%= global_config.dest %>/<%= copy.dhtmlxganttcss.relative_dest %>"
},
qunitcss: {
src: 'node_modules/qunitjs/qunit/qunit.css',
relative_dest: 'lib/qunit.css',
......@@ -210,6 +223,10 @@ module.exports = function (grunt) {
relative_dest: 'lib/jquery.flot.stack.js',
dest: '<%= global_config.dest %>/<%= curl.jqueryflotstack.relative_dest %>'
},
dhtmlxgantt: {
src: 'http://dhtmlx.com/x/download/regular/dhtmlxGantt.zip',
dest: '<%= global_config.tmp %>/dhtmlxGantt.zip'
},
handsontablejs: {
src: 'https://raw.githubusercontent.com/warpech/' +
'jquery-handsontable/v0.10.5/dist/jquery.handsontable.full.js',
......@@ -239,6 +256,13 @@ module.exports = function (grunt) {
}
// qunit: {
// all: ['test/index.html']
},
unzip: {
dhtmlxgantt: {
src: '<%= curl.dhtmlxgantt.dest %>',
dest: '<%= global_config.tmp %>/dhtmlxGantt/'
}
}
});
......@@ -246,7 +270,7 @@ module.exports = function (grunt) {
grunt.registerTask('default', ['all']);
grunt.registerTask('all', ['lint', 'build']);
grunt.registerTask('lint', ['jslint']);
grunt.registerTask('dep', ['curl']);
grunt.registerTask('dep', ['curl', 'unzip']);
// grunt.registerTask('test', ['qunit']);
grunt.registerTask('build', ['concat', 'copy', 'uglify', 'less']);
......
......@@ -8,7 +8,6 @@
<link rel="stylesheet" href="css/skeleton_wide.css">
<link rel="stylesheet" href="css/layout.css">
<link rel="stylesheet" href="css/jquery-ui-1.10.3.custom.min.css">
<link rel="stylesheet" type="text/css" href="lib/dhtmlxgantt/dhtmlxgantt.css">
<link rel="stylesheet" href="css/demo-new.css">
<link rel="stylesheet" href="css/font-awesome.css">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
......@@ -83,7 +82,6 @@
<div id="capacity_graphs"></div>
</div>
<div id="job_gantt" style='width:1320px; height:800px;'></div>
<div id="job_schedule_spreadsheet" style="overflow: scroll;"></div>
</div>
......@@ -103,9 +101,6 @@
<script type="text/javascript" src="lib/jquery.flot.js"></script>
<script type="text/javascript" src="lib/jquery.flot.stack.js"></script>
<!-- gantt chart -->
<script type="text/javascript" src="lib/dhtmlxgantt/dhtmlxgantt.js"></script>
<!-- nice display of dates -->
<script type="text/javascript" src="lib/moment-with-langs.min.js"></script>
......
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("dataview_connector.php");
/*! Connector class for DataView
**/
class ChartConnector extends DataViewConnector{
public function __construct($res,$type=false,$item_type=false,$data_type=false){
parent::__construct($res,$type,$item_type,$data_type);
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("base_connector.php");
/*! DataItem class for Combo component
**/
class ComboDataItem extends DataItem{
private $selected;//!< flag of selected option
function __construct($data,$config,$index){
parent::__construct($data,$config,$index);
$this->selected=false;
}
/*! mark option as selected
*/
function select(){
$this->selected=true;
}
/*! return self as XML string, starting part
*/
function to_xml_start(){
if ($this->skip) return "";
return "<option ".($this->selected?"selected='true'":"")."value='".$this->get_id()."'><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]>";
}
/*! return self as XML string, ending part
*/
function to_xml_end(){
if ($this->skip) return "";
return "</option>";
}
}
/*! Connector for the dhtmlxCombo
**/
class ComboConnector extends Connector{
private $filter; //!< filtering mask from incoming request
private $position; //!< position from incoming request
/*! constructor
Here initilization of all Masters occurs, execution timer initialized
@param res
db connection resource
@param type
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
@param item_type
name of class, which will be used for item rendering, optional, DataItem will be used by default
@param data_type
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
*/
public function __construct($res,$type=false,$item_type=false,$data_type=false){
if (!$item_type) $item_type="ComboDataItem";
parent::__construct($res,$type,$item_type,$data_type);
}
//parse GET scoope, all operations with incoming request must be done here
function parse_request(){
parent::parse_request();
if (isset($_GET["pos"])){
if (!$this->dload) //not critical, so just write a log message
LogMaster::log("Dyn loading request received, but server side was not configured to process dyn. loading. ");
else
$this->request->set_limit($_GET["pos"],$this->dload);
}
if (isset($_GET["mask"]))
$this->request->set_filter($this->config->text[0]["db_name"],$_GET["mask"]."%","LIKE");
LogMaster::log($this->request);
}
/*! renders self as xml, starting part
*/
public function xml_start(){
if ($this->request->get_start())
return "<complete add='true'>";
else
return "<complete>";
}
/*! renders self as xml, ending part
*/
public function xml_end(){
return "</complete>";
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
class ConvertService{
private $url;
private $type;
private $name;
private $inline;
public function __construct($url){
$this->url = $url;
$this->pdf();
EventMaster::attach_static("connectorInit",array($this, "handle"));
}
public function pdf($name = "data.pdf", $inline = false){
$this->type = "pdf";
$this->name = $name;
$this->inline = $inline;
}
public function excel($name = "data.xls", $inline = false){
$this->type = "excel";
$this->name = $name;
$this->inline = $inline;
}
public function handle($conn){
$conn->event->attach("beforeOutput",array($this,"convert"));
}
private function as_file($size, $name, $inline){
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$size);
if ($inline)
header('Content-Disposition: inline; filename="'.$name.'";');
else
header('Content-Disposition: attachment; filename="'.basename($name).'";');
}
public function convert($conn, $out){
$str_out = str_replace("<rows>","<rows profile='color'>", $out);
$str_out = str_replace("<head>","<head><columns>", $str_out);
$str_out = str_replace("</head>","</columns></head>", $str_out);
if ($this->type == "pdf")
header("Content-type: application/pdf");
else
header("Content-type: application/ms-excel");
$handle = curl_init($this->url);
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_HEADER, false);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_POSTFIELDS, "grid_xml=".urlencode($str_out));
$out->reset();
$out->set_type("pdf");
$out->add(curl_exec($handle));
$this->as_file(strlen((string)$out), $this->name, $this->inline);
curl_close($handle);
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("data_connector.php");
class DelayedConnector extends Connector{
protected $init_flag=false;//!< used to prevent rendering while initialization
private $data_mode=false;//!< flag to separate xml and data request modes
private $data_result=false;//<! store results of query
public function dataMode($name){
$this->data_mode = $name;
$this->data_result=array();
}
public function getDataResult(){
return $this->data_result;
}
public function render(){
if (!$this->init_flag){
$this->init_flag=true;
return "";
}
return parent::render();
}
protected function output_as_xml($res){
if ($this->data_mode){
while ($data=$this->sql->get_next($res)){
$this->data_result[]=$data[$this->data_mode];
}
}
else
return parent::output_as_xml($res);
}
protected function end_run(){
if (!$this->data_mode)
parent::end_run();
}
}
class CrossOptionsConnector extends Connector{
public $options, $link;
private $master_name, $link_name, $master_value;
public function __construct($res,$type=false,$item_type=false,$data_type=false){
$this->options = new OptionsConnector($res,$type,$item_type,$data_type);
$this->link = new DelayedConnector($res,$type,$item_type,$data_type);
EventMaster::attach_static("connectorInit",array($this, "handle"));
}
public function handle($conn){
if ($conn instanceof DelayedConnector) return;
if ($conn instanceof OptionsConnector) return;
$this->master_name = $this->link->get_config()->id["db_name"];
$this->link_name = $this->options->get_config()->id["db_name"];
$this->link->event->attach("beforeFilter",array($this, "get_only_related"));
if (isset($_GET["dhx_crosslink_".$this->link_name])){
$this->get_links($_GET["dhx_crosslink_".$this->link_name]);
die();
}
if (!$this->dload){
$conn->event->attach("beforeRender", array($this, "getOptions"));
$conn->event->attach("beforeRenderSet", array($this, "prepareConfig"));
}
$conn->event->attach("afterProcessing", array($this, "afterProcessing"));
}
public function prepareConfig($conn, $res, $config){
$config->add_field($this->link_name);
}
public function getOptions($data){
$this->link->dataMode($this->link_name);
$this->get_links($data->get_value($this->master_name));
$data->set_value($this->link_name, implode(",",$this->link->getDataResult()));
}
public function get_links($id){
$this->master_value = $id;
$this->link->render();
}
public function get_only_related($filters){
$index = $filters->index($this->master_name);
if ($index!==false){
$filters->rules[$index]["value"]=$this->master_value;
} else
$filters->add($this->master_name, $this->master_value, "=");
}
public function afterProcessing($action){
$status = $action->get_status();
$master_key = $action->get_value($this->master_name);
$link_key = $action->get_value($this->link_name);
$link_key = explode(',', $link_key);
if ($status == "inserted")
$master_key = $action->get_new_id();
switch ($status){
case "deleted":
$this->link->delete($master_key);
break;
case "updated":
//cross link options not loaded yet, so we can skip update
if (!array_key_exists($this->link_name, $action->get_data()))
break;
//else, delete old options and continue in insert section to add new values
$this->link->delete($master_key);
case "inserted":
for ($i=0; $i < sizeof($link_key); $i++)
if ($link_key[$i]!="")
$this->link->insert(array(
$this->link_name => $link_key[$i],
$this->master_name => $master_key
));
break;
}
}
}
class JSONCrossOptionsConnector extends CrossOptionsConnector{
public $options, $link;
private $master_name, $link_name, $master_value;
public function __construct($res,$type=false,$item_type=false,$data_type=false){
$this->options = new JSONOptionsConnector($res,$type,$item_type,$data_type);
$this->link = new DelayedConnector($res,$type,$item_type,$data_type);
EventMaster::attach_static("connectorInit",array($this, "handle"));
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("base_connector.php");
/*! DataItem class for DataView component
**/
class DataViewDataItem extends DataItem{
/*! return self as XML string
*/
function to_xml(){
if ($this->skip) return "";
$str="<item id='".$this->get_id()."' >";
for ($i=0; $i<sizeof($this->config->text); $i++){
$extra = $this->config->text[$i]["name"];
$str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
}
return $str."</item>";
}
}
/*! Connector class for DataView
**/
class DataViewConnector extends Connector{
/*! constructor
Here initilization of all Masters occurs, execution timer initialized
@param res
db connection resource
@param type
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
@param item_type
name of class, which will be used for item rendering, optional, DataItem will be used by default
@param data_type
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
*/
public function __construct($res,$type=false,$item_type=false,$data_type=false){
if (!$item_type) $item_type="DataViewDataItem";
if (!$data_type) $data_type="DataProcessor";
parent::__construct($res,$type,$item_type,$data_type);
}
//parse GET scoope, all operations with incoming request must be done here
function parse_request(){
parent::parse_request();
if (isset($_GET["posStart"]) && isset($_GET["count"]))
$this->request->set_limit($_GET["posStart"],$_GET["count"]);
}
/*! renders self as xml, starting part
*/
protected function xml_start(){
$attributes = "";
foreach($this->attributes as $k=>$v)
$attributes .= " ".$k."='".$v."'";
$start.= ">";
if ($this->dload){
if ($pos=$this->request->get_start())
return "<data pos='".$pos."'".$attributes.">";
else
return "<data total_count='".$this->sql->get_size($this->request)."'".$attributes.">";
}
else
return "<data".$attributes.">";
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! Implementation of DataWrapper for PostgreSQL
**/
class AdoDBDataWrapper extends DBDataWrapper{
protected $last_result;
public function query($sql){
LogMaster::log($sql);
if (is_array($sql)) {
$res = $this->connection->SelectLimit($sql['sql'], $sql['numrows'], $sql['offset']);
} else {
$res = $this->connection->Execute($sql);
}
if ($res===false) throw new Exception("ADODB operation failed\n".$this->connection->ErrorMsg());
$this->last_result = $res;
return $res;
}
public function get_next($res){
if (!$res)
$res = $this->last_result;
if ($res->EOF)
return false;
$row = $res->GetRowAssoc(false);
$res->MoveNext();
return $row;
}
protected function get_new_id(){
return $this->connection->Insert_ID();
}
public function escape($data){
return $this->connection->addq($data);
}
/*! escape field name to prevent sql reserved words conflict
@param data
unescaped data
@return
escaped data
*/
public function escape_name($data){
if ((strpos($data,"`")!==false || is_int($data)) || (strpos($data,".")!==false))
return $data;
return '`'.$data.'`';
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
$sql="SELECT ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
if ($start || $count) {
$sql=array("sql"=>$sql,'numrows'=>$count, 'offset'=>$start);
}
return $sql;
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once('db_common.php');
if (!defined('DHX_IGNORE_EMPTY_ROWS')) {
define('DHX_IGNORE_EMPTY_ROWS', true);
}
class ExcelDBDataWrapper extends DBDataWrapper {
public $emptyLimit = 10;
public function excel_data($points){
$path = $this->connection;
$excel = PHPExcel_IOFactory::createReaderForFile($path);
$excel = $excel->load($path);
$result = array();
$excelWS = $excel->getActiveSheet();
for ($i=0; $i < sizeof($points); $i++) {
$c = array();
preg_match("/^([a-zA-Z]+)(\d+)/", $points[$i], $c);
if (count($c) > 0) {
$col = PHPExcel_Cell::columnIndexFromString($c[1]) - 1;
$cell = $excelWS->getCellByColumnAndRow($col, (int)$c[2]);
$result[] = $cell->getValue();
}
}
return $result;
}
public function select($source) {
$path = $this->connection;
$excel = PHPExcel_IOFactory::createReaderForFile($path);
$excel->setReadDataOnly(false);
$excel = $excel->load($path);
$excRes = new ExcelResult();
$excelWS = $excel->getActiveSheet();
$addFields = true;
$coords = array();
if ($source->get_source() == '*') {
$coords['start_row'] = 0;
$coords['end_row'] = false;
} else {
$c = array();
preg_match("/^([a-zA-Z]+)(\d+)/", $source->get_source(), $c);
if (count($c) > 0) {
$coords['start_row'] = (int) $c[2];
} else {
$coords['start_row'] = 0;
}
$c = array();
preg_match("/:(.+)(\d+)$/U", $source->get_source(), $c);
if (count($c) > 0) {
$coords['end_row'] = (int) $c[2];
} else {
$coords['end_row'] = false;
}
}
$i = $coords['start_row'];
$end = 0;
while ((($coords['end_row'] == false)&&($end < $this->emptyLimit))||(($coords['end_row'] !== false)&&($i < $coords['end_row']))) {
$r = Array();
$emptyNum = 0;
for ($j = 0; $j < count($this->config->text); $j++) {
$col = PHPExcel_Cell::columnIndexFromString($this->config->text[$j]['name']) - 1;
$cell = $excelWS->getCellByColumnAndRow($col, $i);
if (PHPExcel_Shared_Date::isDateTime($cell)) {
$r[PHPExcel_Cell::stringFromColumnIndex($col)] = PHPExcel_Shared_Date::ExcelToPHP($cell->getValue());
} else if ($cell->getDataType() == 'f') {
$r[PHPExcel_Cell::stringFromColumnIndex($col)] = $cell->getCalculatedValue();
} else {
$r[PHPExcel_Cell::stringFromColumnIndex($col)] = $cell->getValue();
}
if ($r[PHPExcel_Cell::stringFromColumnIndex($col)] == '') {
$emptyNum++;
}
}
if ($emptyNum < count($this->config->text)) {
$r['id'] = $i;
$excRes->addRecord($r);
$end = 0;
} else {
if (DHX_IGNORE_EMPTY_ROWS == false) {
$r['id'] = $i;
$excRes->addRecord($r);
}
$end++;
}
$i++;
}
return $excRes;
}
public function query($sql) {
}
public function get_new_id() {
}
public function escape($data) {
}
public function get_next($res) {
return $res->next();
}
}
class ExcelResult {
private $rows;
private $currentRecord = 0;
// add record to output list
public function addRecord($file) {
$this->rows[] = $file;
}
// return next record
public function next() {
if ($this->currentRecord < count($this->rows)) {
$row = $this->rows[$this->currentRecord];
$this->currentRecord++;
return $row;
} else {
return false;
}
}
// sorts records under $sort array
public function sort($sort, $data) {
if (count($this->files) == 0) {
return $this;
}
// defines fields list if it's need
for ($i = 0; $i < count($sort); $i++) {
$fieldname = $sort[$i]['name'];
if (!isset($this->files[0][$fieldname])) {
if (isset($data[$fieldname])) {
$fieldname = $data[$fieldname]['db_name'];
$sort[$i]['name'] = $fieldname;
} else {
$fieldname = false;
}
}
}
// for every sorting field will sort
for ($i = 0; $i < count($sort); $i++) {
// if field, setted in sort parameter doesn't exist, continue
if ($sort[$i]['name'] == false) {
continue;
}
// sorting by current field
$flag = true;
while ($flag == true) {
$flag = false;
// checks if previous sorting fields are equal
for ($j = 0; $j < count($this->files) - 1; $j++) {
$equal = true;
for ($k = 0; $k < $i; $k++) {
if ($this->files[$j][$sort[$k]['name']] != $this->files[$j + 1][$sort[$k]['name']]) {
$equal = false;
}
}
// compares two records in list under current sorting field and sorting direction
if (((($this->files[$j][$sort[$i]['name']] > $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'ASC'))||(($this->files[$j][$sort[$i]['name']] < $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'DESC')))&&($equal == true)) {
$c = $this->files[$j];
$this->files[$j] = $this->files[$j+1];
$this->files[$j+1] = $c;
$flag = true;
}
}
}
}
return $this;
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once('db_common.php');
require_once('tree_connector.php');
/*
Most execution time is a standart functions for workin with FileSystem: is_dir(), dir(), readdir(), stat()
*/
class FileSystemDBDataWrapper extends DBDataWrapper {
// returns list of files and directories
public function select($source) {
$relation = $this->getFileName($source->get_relation());
// for tree checks relation id and forms absolute path
if ($relation == '0') {
$relation = '';
} else {
$path = $source->get_source();
}
$path = $source->get_source();
$path = $this->getFileName($path);
$path = realpath($path);
if ($path == false) {
return new FileSystemResult();
}
if (strpos(realpath($path.'/'.$relation), $path) !== 0) {
return new FileSystemResult();
}
// gets files and directories list
$res = $this->getFilesList($path, $relation);
// sorts list
$res = $res->sort($source->get_sort_by(), $this->config->data);
return $res;
}
// gets files and directory list
private function getFilesList($path, $relation) {
$fileSystemTypes = FileSystemTypes::getInstance();
LogMaster::log("Query filesystem: ".$path);
$dir = opendir($path.'/'.$relation);
$result = new FileSystemResult();
// forms fields list
for ($i = 0; $i < count($this->config->data); $i++) {
$fields[] = $this->config->data[$i]['db_name'];
}
// for every file and directory of folder
while ($file = readdir($dir)) {
// . and .. should not be in output list
if (($file == '.')||($file == '..')) {
continue;
}
$newFile = array();
// parse file name as Array('name', 'ext', 'is_dir')
$fileNameExt = $this->parseFileName($path.'/'.$relation, $file);
// checks if file should be in output array
if (!$fileSystemTypes->checkFile($file, $fileNameExt)) {
continue;
}
// takes file stat if it's need
if ((in_array('size', $fields))||(in_array('date', $fields))) {
$fileInfo = stat($path.'/'.$file);
}
// for every field forms list of fields
for ($i = 0; $i < count($fields); $i++) {
$field = $fields[$i];
switch ($field) {
case 'filename':
$newFile['filename'] = $file;
break;
case 'full_filename':
$newFile['full_filename'] = $path."/".$file;
break;
case 'size':
$newFile['size'] = $fileInfo['size'];
break;
case 'extention':
$newFile['extention'] = $fileNameExt['ext'];
break;
case 'name':
$newFile['name'] = $fileNameExt['name'];
break;
case 'date':
$newFile['date'] = date("Y-m-d H:i:s", $fileInfo['ctime']);
break;
}
$newFile['relation_id'] = $relation.'/'.$file;
$newFile['safe_name'] = $this->setFileName($relation.'/'.$file);
$newFile['is_folder'] = $fileNameExt['is_dir'];
}
// add file in output list
$result->addFile($newFile);
}
return $result;
}
// replaces '.' and '_' in id
private function setFileName($filename) {
$filename = str_replace(".", "{-dot-}", $filename);
$filename = str_replace("_", "{-nizh-}", $filename);
return $filename;
}
// replaces '{-dot-}' and '{-nizh-}' in id
private function getFileName($filename) {
$filename = str_replace("{-dot-}", ".", $filename);
$filename = str_replace("{-nizh-}", "_", $filename);
return $filename;
}
// parses file name and checks if is directory
private function parseFileName($path, $file) {
$result = Array();
if (is_dir($path.'/'.$file)) {
$result['name'] = $file;
$result['ext'] = 'dir';
$result['is_dir'] = 1;
} else {
$pos = strrpos($file, '.');
$result['name'] = substr($file, 0, $pos);
$result['ext'] = substr($file, $pos + 1);
$result['is_dir'] = 0;
}
return $result;
}
public function query($sql) {
}
public function get_new_id() {
}
public function escape($data) {
}
public function get_next($res) {
return $res->next();
}
}
class FileSystemResult {
private $files;
private $currentRecord = 0;
// add record to output list
public function addFile($file) {
$this->files[] = $file;
}
// return next record
public function next() {
if ($this->currentRecord < count($this->files)) {
$file = $this->files[$this->currentRecord];
$this->currentRecord++;
return $file;
} else {
return false;
}
}
// sorts records under $sort array
public function sort($sort, $data) {
if (count($this->files) == 0) {
return $this;
}
// defines fields list if it's need
for ($i = 0; $i < count($sort); $i++) {
$fieldname = $sort[$i]['name'];
if (!isset($this->files[0][$fieldname])) {
if (isset($data[$fieldname])) {
$fieldname = $data[$fieldname]['db_name'];
$sort[$i]['name'] = $fieldname;
} else {
$fieldname = false;
}
}
}
// for every sorting field will sort
for ($i = 0; $i < count($sort); $i++) {
// if field, setted in sort parameter doesn't exist, continue
if ($sort[$i]['name'] == false) {
continue;
}
// sorting by current field
$flag = true;
while ($flag == true) {
$flag = false;
// checks if previous sorting fields are equal
for ($j = 0; $j < count($this->files) - 1; $j++) {
$equal = true;
for ($k = 0; $k < $i; $k++) {
if ($this->files[$j][$sort[$k]['name']] != $this->files[$j + 1][$sort[$k]['name']]) {
$equal = false;
}
}
// compares two records in list under current sorting field and sorting direction
if (((($this->files[$j][$sort[$i]['name']] > $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'ASC'))||(($this->files[$j][$sort[$i]['name']] < $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'DESC')))&&($equal == true)) {
$c = $this->files[$j];
$this->files[$j] = $this->files[$j+1];
$this->files[$j+1] = $c;
$flag = true;
}
}
}
}
return $this;
}
}
// singleton class for setting file types filter
class FileSystemTypes {
static private $instance = NULL;
private $extentions = Array();
private $extentions_not = Array();
private $all = true;
private $patterns = Array();
// predefined types
private $types = Array(
'image' => Array('jpg', 'jpeg', 'gif', 'png', 'tiff', 'bmp', 'psd', 'dir'),
'document' => Array('txt', 'doc', 'docx', 'xls', 'xlsx', 'rtf', 'dir'),
'web' => Array('php', 'html', 'htm', 'js', 'css', 'dir'),
'audio' => Array('mp3', 'wav', 'ogg', 'dir'),
'video' => Array('avi', 'mpg', 'mpeg', 'mp4', 'dir'),
'only_dir' => Array('dir')
);
static function getInstance() {
if (self::$instance == NULL) {
self::$instance = new FileSystemTypes();
}
return self::$instance;
}
// sets array of extentions
public function setExtentions($ext) {
$this->all = false;
$this->extentions = $ext;
}
// adds one extention in array
public function addExtention($ext) {
$this->all = false;
$this->extentions[] = $ext;
}
// adds one extention which will not ouputed in array
public function addExtentionNot($ext) {
$this->extentions_not[] = $ext;
}
// returns array of extentions
public function getExtentions() {
return $this->extentions;
}
// adds regexp pattern
public function addPattern($pattern) {
$this->all = false;
$this->patterns[] = $pattern;
}
// clear extentions array
public function clearExtentions() {
$this->all = true;
$this->extentions = Array();
}
// clear regexp patterns array
public function clearPatterns() {
$this->all = true;
$this->patterns = Array();
}
// clear all filters
public function clearAll() {
$this->clearExtentions();
$this->clearPatterns();
}
// sets predefined type
public function setType($type, $clear = false) {
$this->all = false;
if ($type == 'all') {
$this->all = true;
return true;
}
if (isset($this->types[$type])) {
if ($clear) {
$this->clearExtentions();
}
for ($i = 0; $i < count($this->types[$type]); $i++) {
$this->extentions[] = $this->types[$type][$i];
}
return true;
} else {
return false;
}
}
// check file under setted filter
public function checkFile($filename, $fileNameExt) {
if (in_array($fileNameExt['ext'], $this->extentions_not)) {
return false;
}
if ($this->all) {
return true;
}
if ((count($this->extentions) > 0)&&(!in_array($fileNameExt['ext'], $this->extentions))) {
return false;
}
for ($i = 0; $i < count($this->patterns); $i++) {
if (!preg_match($this->patterns[$i], $filename)) {
return false;
}
}
return true;
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! MSSQL implementation of DataWrapper
**/
class MsSQLDBDataWrapper extends DBDataWrapper{
private $last_id=""; //!< ID of previously inserted record
private $insert_operation=false; //!< flag of insert operation
private $start_from=false; //!< index of start position
public function query($sql){
LogMaster::log($sql);
$res = mssql_query($sql,$this->connection);
if ($this->insert_operation){
$last = mssql_fetch_assoc($res);
$this->last_id = $last["dhx_id"];
mssql_free_result($res);
}
if ($this->start_from)
mssql_data_seek($res,$this->start_from);
return $res;
}
public function get_next($res){
return mssql_fetch_assoc($res);
}
public function get_new_id(){
/*
MSSQL doesn't support identity or auto-increment fields
Insert SQL returns new ID value, which stored in last_id field
*/
return $this->last_id;
}
protected function insert_query($data,$request){
$sql = parent::insert_query($data,$request);
$this->insert_operation=true;
return $sql.";SELECT @@IDENTITY AS dhx_id";
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
$sql="SELECT " ;
if ($count)
$sql.=" TOP ".($count+$start);
$sql.=" ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
if ($start && $count)
$this->start_from=$start;
else
$this->start_from=false;
return $sql;
}
public function escape($data){
/*
there is no special escaping method for mssql - use common logic
*/
return str_replace("'","''",$data);
}
public function begin_transaction(){
$this->query("BEGIN TRAN");
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
class MySQLiDBDataWrapper extends MySQLDBDataWrapper{
public function query($sql){
LogMaster::log($sql);
$res = $this->connection->query($sql);
if ($res===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
return $res;
}
public function get_next($res){
return $res->fetch_assoc();
}
public function get_new_id(){
return $this->connection->insert_id;
}
public function escape($data){
return $this->connection->real_escape_string($data);
}
public function tables_list() {
$result = $this->connection->query("SHOW TABLES");
if ($result===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
$tables = array();
while ($table = $result->fetch_array()) {
$tables[] = $table[0];
}
return $tables;
}
public function fields_list($table) {
$result = $this->connection->query("SHOW COLUMNS FROM `".$table."`");
if ($result===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
$fields = array();
while ($field = $result->fetch_array()) {
if ($field['Key'] == "PRI") {
$fields[$field[0]] = 1;
} else {
$fields[$field[0]] = 0;
}
}
return $fields;
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! Implementation of DataWrapper for Oracle
**/
class OracleDBDataWrapper extends DBDataWrapper{
private $last_id=""; //id of previously inserted record
private $insert_operation=false; //flag of insert operation
public function query($sql){
LogMaster::log($sql);
$stm = oci_parse($this->connection,$sql);
if ($stm===false) throw new Exception("Oracle - sql parsing failed\n".oci_error($this->connection));
$out = array(0=>null);
if($this->insert_operation){
oci_bind_by_name($stm,":outID",$out[0],999);
$this->insert_operation=false;
}
$mode = ($this->is_record_transaction() || $this->is_global_transaction())?OCI_DEFAULT:OCI_COMMIT_ON_SUCCESS;
$res=oci_execute($stm,$mode);
if ($res===false) throw new Exception("Oracle - sql execution failed\n".oci_error($this->connection));
$this->last_id=$out[0];
return $stm;
}
public function get_next($res){
$data = oci_fetch_assoc($res);
if ($data){
foreach ($data as $k => $v)
$data[strtolower($k)] = $v;
}
return $data;
}
public function get_new_id(){
/*
Oracle doesn't support identity or auto-increment fields
Insert SQL returns new ID value, which stored in last_id field
*/
return $this->last_id;
}
protected function insert_query($data,$request){
$sql = parent::insert_query($data,$request);
$this->insert_operation=true;
return $sql." returning ".$this->config->id["db_name"]." into :outID";
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
$sql="SELECT ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
if ($start || $count)
$sql="SELECT * FROM ( select /*+ FIRST_ROWS(".$count.")*/dhx_table.*, ROWNUM rnum FROM (".$sql.") dhx_table where ROWNUM <= ".($count+$start)." ) where rnum >".$start;
return $sql;
}
public function escape($data){
/*
as far as I can see the only way to escape data is by using oci_bind_by_name
while it is neat solution in common case, it conflicts with existing SQL building logic
fallback to simple escaping
*/
return str_replace("'","''",$data);
}
public function begin_transaction(){
//auto-start of transaction
}
public function commit_transaction(){
oci_commit($this->connection);
}
public function rollback_transaction(){
oci_rollback($this->connection);
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! Implementation of DataWrapper for PDO
if you plan to use it for Oracle - use Oracle connection type instead
**/
class PDODBDataWrapper extends DBDataWrapper{
private $last_result;//!< store result or last operation
public function query($sql){
LogMaster::log($sql);
$res=$this->connection->query($sql);
if ($res===false) {
$message = $this->connection->errorInfo();
throw new Exception("PDO - sql execution failed\n".$message[2]);
}
return new PDOResultSet($res);
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
$sql="SELECT ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
if ($start || $count) {
if ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)=="pgsql")
$sql.=" OFFSET ".$start." LIMIT ".$count;
else
$sql.=" LIMIT ".$start.",".$count;
}
return $sql;
}
public function get_next($res){
$data = $res->next();
return $data;
}
public function get_new_id(){
return $this->connection->lastInsertId();
}
public function escape($str){
$res=$this->connection->quote($str);
if ($res===false) //not supported by pdo driver
return str_replace("'","''",$str);
return substr($res,1,-1);
}
}
class PDOResultSet{
private $res;
public function __construct($res){
$this->res = $res;
}
public function next(){
$data = $this->res->fetch(PDO::FETCH_ASSOC);
if (!$data){
$this->res->closeCursor();
return null;
}
return $data;
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
//DataProcessor::$action_param ="dhx_editor_status";
/*! Implementation of DataWrapper for PDO
if you plan to use it for Oracle - use Oracle connection type instead
**/
class PHPCakeDBDataWrapper extends ArrayDBDataWrapper{
public function select($sql){
$source = $sql->get_source();
if (is_array($source)) //result of find
$res = $source;
else
$res = $this->connection->find("all");
if (sizeof($res)){
$name = get_class($this->connection);
$temp = array();
for ($i=sizeof($res)-1; $i>=0; $i--)
$temp[]=&$res[$i][$name];
}
return new ArrayQueryWrapper($temp);
}
protected function getErrorMessage(){
$errors = $this->connection->invalidFields();
$text = array();
foreach ($errors as $key => $value){
$text[] = $key." - ".$value[0];
}
return implode("\n", $text);
}
public function insert($data,$source){
$name = get_class($this->connection);
$save = array();
$temp_data = $data->get_data();
unset($temp_data[$this->config->id['db_name']]);
unset($temp_data["!nativeeditor_status"]);
$save[$name] = $temp_data;
if ($this->connection->save($save)){
$data->success($this->connection->getLastInsertID());
} else {
$data->set_response_attribute("details", $this->getErrorMessage());
$data->invalid();
}
}
public function delete($data,$source){
$id = $data->get_id();
$this->connection->delete($id);
$data->success();
}
public function update($data,$source){
$name = get_class($this->connection);
$save = array();
$save[$name] = &$data->get_data();
if ($this->connection->save($save)){
$data->success();
} else {
$data->set_response_attribute("details", $this->getErrorMessage());
$data->invalid();
}
}
public function escape($str){
throw new Exception("Not implemented");
}
public function query($str){
throw new Exception("Not implemented");
}
public function get_new_id(){
throw new Exception("Not implemented");
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! Implementation of DataWrapper for PDO
if you plan to use it for Oracle - use Oracle connection type instead
**/
class PHPCIDBDataWrapper extends DBDataWrapper{
private $last_result;//!< store result or last operation
public function query($sql){
LogMaster::log($sql);
$res=$this->connection->query($sql);
if ($res===false) {
throw new Exception("CI - sql execution failed");
}
return new PHPCIResultSet($res);
}
public function get_next($res){
$data = $res->next();
return $data;
}
public function get_new_id(){
return $this->connection->insert_id();
}
public function escape($str){
return $this->connection->escape_str($str);
}
public function escape_name($data){
return $this->connection->protect_identifiers($data);
}
}
class PHPCIResultSet{
private $res;
private $start;
private $count;
public function __construct($res){
$this->res = $res;
$this->start = $res->current_row;
$this->count = $res->num_rows;
}
public function next(){
if ($this->start != $this->count){
return $this->res->row($this->start++,'array');
} else {
$this->res->free_result();
return null;
}
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
public function select($sql){
if (is_array($this->connection)) //result of findAll
$res = $this->connection;
else
$res = $this->connection->findAll();
if (sizeof($res)){
$temp = array();
foreach ($res as $obj)
$temp[]=$obj->getAttributes();
}
return new ArrayQueryWrapper($temp);
}
protected function getErrorMessage(){
$errors = $this->connection->invalidFields();
$text = array();
foreach ($errors as $key => $value){
$text[] = $key." - ".$value[0];
}
return implode("\n", $text);
}
public function insert($data,$source){
$name = get_class($this->connection);
$obj = new $name();
$this->fill_model_and_save($obj, $data);
}
public function delete($data,$source){
$obj = $this->connection->findByPk($data->get_id());
if ($obj->delete()){
$data->success();
$data->set_new_id($obj->getPrimaryKey());
} else {
$data->set_response_attribute("details", $this->errors_to_string($obj->getErrors()));
$data->invalid();
}
}
public function update($data,$source){
$obj = $this->connection->findByPk($data->get_id());
$this->fill_model_and_save($obj, $data);
}
protected function fill_model_and_save($obj, $data){
$values = $data->get_data();
//map data to model object
for ($i=0; $i < sizeof($this->config->text); $i++){
$step=$this->config->text[$i];
$obj->setAttribute($step["name"], $data->get_value($step["name"]));
}
if ($relation = $this->config->relation_id["db_name"])
$obj->setAttribute($relation, $data->get_value($relation));
//save model
if ($obj->save()){
$data->success();
$data->set_new_id($obj->getPrimaryKey());
} else {
$data->set_response_attribute("details", $this->errors_to_string($obj->getErrors()));
$data->invalid();
}
}
protected function errors_to_string($errors){
$text = array();
foreach($errors as $value)
$text[]=implode("\n", $value);
return implode("\n",$text);
}
public function escape($str){
throw new Exception("Not implemented");
}
public function query($str){
throw new Exception("Not implemented");
}
public function get_new_id(){
throw new Exception("Not implemented");
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! Implementation of DataWrapper for PostgreSQL
**/
class PostgreDBDataWrapper extends DBDataWrapper{
public function query($sql){
LogMaster::log($sql);
$res=pg_query($this->connection,$sql);
if ($res===false) throw new Exception("Postgre - sql execution failed\n".pg_last_error($this->connection));
return $res;
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
$sql="SELECT ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
if ($start || $count)
$sql.=" OFFSET ".$start." LIMIT ".$count;
return $sql;
}
public function get_next($res){
return pg_fetch_assoc($res);
}
public function get_new_id(){
$res = pg_query( $this->connection, "SELECT LASTVAL() AS seq");
$data = pg_fetch_assoc($res);
pg_free_result($res);
return $data['seq'];
}
public function escape($data){
//need to use oci_bind_by_name
return pg_escape_string($this->connection,$data);
}
public function tables_list() {
$sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
$res = pg_query($this->connection, $sql);
$tables = array();
while ($table = pg_fetch_assoc($res)) {
$tables[] = $table['table_name'];
}
return $tables;
}
public function fields_list($table) {
$sql = "SELECT * FROM information_schema.constraint_column_usage";
$result = pg_query($this->connection, $sql);
$field = pg_fetch_assoc($result);
$id = $field['column_name'];
$sql = "SELECT * FROM information_schema.columns WHERE table_name ='".$table."';";
$result = pg_query($this->connection, $sql);
$fields = array();
$id = "";
while ($field = pg_fetch_assoc($result)) {
$fields[] = $field["column_name"];
}
return array('fields' => $fields, 'key' => $id );
}
}
?>
\ No newline at end of file
<?php
require_once("db_common.php");
/*! SaSQL implementation of DataWrapper
**/
class SaSQLDBDataWrapper extends DBDataWrapper{
private $last_id=""; //!< ID of previously inserted record
public function query($sql){
LogMaster::log($sql);
$res=sasql_query($this->connection, $sql);
if ($res===false) throw new Exception("SaSQL operation failed\n".sasql_error($this->connection));
$this->last_result = $res;
return $res;
}
public function get_next($res){
if (!$res)
$res = $this->last_result;
return sasql_fetch_assoc($res);
}
public function get_new_id(){
return sasql_insert_id($this->connection);
}
protected function insert_query($data,$request){
$sql = parent::insert_query($data,$request);
$this->insert_operation=true;
return $sql;
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
$sql="SELECT " ;
if ($count)
$sql.=" TOP ".($count+$start);
$sql.=" ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
return $sql;
}
public function escape($data){
return sasql_escape_string($this->connection, $data);
}
public function begin_transaction(){
$this->query("BEGIN TRAN");
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! SQLite implementation of DataWrapper
**/
class SQLiteDBDataWrapper extends DBDataWrapper{
public function query($sql){
LogMaster::log($sql);
$res = sqlite_query($this->connection,$sql);
if ($res === false)
throw new Exception("SQLLite - sql execution failed\n".sqlite_error_string(sqlite_last_error($this->connection)));
return $res;
}
public function get_next($res){
$data = sqlite_fetch_array($res, SQLITE_ASSOC);
return $data;
}
public function get_new_id(){
return sqlite_last_insert_rowid($this->connection);
}
public function escape($data){
return sqlite_escape_string($data);
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
require_once("db_common.php");
/*! SQLite implementation of DataWrapper
**/
class SQLite3DBDataWrapper extends DBDataWrapper{
public function query($sql){
LogMaster::log($sql);
$res = $this->connection->query($sql);
if ($res === false)
throw new Exception("SQLLite - sql execution failed\n".$this->connection->lastErrorMsg());
return $res;
}
public function get_next($res){
return $res->fetchArray();
}
public function get_new_id(){
return $this->connection->lastInsertRowID();
}
public function escape($data){
return $this->connection->escapeString($data);
}
}
?>
\ No newline at end of file
<?php
/*
@author dhtmlx.com
@license GPL, see license.txt
*/
class FileTreeDataItem extends TreeDataItem {
function has_kids(){
if ($this->data['is_folder'] == '1') {
return true;
} else {
return false;
}
}
}
?>
\ No newline at end of file
This diff is collapsed.
/*
This software is allowed to use under GPL or you need to obtain Commercial or Enterise License
to use it in non-GPL project. Please contact sales@dhtmlx.com for details
*/
gantt.config.quickinfo_buttons=["icon_delete","icon_edit"],gantt.config.quick_info_detached=!0,gantt.attachEvent("onTaskClick",function(t){return gantt.showQuickInfo(t),!0}),function(){for(var t=["onEmptyClick","onViewChange","onLightbox","onBeforeTaskDelete","onBeforeDrag"],e=function(){return gantt._hideQuickInfo(),!0},n=0;n<t.length;n++)gantt.attachEvent(t[n],e)}(),gantt.templates.quick_info_title=function(t,e,n){return n.text.substr(0,50)},gantt.templates.quick_info_content=function(t,e,n){return n.details||n.text},gantt.templates.quick_info_date=function(t,e,n){return gantt.templates.task_time(t,e,n)},gantt.showQuickInfo=function(t){if(t!=this._quick_info_box_id){this.hideQuickInfo(!0);var e=this._get_event_counter_part(t);e&&(this._quick_info_box=this._init_quick_info(e),this._fill_quick_data(t),this._show_quick_info(e))}},gantt._hideQuickInfo=function(){gantt.hideQuickInfo()},gantt.hideQuickInfo=function(t){var e=this._quick_info_box;if(this._quick_info_box_id=0,e&&e.parentNode){if(gantt.config.quick_info_detached)return e.parentNode.removeChild(e);"auto"==e.style.right?e.style.left="-350px":e.style.right="-350px",t&&e.parentNode.removeChild(e)}},dhtmlxEvent(window,"keydown",function(t){27==t.keyCode&&gantt.hideQuickInfo()}),gantt._show_quick_info=function(t){var e=gantt._quick_info_box;if(gantt.config.quick_info_detached){e.parentNode&&"#document-fragment"!=e.parentNode.nodeName.toLowerCase()||gantt.$task_data.appendChild(e);var n=e.offsetWidth,i=e.offsetHeight,a=this.getScrollState(),s=this.$task.offsetWidth+a.x-n;e.style.left=Math.min(Math.max(a.x,t.left-t.dx*(n-t.width)),s)+"px",e.style.top=t.top-(t.dy?i:-t.height)-25+"px"}else e.style.top="20px",1==t.dx?(e.style.right="auto",e.style.left="-300px",setTimeout(function(){e.style.left="-10px"},1)):(e.style.left="auto",e.style.right="-300px",setTimeout(function(){e.style.right="-10px"},1)),e.className=e.className.replace("dhx_qi_left","").replace("dhx_qi_left","")+" dhx_qi_"+(1==t?"left":"right"),gantt._obj.appendChild(e)},gantt._init_quick_info=function(){if(!this._quick_info_box){var t=this._quick_info_box=document.createElement("div");t.className="dhx_cal_quick_info",gantt.$testmode&&(t.className+=" dhx_no_animate");var e='<div class="dhx_cal_qi_title"><div class="dhx_cal_qi_tcontent"></div><div class="dhx_cal_qi_tdate"></div></div><div class="dhx_cal_qi_content"></div>';e+='<div class="dhx_cal_qi_controls">';for(var n=gantt.config.quickinfo_buttons,i=0;i<n.length;i++)e+='<div class="dhx_qi_big_icon '+n[i]+'" title="'+gantt.locale.labels[n[i]]+"\"><div class='dhx_menu_icon "+n[i]+"'></div><div>"+gantt.locale.labels[n[i]]+"</div></div>";e+="</div>",t.innerHTML=e,dhtmlxEvent(t,"click",function(t){t=t||event,gantt._qi_button_click(t.target||t.srcElement)}),gantt.config.quick_info_detached&&dhtmlxEvent(gantt.$task_data,"scroll",function(){gantt.hideQuickInfo()})}return this._quick_info_box},gantt._qi_button_click=function(t){var e=gantt._quick_info_box;if(t&&t!=e){var n=t.className;if(-1!=n.indexOf("_icon")){var i=gantt._quick_info_box_id;gantt.$click.buttons[n.split(" ")[1].replace("icon_","")](i)}else gantt._qi_button_click(t.parentNode)}},gantt._get_event_counter_part=function(t){for(var e=gantt.getTaskNode(t),n=0,i=0,a=e;a&&"gantt_task"!=a.className;)n+=a.offsetLeft,i+=a.offsetTop,a=a.offsetParent;var s=this.getScrollState();if(a){var r=n+e.offsetWidth/2-s.x>gantt._x/2?1:0,o=i+e.offsetHeight/2-s.y>gantt._y/2?1:0;return{left:n,top:i,dx:r,dy:o,width:e.offsetWidth,height:e.offsetHeight}}return 0},gantt._fill_quick_data=function(t){var e=gantt.getTask(t),n=gantt._quick_info_box;gantt._quick_info_box_id=t;var i=n.firstChild.firstChild;i.innerHTML=gantt.templates.quick_info_title(e.start_date,e.end_date,e);var a=i.nextSibling;a.innerHTML=gantt.templates.quick_info_date(e.start_date,e.end_date,e);var s=n.firstChild.nextSibling;s.innerHTML=gantt.templates.quick_info_content(e.start_date,e.end_date,e)};
\ No newline at end of file
/*
This software is allowed to use under GPL or you need to obtain Commercial or Enterise License
to use it in non-GPL project. Please contact sales@dhtmlx.com for details
*/
gantt._tooltip={},gantt._tooltip_class="gantt_tooltip",gantt.config.tooltip_timeout=30,gantt._create_tooltip=function(){return this._tooltip_html||(this._tooltip_html=document.createElement("div"),this._tooltip_html.className=gantt._tooltip_class),this._tooltip_html},gantt._show_tooltip=function(t,e){if(!gantt.config.touch||gantt.config.touch_tooltip){var n=this._create_tooltip();n.innerHTML=t,gantt.$task_data.appendChild(n);var i=n.offsetWidth+20,a=n.offsetHeight+40,s=this.$task.offsetHeight,r=this.$task.offsetWidth,o=this.getScrollState();e.x+=o.x,e.y+=o.y,e.y=Math.min(Math.max(o.y,e.y),o.y+s-a),e.x=Math.min(Math.max(o.x,e.x),o.x+r-i),n.style.left=e.x+"px",n.style.top=e.y+"px"}},gantt._hide_tooltip=function(){this._tooltip_html&&this._tooltip_html.parentNode&&this._tooltip_html.parentNode.removeChild(this._tooltip_html),this._tooltip_id=0},gantt._is_tooltip=function(t){var e=t.target||t.srcElement;return gantt._is_node_child(e,function(t){return t.className==this._tooltip_class})},gantt._is_task_line=function(t){var e=t.target||t.srcElement;return gantt._is_node_child(e,function(t){return t==this.$task_data})},gantt._is_node_child=function(t,e){for(var n=!1;t&&!n;)n=e.call(gantt,t),t=t.parentNode;return n},gantt._tooltip_pos=function(t){if(t.pageX||t.pageY)var e={x:t.pageX,y:t.pageY};var n=_isIE?document.documentElement:document.body,e={x:t.clientX+n.scrollLeft-n.clientLeft,y:t.clientY+n.scrollTop-n.clientTop},i=gantt._get_position(gantt.$task);return e.x=e.x-i.x,e.y=e.y-i.y,e},gantt.attachEvent("onMouseMove",function(t,e){this.config.tooltip_timeout?(document.createEventObject&&!document.createEvent&&(e=document.createEventObject(e)),clearTimeout(gantt._tooltip_ev_timer),gantt._tooltip_ev_timer=setTimeout(function(){gantt._init_tooltip(t,e)},gantt.config.tooltip_timeout)):gantt._init_tooltip(t,e)}),gantt._init_tooltip=function(t,e){if(!this._is_tooltip(e)&&(t!=this._tooltip_id||this._is_task_line(e))){if(!t)return this._hide_tooltip();this._tooltip_id=t;var n=this.getTask(t),i=this.templates.tooltip_text(n.start_date,n.end_date,n);i||this._hide_tooltip(),this._show_tooltip(i,this._tooltip_pos(e))}},gantt.attachEvent("onMouseLeave",function(t){gantt._is_tooltip(t)||this._hide_tooltip()}),gantt.templates.tooltip_date_format=gantt.date.date_to_str("%Y-%m-%d"),gantt.templates.tooltip_text=function(t,e,n){return"<b>Task:</b> "+n.text+"<br/><b>Start date:</b> "+gantt.templates.tooltip_date_format(t)+"<br/><b>End date:</b> "+gantt.templates.tooltip_date_format(e)};
\ No newline at end of file
gantt.locale={date:{month_full:["January","February","March","April","May","June","July","August","September","October","November","December"],month_short:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],day_full:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],day_short:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},labels:{new_task:"New task",icon_save:"Save",icon_cancel:"Cancel",icon_details:"Details",icon_edit:"Edit",icon_delete:"Delete",confirm_closing:"",confirm_deleting:"Task will be deleted permanently, are you sure?",section_description:"Description",section_time:"Time period",column_text:"Task name",column_start_date:"Start time",column_duration:"Duration",column_add:"",link:"Link",confirm_link_deleting:"will be deleted",link_start:" (start)",link_end:" (end)",minutes:"Minutes",hours:"Hours",days:"Days",weeks:"Week",months:"Months",years:"Years"}};
\ No newline at end of file
scheduler.locale={date:{month_full:["كانون الثاني","شباط","آذار","نيسان","أيار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول"],month_short:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],day_full:["الأحد","الأثنين","ألثلاثاء","الأربعاء","ألحميس","ألجمعة","السبت"],day_short:["احد","اثنين","ثلاثاء","اربعاء","خميس","جمعة","سبت"]},labels:{dhx_cal_today_button:"اليوم",day_tab:"يوم",week_tab:"أسبوع",month_tab:"شهر",new_event:"حدث جديد",icon_save:"اخزن",icon_cancel:"الغاء",icon_details:"تفاصيل",icon_edit:"تحرير",icon_delete:"حذف",confirm_closing:"التغييرات سوف تضيع, هل انت متأكد؟",confirm_deleting:"الحدث سيتم حذفها نهائيا ، هل أنت متأكد؟",section_description:"الوصف",section_time:"الفترة الزمنية",column_text:"Task name",column_start_date:"Start time",column_duration:"Duration",column_add:"",link:"Link",confirm_link_deleting:"will be deleted",link_start:" (start)",link_end:" (end)",minutes:"Minutes",hours:"Hours",days:"Days",weeks:"Week",months:"Months",years:"Years"}};
\ No newline at end of file
gantt.locale={date:{month_full:["Студзень","Люты","Сакавік","Красавік","Maй","Чэрвень","Ліпень","Жнівень","Верасень","Кастрычнік","Лістапад","Снежань"],month_short:["Студз","Лют","Сак","Крас","Maй","Чэр","Ліп","Жнів","Вер","Каст","Ліст","Снеж"],day_full:["Нядзеля","Панядзелак","Аўторак","Серада","Чацвер","Пятніца","Субота"],day_short:["Нд","Пн","Аўт","Ср","Чцв","Пт","Сб"]},labels:{dhx_cal_today_button:"Сёння",day_tab:"Дзень",week_tab:"Тыдзень",month_tab:"Месяц",new_event:"Новая падзея",icon_save:"Захаваць",icon_cancel:"Адмяніць",icon_details:"Дэталі",icon_edit:"Змяніць",icon_delete:"Выдаліць",confirm_closing:"",confirm_deleting:"Падзея будзе выдалена незваротна, працягнуць?",section_description:"Апісанне",section_time:"Перыяд часу",column_text:"Задача",column_start_date:"Пачатак",column_duration:"Працяг",column_add:"",link:"Сувязь",confirm_link_deleting:"будзе выдалена",link_start:"(пачатак)",link_end:"(канец)",minutes:"Хвiлiна",hours:"Гадзiна",days:"Дзень",weeks:"Тыдзень",months:"Месяц",years:"Год"}};
\ No newline at end of file
scheduler.locale={date:{month_full:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],month_short:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],day_full:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],day_short:["Dg","Dl","Dm","Dc","Dj","Dv","Ds"]},labels:{dhx_cal_today_button:"Hui",day_tab:"Dia",week_tab:"Setmana",month_tab:"Mes",new_event:"Nou esdeveniment",icon_save:"Guardar",icon_cancel:"Cancel·lar",icon_details:"Detalls",icon_edit:"Editar",icon_delete:"Esborrar",confirm_closing:"",confirm_deleting:"L'esdeveniment s'esborrarà definitivament, continuar ?",section_description:"Descripció",section_time:"Periode de temps",column_text:"Task name",column_start_date:"Start time",column_duration:"Duration",column_add:"",link:"Link",confirm_link_deleting:"will be deleted",link_start:" (start)",link_end:" (end)",minutes:"Minutes",hours:"Hours",days:"Days",weeks:"Week",months:"Months",years:"Years"}};
\ No newline at end of file
scheduler.config.day_date="%M %d日 %D",scheduler.config.default_date="%Y年 %M %d日",scheduler.config.month_date="%Y年 %M",scheduler.locale={date:{month_full:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],month_short:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],day_full:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],day_short:["","","","","","",""]},labels:{dhx_cal_today_button:"今天",day_tab:"",week_tab:"",month_tab:"",new_event:"新建日程",icon_save:"保存",icon_cancel:"关闭",icon_details:"详细",icon_edit:"编辑",icon_delete:"删除",confirm_closing:"请确认是否撤销修改!",confirm_deleting:"是否删除日程?",section_description:"描述",section_time:"时间范围",column_text:"Task name",column_start_date:"Start time",column_duration:"Duration",column_add:"",link:"Link",confirm_link_deleting:"will be deleted",link_start:" (start)",link_end:" (end)",minutes:"Minutes",hours:"Hours",days:"Days",weeks:"Week",months:"Months",years:"Years"}};
\ 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.
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