TreeAjax.php 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873
  1. <?php
  2. Lib::loadClass('ViewAjax');
  3. class TreeAjax extends ViewAjax {
  4. private $_cnf = '';// Column
  5. private $_htmlID = '';
  6. private $_dataSource = null;
  7. private $_rowFunctions = array();
  8. public function __construct($tblAcl) {
  9. $this->_tbl = $tblAcl->getName();
  10. $this->_acl = $tblAcl;
  11. $this->_zasobID = $tblAcl->getID();
  12. Lib::loadClass('Data_Tree_Source');
  13. $this->_dataSource = new Data_Tree_Source($tblAcl->getDB());
  14. $this->_dataSource->setTable($tblAcl->getName());
  15. $this->_dataSource->setCols($tblAcl->getRealFieldList());
  16. $this->_dataSource->setVirtualCols($tblAcl->getVirtualFieldList());
  17. // TODO: mv to config or Zasoby (ALIAS?)
  18. switch ($tblAcl->getName()) {
  19. case 'IN7_MK_BAZA_DYSTRYBUCJI':
  20. $this->_dataSource->setParentIdField('P_ID');
  21. $this->_dataSource->setNameField('ID');//M_DIST_DESC
  22. break;
  23. case 'CRM_LISTA_ZASOBOW':
  24. $this->_dataSource->setParentIdField('PARENT_ID');
  25. $this->_dataSource->setNameField('ID');// 'DESC_PL'
  26. $this->_dataSource->setSortField('SORT_PRIO');
  27. break;
  28. case 'CRM_PROCES':
  29. $this->_dataSource->setParentIdField('PARENT_ID');
  30. $this->_dataSource->setNameField('ID');
  31. $this->_dataSource->setSortField('SORT_PRIO');
  32. break;
  33. default:
  34. }
  35. $hash = V::get('_hash', '', $_GET);
  36. $this->_htmlID = ($hash)? $hash : $this->_tbl . '-Tree';//uniqid($this->_tbl);
  37. // TODO: load filters and state: table, edit, add, etc.
  38. // TODO: save this data in Workspace 1, 2, 3, etc.
  39. }
  40. public function renderRootNode() {
  41. ?>
  42. <tr data-tt-id="0" data-tt-parent-id="" data-tt-branch="true">
  43. <td>
  44. <span class="directory">0</span>
  45. </td>
  46. <td coslpan="<?php echo count($fieldList); ?>"></td>
  47. </tr>
  48. <?php
  49. }
  50. public function renderNode($node) {
  51. $visibleCols = $this->_acl->getVisibleFieldList();
  52. $fieldList = array();
  53. foreach ($visibleCols as $fieldID => $col) {
  54. if ($col == 'ID') {// || $col == $this->_dataSource->getParentIdField()) {
  55. continue;
  56. }
  57. $fieldList[] = $col;
  58. }
  59. ?>
  60. <tr data-tt-id="<?php echo $node->id; ?>" data-tt-parent-id="<?php echo ($node->parent_id > 0)? $node->parent_id : ''; ?>" data-tt-branch="<?php echo ($node->type == 'folder')? 'true' : 'false'; ?>" class="ui-state-default">
  61. <td class="TreeAjax-cell-indenter">
  62. <span class="<?php echo $node->type; ?>">
  63. <i class="icon-folder-open"></i>
  64. <?php echo $node->name; ?>
  65. </span>
  66. </td>
  67. <?php if ($this->_dataSource->hasSortField()) : ?>
  68. <td class="TreeAjax-cell-sorter">
  69. <i class="sort-handler icon-resize-vertical"></i>
  70. </td>
  71. <?php endif; ?>
  72. <?php if (true) : ?>
  73. <td class="TreeAjax-cell-edit">
  74. <a href="#EDIT/<?php echo $node->id; ?>" class="icon-pencil" title="Edytuj rekord"> </a>
  75. </td>
  76. <?php endif; ?>
  77. <?php foreach ($fieldList as $fieldName) : $val = V::get($fieldName, '', $node->data); ?>
  78. <td class="TreeAjax-cell-data tbl-short-txt"><span title="<?php echo $val; ?>"><?php echo $val ?></span></td>
  79. <?php endforeach; ?>
  80. </tr>
  81. <?php
  82. }
  83. public function render() {
  84. if (!$this->_dataSource->isValidTree()) {
  85. $msg = "Błąd nie można wyświetlić drzewa dla tej tabeli";
  86. $msg = '<div class="alert alert-error">' . $msg . '</div>';
  87. $msg = '<div class="container">' . $msg . '</div>';
  88. return $msg;
  89. }
  90. $visibleCols = $this->_acl->getVisibleFieldList();
  91. $fieldList = array();
  92. foreach ($visibleCols as $fieldID => $col) {
  93. if ($col == 'ID') {// || $col == $this->_dataSource->getParentIdField()) {
  94. continue;
  95. }
  96. $fieldList[] = $col;
  97. }
  98. $nodes = $this->_dataSource->getTreeNodes(0, array('order_by'=>'SORT_PRIO'));
  99. $pInitList = array();
  100. $forceFilterInit = array();
  101. ob_start();
  102. // class="TreeAjax table table-striped table-hover table-bordered table-condensed"
  103. ?>
  104. <link rel="stylesheet" href="stuff/jquery.treetable/jquery.treetable.css" type="text/css" />
  105. <link rel="stylesheet" href="stuff/jquery.treetable/jquery.treetable.theme.default.css" type="text/css" />
  106. <style type="text/css">
  107. .treetable .icon-folder-open { margin-top:0; }
  108. .treetable tr.selected .icon-folder-open { background-image: url(stuff/twitter-bootstrap/img/glyphicons-halflings-white.png); }
  109. .treetable {white-space:nowrap; width:auto;}
  110. .treetable .TreeAjax-cell-sorter { cursor:pointer; }
  111. .treetable td,
  112. .treetable th { border-color:#999; }
  113. .AjaxTreeCont .breadcrumb em { color:#bbb; }
  114. .AjaxTreeCont .treetable tr.selected td { background-color:#3875D7; color:#FFF; }
  115. /* loading */
  116. .AjaxTreeCont .loading-info {display:none;}
  117. .AjaxTreeCont .inlineEditBox .loading-info {display:block;}
  118. .AjaxTree-loading .loading-info,
  119. .AjaxTreeCont .inlineEditBox .loading-info {display:block; padding:0 0 0 20px; background:url(./icon/loading.gif) no-repeat left top;}
  120. /* form btn Cofnij: .appendBack */
  121. .AjaxTreeCont .AjaxTableEdit .show-last-value .btn-appendBack,
  122. .AjaxTreeCont .AjaxFrmHorizontalEdit .show-last-value .btn-appendBack {display:none;}
  123. </style>
  124. <div class="AjaxTreeCont">
  125. <ul class="breadcrumb">
  126. <li><a href="#" onclick="return treeAjaxBackToTree();"><?php echo $this->getLabelHtml(); ?></a></li>
  127. <?php if (!empty($pInitList)) : ?>
  128. <div class="btn-group pull-right">
  129. <a class="btn btn-mini btn-info dropdown-toggle" data-toggle="dropdown" href="#" title="Uruchom filtr procesu powiązanego z tabelą <?php echo $this->getLabel(); ?>">
  130. Filtr procesu
  131. <span class="caret"></span>
  132. </a>
  133. <ul class="dropdown-menu pull-left">
  134. <?php foreach ($pInitList as $kId => $vLabel) : ?>
  135. <?php if ($pInitListSelected && $pInitListSelected == $kId) : ?>
  136. <li class="disabled">
  137. <?php else : ?>
  138. <li>
  139. <?php endif; ?>
  140. <a href="index.php?FUNCTION_INIT=MENU_SELECT_PROCES&_action=setPermsByProces&id_proces=<?php echo $kId; ?>&MENU_INIT=VIEWTABLE_AJAX&ZASOB_ID=<?php echo $this->_zasobID; ?>" title="<?php echo htmlspecialchars("{{$kId}} {$vLabel}"); ?>"><?php echo "{{$kId}} " . V::strShortUtf8($vLabel, 50); ?></a>
  141. </li>
  142. <?php endforeach; ?>
  143. </ul>
  144. </div>
  145. <?php endif; ?>
  146. <a class="pull-right" style="padding:0 20px 0 0;" href="<?php echo "index.php?MENU_INIT=VIEWTABLE_AJAX&ZASOB_ID={$this->_zasobID}"; ?>"><i class="icon-list"></i> Tabela</a>
  147. </ul>
  148. <table id="<?php echo $this->_htmlID; ?>" class="TreeAjax table table-bordered">
  149. <thead>
  150. <tr>
  151. <th></th>
  152. <?php if ($this->_dataSource->hasSortField()) : ?>
  153. <th class="TreeAjax-cell-sorter">
  154. <i title="Sortuj" class="icon-question-sign"></i>
  155. </th>
  156. <?php endif; ?>
  157. <?php if (true) : ?>
  158. <th class="TreeAjax-cell-edit">
  159. <i title="Edytuj rekord" class="icon-question-sign"></i>
  160. </th>
  161. <?php endif; ?>
  162. <?php foreach ($fieldList as $label) : ?>
  163. <th><?php echo $label; ?></th>
  164. <?php endforeach; ?>
  165. </tr>
  166. </thead>
  167. <tbody>
  168. <?php //$this->renderRootNode(); ?>
  169. <?php foreach ($nodes as $node) : ?>
  170. <?php //$this->renderNode($node); ?>
  171. <?php endforeach; ?>
  172. </tbody>
  173. </table>
  174. </div>
  175. <script>
  176. /*
  177. * jQuery treeTable Plugin 3.0.2
  178. * http://ludo.cubicphuse.nl/jquery-treetable
  179. *
  180. * Copyright 2013, Ludo van den Boom
  181. * Dual licensed under the MIT or GPL Version 2 licenses.
  182. */
  183. (function() {
  184. var $, Node, Tree, methods;
  185. $ = jQuery;
  186. Node = (function() {
  187. function Node(row, tree, settings) {
  188. var parentId;
  189. this.row = row;
  190. this.tree = tree;
  191. this.settings = settings;
  192. // TODO Ensure id/parentId is always a string (not int)
  193. this.id = this.row.data(this.settings.nodeIdAttr);
  194. // TODO Move this to a setParentId function?
  195. parentId = this.row.data(this.settings.parentIdAttr);
  196. if (parentId != null && parentId !== "") {
  197. this.parentId = parentId;
  198. }
  199. this.treeCell = $(this.row.children(this.settings.columnElType)[this.settings.column]);
  200. this.expander = $(this.settings.expanderTemplate);
  201. this.indenter = $(this.settings.indenterTemplate);
  202. this.children = [];
  203. this.initialized = false;
  204. this.treeCell.prepend(this.indenter);
  205. }
  206. Node.prototype.addChild = function(child) {
  207. return this.children.push(child);
  208. };
  209. Node.prototype.ancestors = function() {
  210. var ancestors, node;
  211. node = this;
  212. ancestors = [];
  213. while (node = node.parentNode()) {
  214. ancestors.push(node);
  215. }
  216. return ancestors;
  217. };
  218. Node.prototype.collapse = function() {
  219. this._hideChildren();
  220. this.row.removeClass("expanded").addClass("collapsed");
  221. this.expander.attr("title", this.settings.stringExpand);
  222. if (this.initialized && this.settings.onNodeCollapse != null) {
  223. this.settings.onNodeCollapse.apply(this);
  224. }
  225. return this;
  226. };
  227. // TODO destroy: remove event handlers, expander, indenter, etc.
  228. Node.prototype.expand = function() {
  229. if (this.initialized && this.settings.onNodeExpand != null) {
  230. this.settings.onNodeExpand.apply(this);
  231. }
  232. this.row.removeClass("collapsed").addClass("expanded");
  233. if ($(this.row).is(":visible")) {
  234. this._showChildren();
  235. }
  236. this.expander.attr("title", this.settings.stringCollapse);
  237. return this;
  238. };
  239. Node.prototype.expanded = function() {
  240. return this.row.hasClass("expanded");
  241. };
  242. Node.prototype.hide = function() {
  243. this._hideChildren();
  244. this.row.hide();
  245. return this;
  246. };
  247. Node.prototype.isBranchNode = function() {
  248. if(this.children.length > 0 || this.row.data(this.settings.branchAttr) === true) {
  249. return true;
  250. } else {
  251. return false;
  252. }
  253. };
  254. Node.prototype.updateBranchLeafClass = function(){
  255. this.row.removeClass('branch');
  256. this.row.removeClass('leaf');
  257. this.row.addClass(this.isBranchNode()?'branch':'leaf');
  258. };
  259. Node.prototype.level = function() {
  260. return this.ancestors().length;
  261. };
  262. Node.prototype.parentNode = function() {
  263. if (this.parentId != null) {
  264. return this.tree[this.parentId];
  265. } else {
  266. return null;
  267. }
  268. };
  269. Node.prototype.removeChild = function(child) {
  270. var i = $.inArray(child, this.children);
  271. return this.children.splice(i, 1)
  272. };
  273. Node.prototype.render = function() {
  274. var handler,
  275. settings = this.settings,
  276. target;
  277. if (settings.expandable === true && this.isBranchNode()) {
  278. handler = function(e) {
  279. $(this).parents("table").treetable("node", $(this).parents("tr").data(settings.nodeIdAttr)).toggle();
  280. return e.preventDefault();
  281. };
  282. this.indenter.html(this.expander);
  283. target = settings.clickableNodeNames === true ? this.treeCell : this.expander;
  284. target.off("click.treetable").on("click.treetable", handler);
  285. target.off("keydown.treetable").on("keydown.treetable", function(e) {
  286. if (e.keyCode == 13) {
  287. handler.apply(this, [e]);
  288. }
  289. });
  290. }
  291. if (settings.expandable === true && settings.initialState === "collapsed") {
  292. this.collapse();
  293. } else {
  294. this.expand();
  295. }
  296. this.indenter[0].style.paddingLeft = "" + (this.level() * settings.indent) + "px";
  297. return this;
  298. };
  299. Node.prototype.reveal = function() {
  300. if (this.parentId != null) {
  301. this.parentNode().reveal();
  302. }
  303. return this.expand();
  304. };
  305. Node.prototype.setParent = function(node) {
  306. if (this.parentId != null) {
  307. this.tree[this.parentId].removeChild(this);
  308. }
  309. this.parentId = node.id;
  310. this.row.data(this.settings.parentIdAttr, node.id);
  311. return node.addChild(this);
  312. };
  313. Node.prototype.show = function() {
  314. if (!this.initialized) {
  315. this._initialize();
  316. }
  317. this.row.show();
  318. if (this.expanded()) {
  319. this._showChildren();
  320. }
  321. return this;
  322. };
  323. Node.prototype.toggle = function() {
  324. if (this.expanded()) {
  325. this.collapse();
  326. } else {
  327. this.expand();
  328. }
  329. return this;
  330. };
  331. Node.prototype._hideChildren = function() {
  332. var child, _i, _len, _ref, _results;
  333. _ref = this.children;
  334. _results = [];
  335. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  336. child = _ref[_i];
  337. _results.push(child.hide());
  338. }
  339. return _results;
  340. };
  341. Node.prototype._initialize = function() {
  342. this.render();
  343. if (this.settings.onNodeInitialized != null) {
  344. this.settings.onNodeInitialized.apply(this);
  345. }
  346. return this.initialized = true;
  347. };
  348. Node.prototype._showChildren = function() {
  349. var child, _i, _len, _ref, _results;
  350. _ref = this.children;
  351. _results = [];
  352. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  353. child = _ref[_i];
  354. _results.push(child.show());
  355. }
  356. return _results;
  357. };
  358. return Node;
  359. })();
  360. Tree = (function() {
  361. function Tree(table, settings) {
  362. this.table = table;
  363. this.settings = settings;
  364. this.tree = {};
  365. // Cache the nodes and roots in simple arrays for quick access/iteration
  366. this.nodes = [];
  367. this.roots = [];
  368. if (typeof this.settings.router == "function") {
  369. var that = this;
  370. $(window).bind('hashchange', function() {
  371. //console.log('hashchange: location.hash: ' + location.hash);
  372. that.settings.router.apply(this);
  373. });
  374. that.settings.router.apply(this);
  375. }
  376. }
  377. Tree.prototype.collapseAll = function() {
  378. var node, _i, _len, _ref, _results;
  379. _ref = this.nodes;
  380. _results = [];
  381. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  382. node = _ref[_i];
  383. _results.push(node.collapse());
  384. }
  385. return _results;
  386. };
  387. Tree.prototype.expandAll = function() {
  388. var node, _i, _len, _ref, _results;
  389. _ref = this.nodes;
  390. _results = [];
  391. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  392. node = _ref[_i];
  393. _results.push(node.expand());
  394. }
  395. return _results;
  396. };
  397. Tree.prototype.findLastNode = function (node) {
  398. if (node.children.length > 0) {
  399. return this.findLastNode(node.children[node.children.length - 1]);
  400. } else {
  401. return node;
  402. }
  403. };
  404. Tree.prototype.loadRows = function(rows) {
  405. var node, row, i;
  406. if (rows != null) {
  407. for (i = 0; i < rows.length; i++) {
  408. row = $(rows[i]);
  409. if (row.data(this.settings.nodeIdAttr) != null) {
  410. node = new Node(row, this.tree, this.settings);
  411. this.nodes.push(node);
  412. this.tree[node.id] = node;
  413. if (node.parentId != null) {
  414. if (this.tree[node.parentId]) {
  415. this.tree[node.parentId].addChild(node);
  416. } else {
  417. //console.log('loadRows this.tree[' + node.parentId + ']', this.tree[node.parentId])
  418. }
  419. } else {
  420. this.roots.push(node);
  421. }
  422. }
  423. }
  424. }
  425. for (i = 0; i < this.nodes.length; i++) {
  426. node = this.nodes[i].updateBranchLeafClass();
  427. }
  428. return this;
  429. };
  430. Tree.prototype.move = function(node, destination) {
  431. // Conditions:
  432. // 1: +node+ should not be inserted as a child of +node+ itself.
  433. // 2: +destination+ should not be the same as +node+'s current parent (this
  434. // prevents +node+ from being moved to the same location where it already
  435. // is).
  436. // 3: +node+ should not be inserted in a location in a branch if this would
  437. // result in +node+ being an ancestor of itself.
  438. var nodeParent = node.parentNode();
  439. if (node !== destination && destination.id !== node.parentId && $.inArray(node, destination.ancestors()) === -1) {
  440. node.setParent(destination);
  441. this._moveRows(node, destination);
  442. // Re-render parentNode if this is its first child node, and therefore
  443. // doesn't have the expander yet.
  444. if (node.parentNode().children.length === 1) {
  445. node.parentNode().render();
  446. }
  447. }
  448. if(nodeParent){
  449. nodeParent.updateBranchLeafClass();
  450. }
  451. if(node.parentNode()){
  452. node.parentNode().updateBranchLeafClass();
  453. }
  454. node.updateBranchLeafClass();
  455. return this;
  456. };
  457. Tree.prototype.render = function() {
  458. var root, _i, _len, _ref;
  459. _ref = this.roots;
  460. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  461. root = _ref[_i];
  462. // Naming is confusing (show/render). I do not call render on node from
  463. // here.
  464. root.show();
  465. }
  466. return this;
  467. };
  468. Tree.prototype._moveRows = function(node, destination) {
  469. var child, _i, _len, _ref, _results;
  470. node.row.insertAfter(destination.row);
  471. node.render();
  472. _ref = node.children;
  473. _results = [];
  474. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  475. child = _ref[_i];
  476. _results.push(this._moveRows(child, node));
  477. }
  478. return _results;
  479. };
  480. Tree.prototype.unloadBranch = function(node) {
  481. var child, children, i;
  482. for (i = 0; i < node.children.length; i++) {
  483. child = node.children[i];
  484. // Recursively remove all descendants of +node+
  485. this.unloadBranch(child);
  486. // Remove child from DOM (<tr>)
  487. child.row.remove();
  488. // Clean up Tree object (so Node objects are GC-ed)
  489. delete this.tree[child.id];
  490. this.nodes.splice($.inArray(child, this.nodes), 1);
  491. }
  492. // Reset node's collection of children
  493. node.children = [];
  494. node.updateBranchLeafClass();
  495. return this;
  496. };
  497. Tree.prototype.updateNodeHtmlData = function(id, newDataHtml) {
  498. var draggedNode = this.tree[id]
  499. // draggedNode = this.data("treetable").tree[id];// $("#<?php echo $this->_htmlID; ?>").treetable("node", node.id);
  500. , cellsOld = draggedNode.row.find('td')
  501. , cellsNew = $(newDataHtml).find('td')
  502. , cellsOldCnt = cellsOld.length
  503. , cellsNewCnt = cellsNew.length;
  504. if (cellsOldCnt > 1 && cellsOldCnt == cellsNewCnt) {
  505. for(var i=1; i<cellsOldCnt; i++){
  506. $(cellsOld[i]).replaceWith(cellsNew[i]);
  507. }
  508. }
  509. return this;
  510. };
  511. return Tree;
  512. })();
  513. // jQuery Plugin
  514. methods = {
  515. init: function(options, force) {
  516. var settings;
  517. settings = $.extend({
  518. branchAttr: "ttBranch",
  519. clickableNodeNames: false,
  520. column: 0,
  521. columnElType: "td", // i.e. 'td', 'th' or 'td,th'
  522. expandable: false,
  523. expanderTemplate: "<a href='#'>&nbsp;</a>",
  524. indent: 19,
  525. indenterTemplate: "<span class='indenter'></span>",
  526. initialState: "collapsed",
  527. nodeIdAttr: "ttId", // maps to data-tt-id
  528. parentIdAttr: "ttParentId", // maps to data-tt-parent-id
  529. stringExpand: "Expand",
  530. stringCollapse: "Collapse",
  531. router: null, // router
  532. // Events
  533. onInitialized: null,
  534. onNodeCollapse: null,
  535. onNodeExpand: null,
  536. onNodeInitialized: null
  537. }, options);
  538. return this.each(function() {
  539. var el = $(this), tree;
  540. if (force || el.data("treetable") === undefined) {
  541. tree = new Tree(this, settings);
  542. tree.loadRows(this.rows).render();
  543. el.addClass("treetable").data("treetable", tree);
  544. if (settings.onInitialized != null) {
  545. settings.onInitialized.apply(tree);
  546. }
  547. }
  548. return el;
  549. });
  550. },
  551. destroy: function() {
  552. return this.each(function() {
  553. return $(this).removeData("treetable").removeClass("treetable");
  554. });
  555. },
  556. collapseAll: function() {
  557. this.data("treetable").collapseAll();
  558. return this;
  559. },
  560. collapseNode: function(id) {
  561. var node = this.data("treetable").tree[id];
  562. if (node) {
  563. node.collapse();
  564. } else {
  565. throw new Error("Unknown node '" + id + "'");
  566. }
  567. return this;
  568. },
  569. expandAll: function() {
  570. this.data("treetable").expandAll();
  571. return this;
  572. },
  573. expandNode: function(id) {
  574. var node = this.data("treetable").tree[id];
  575. if (node) {
  576. if (!node.initialized) {
  577. node._initialize();
  578. }
  579. node.expand();
  580. } else {
  581. throw new Error("Unknown node '" + id + "'");
  582. }
  583. return this;
  584. },
  585. loadBranch: function(node, rows) {
  586. var settings = this.data("treetable").settings,
  587. tree = this.data("treetable").tree;
  588. // TODO Switch to $.parseHTML
  589. rows = $(rows);
  590. if (node == null) { // Inserting new root nodes
  591. this.append(rows);
  592. } else {
  593. var lastNode = this.data("treetable").findLastNode(node);
  594. rows.insertAfter(lastNode.row);
  595. }
  596. this.data("treetable").loadRows(rows);
  597. // Make sure nodes are properly initialized
  598. rows.filter("tr").each(function() {
  599. tree[$(this).data(settings.nodeIdAttr)].show();
  600. });
  601. return this;
  602. },
  603. move: function(nodeId, destinationId) {
  604. var destination, node;
  605. node = this.data("treetable").tree[nodeId];
  606. destination = this.data("treetable").tree[destinationId];
  607. this.data("treetable").move(node, destination);
  608. return this;
  609. },
  610. node: function(id) {
  611. return this.data("treetable").tree[id];
  612. },
  613. reveal: function(id) {
  614. var node = this.data("treetable").tree[id];
  615. if (node) {
  616. node.reveal();
  617. } else {
  618. throw new Error("Unknown node '" + id + "'");
  619. }
  620. return this;
  621. },
  622. unloadBranch: function(node) {
  623. this.data("treetable").unloadBranch(node);
  624. return this;
  625. },
  626. updateNode: function(id, params) {
  627. var params = params || {};
  628. if ('html' in params) {
  629. this.data("treetable").updateNodeHtmlData(id, params.html);
  630. }
  631. else {
  632. var that = this;
  633. $.ajax({
  634. data: {},
  635. type: "GET",
  636. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=NODE&ID=' + id
  637. })
  638. .done(function(data, textStatus, jqXHR){
  639. //console.log('move-info: ', data);
  640. //$("#<?php echo $this->_htmlID; ?>").treetable("updateNode", id, {html: jqXHR.responseText});
  641. that.data("treetable").updateNodeHtmlData(id, jqXHR.responseText);
  642. jQuery.notify('Aktualizacja danych ' + id, 'success');
  643. })
  644. .fail(function(jqXHR){// jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});
  645. var txt = jqXHR.responseText || 'Error';
  646. if (jqXHR.status == 404) {
  647. jQuery.notify(jqXHR.responseText, 'error');
  648. } else {
  649. jQuery.notify(jqXHR.responseText, 'warn');
  650. }
  651. });
  652. }
  653. }
  654. };
  655. $.fn.treetable = function(method) {
  656. if (methods[method]) {
  657. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  658. } else if (typeof method === 'object' || !method) {
  659. return methods.init.apply(this, arguments);
  660. } else {
  661. return $.error("Method " + method + " does not exist on jQuery.treetable");
  662. }
  663. };
  664. // Expose classes to world
  665. this.TreeTable || (this.TreeTable = {});
  666. this.TreeTable.Node = Node;
  667. this.TreeTable.Tree = Tree;
  668. }).call(this);
  669. </script>
  670. <script>
  671. function treeAjaxBackToTree() {
  672. var cont = jQuery('#<?php echo $this->_htmlID; ?>').parent();
  673. cont.show();
  674. var taskCont = jQuery('#<?php echo $this->_htmlID . '_task'; ?>').parent();
  675. taskCont.remove();
  676. // TODO: reload data?
  677. //var con = jQuery('#<?php echo $this->_htmlID; ?>');
  678. //con.TableAjaxLoadPage(0);// TODO: load current page
  679. }
  680. jQuery(document).ready(function(){
  681. /*
  682. jQuery('#<?php echo $this->_htmlID; ?>').TableAjax({
  683. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>',
  684. debug: true, // TODO: DBG
  685. height: 400 // TODO: ?
  686. });
  687. */
  688. var table = $("#<?php echo $this->_htmlID; ?>");
  689. function initializeTableRow() {
  690. var n = $(this);
  691. // Highlight on press
  692. n.on("mousedown", function() {
  693. $("tr.selected").removeClass("selected");
  694. $(this).addClass("selected");
  695. });
  696. // Drag & Drop Example Code
  697. n.find(".folder").on("mouseenter", function() {
  698. var el = $(this);
  699. if(!el.data("dndInit")) {
  700. el.data("dndInit", true);
  701. el.draggable({
  702. helper: "clone",
  703. opacity: .75,
  704. refreshPositions: true, // Performance?
  705. revert: "invalid",
  706. revertDuration: 300,
  707. scroll: true
  708. });
  709. }
  710. });
  711. // add droppable
  712. n.droppable({
  713. accept: ".file, .folder",
  714. drop: function(e, ui) {
  715. var droppedEl = ui.draggable.parents("tr")
  716. , node = $("#<?php echo $this->_htmlID; ?>").treetable("node", droppedEl.data("ttId"))
  717. , this_ttId = $(this).data("ttId");
  718. $(this).find(".placeholder").remove();
  719. // Update server-side tree
  720. $.ajax({
  721. data: { MOVE_TO_ID: this_ttId },
  722. type: "POST",
  723. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=MOVE&ID=' + node.id,
  724. })
  725. .done(function(data, textStatus, jqXHR){
  726. //console.log('move-info: ', data);
  727. $("#<?php echo $this->_htmlID; ?>").treetable("move", node.id, this_ttId);
  728. $("#<?php echo $this->_htmlID; ?>").treetable("updateNode", node.id, {html: jqXHR.responseText});
  729. jQuery.notify('Przeniesienie udane', 'success');
  730. })
  731. .fail(function(jqXHR){// jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});
  732. var txt = jqXHR.responseText || 'Error';
  733. if (jqXHR.status == 404) {
  734. jQuery.notify(jqXHR.responseText, 'error');
  735. } else {
  736. jQuery.notify(jqXHR.responseText, 'warn');
  737. }
  738. });
  739. },
  740. hoverClass: "accept",
  741. over: function(e, ui) {
  742. var droppedEl = ui.draggable.parents("tr");
  743. if(this != droppedEl[0] && !$(this).is(".expanded")) {
  744. $("#<?php echo $this->_htmlID; ?>").treetable("expandNode", $(this).data("ttId"));
  745. }
  746. }
  747. });
  748. /*
  749. .sortable({
  750. items: "tr:not(.placeholder)",
  751. sort: function() {
  752. // gets added unintentionally by droppable interacting with sortable
  753. // using connectWithSortable fixes this, but doesn't allow you to customize active/hoverClass options
  754. $(this).removeClass("ui-state-default");
  755. }
  756. });
  757. */
  758. // add tooltips
  759. if (false) n.find('.TreeAjax-cell-data').each(function(ind, n){
  760. var title;
  761. //console.log('TreeAjax-cell-data.each(n:', n, n.firstChild);
  762. if(n.firstChild) {
  763. title = jQuery(n.firstChild).data('original-title');
  764. }
  765. if (title) {
  766. jQuery(n).tooltip({
  767. title: title,
  768. html: true,
  769. container: 'body',
  770. trigger: 'hover',
  771. placement: 'top',
  772. delay: {
  773. show: 500,
  774. hide: 100
  775. }
  776. });
  777. }
  778. });
  779. }
  780. table.treetable({
  781. expandable: true,
  782. onInitialized: function() {
  783. //console.log('onInitialized...');
  784. var node;
  785. // Render loader/spinner while loading
  786. $.ajax({
  787. async: false, // Must be false, otherwise loadBranch happens after showChildren?
  788. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=ROOT_NODES',
  789. })
  790. .done(function(html) {
  791. if ($.trim(html) == '') {
  792. if (node.indenter) {
  793. $(node.indenter).empty();// no children -> remove indenter
  794. }
  795. return false;
  796. }
  797. var rows = $(html).filter("tr");
  798. rows.find(".folder").parents("tr").each(function() {
  799. initializeTableRow.apply(this);
  800. })
  801. table.treetable("loadBranch", node, rows);
  802. });
  803. },
  804. router: function () {
  805. var routes = {
  806. EDIT: function (args) {
  807. var recordID = args;
  808. if (typeof args == 'object') {
  809. recordID = args.shift();
  810. recordID = parseInt(recordID);
  811. }
  812. if (typeof recordID !== 'number' || recordID <= 0) {
  813. // TODO: msg
  814. return false;
  815. }
  816. var cont = jQuery('#<?php echo $this->_htmlID; ?>').parent();
  817. cont.hide();
  818. // remove previous task content
  819. var taskCnt = jQuery('#<?php echo $this->_htmlID; ?>_task');
  820. taskCnt.parent().remove();
  821. taskCnt.remove();
  822. var taskCont = jQuery('<div class="AjaxTreeCont"></div>').insertBefore(cont);
  823. jQuery('<ul class="breadcrumb">' +
  824. '<li><a href="#" onclick="return treeAjaxBackToTree();"><?php echo $this->getLabelHtml(); ?></a> <span class="divider">/</span></li>' +
  825. '<li class="active">Edytuj rekord</li>' +
  826. '</ul>').appendTo(taskCont);
  827. taskCnt = jQuery('<div id="<?php echo $this->_htmlID . '_task'; ?>" class="AjaxTableTaskCnt AjaxTable-loading"></div>').appendTo(taskCont);
  828. jQuery('<span class="loading-info"> loading ...</span>').appendTo(taskCnt);
  829. jQuery.ajax({
  830. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=EDIT&ID=' + recordID,
  831. type: 'GET',
  832. dataType: 'text',
  833. data: '',
  834. async: true,
  835. success: function (data) {
  836. taskCnt.removeClass('AjaxTable-loading');
  837. //console.log('request finished L.<?php echo __LINE__; ?>');
  838. jQuery(data).appendTo(taskCnt);
  839. taskCnt.find('.se_type-date').datepicker({
  840. format: "yyyy-mm-dd"
  841. , language: 'pl'
  842. , todayBtn: "linked"
  843. });
  844. taskCnt.find('.se_type-datetime').parent().datetimepicker({
  845. language: 'pl'
  846. , format: 'yyyy-MM-dd hh:mm'
  847. , weekStart: 1
  848. });
  849. },
  850. error: function (err) {
  851. taskCnt.removeClass('AjaxTable-loading');
  852. //console.log('request error: {0}'.f(err));
  853. }
  854. });
  855. //return false;
  856. },
  857. HIST: function (args) {
  858. var recordID = args;
  859. if (typeof args == 'object') {
  860. recordID = args.shift();
  861. recordID = parseInt(recordID);
  862. }
  863. if (typeof recordID !== 'number' || recordID <= 0) {
  864. // TODO: msg
  865. return false;
  866. }
  867. var cont = jQuery('#<?php echo $this->_htmlID; ?>').parent();
  868. cont.hide();
  869. // remove previous task content
  870. var taskCnt = jQuery('#<?php echo $this->_htmlID; ?>_task');
  871. taskCnt.parent().remove();
  872. taskCnt.remove();
  873. var taskCont = jQuery('<div class="AjaxTableCont"></div>').insertBefore(cont);
  874. jQuery('<ul class="breadcrumb">' +
  875. '<li><a href="#" onclick="return treeAjaxBackToTree();"><?php echo $this->getLabelHtml(); ?></a> <span class="divider">/</span></li>' +
  876. '<li class="active">Historia rekordu</li>' +
  877. '</ul>').appendTo(taskCont);
  878. var taskCnt = jQuery('<div id="<?php echo $this->_htmlID . '_task'; ?>" class="AjaxTableTaskCnt AjaxTable-loading"></div>').appendTo(taskCont);
  879. jQuery('<span class="loading-info"> loading ...</span>').appendTo(taskCnt);
  880. jQuery.ajax({
  881. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=HIST&ID=' + recordID,
  882. type: 'GET',
  883. dataType: 'text',
  884. data: '',
  885. async: true,
  886. success: function (data) {
  887. taskCnt.removeClass('AjaxTable-loading');
  888. //console.log('request finished L.<?php echo __LINE__; ?>');
  889. jQuery(data).appendTo(taskCnt);
  890. },
  891. error: function (err) {
  892. taskCnt.removeClass('AjaxTable-loading');
  893. //console.log('request error: {0}'.f(err));
  894. }
  895. });
  896. //return false;
  897. },
  898. FILES: function tableAjaxFiles(args) {
  899. var recordID = args;
  900. if (typeof args == 'object') {
  901. recordID = args.shift();
  902. recordID = parseInt(recordID);
  903. }
  904. if (typeof recordID !== 'number' || recordID <= 0) {
  905. // TODO: msg
  906. return false;
  907. }
  908. var cont = jQuery('#<?php echo $this->_htmlID; ?>').parent();
  909. cont.hide();
  910. // remove previous task content
  911. var taskCnt = jQuery('#<?php echo $this->_htmlID; ?>_task');
  912. taskCnt.parent().remove();
  913. taskCnt.remove();
  914. var taskCont = jQuery('<div class="AjaxTableCont"></div>').insertBefore(cont);
  915. jQuery('<ul class="breadcrumb">' +
  916. '<li><a href="#" onclick="return treeAjaxBackToTree();"><?php echo $this->getLabelHtml(); ?></a> <span class="divider">/</span></li>' +
  917. '<li class="active">Pliki</li>' +
  918. '</ul>').appendTo(taskCont);
  919. var taskCnt = jQuery('<div id="<?php echo $this->_htmlID . '_task'; ?>" class="AjaxTable-loading"></div>').appendTo(taskCont);
  920. jQuery('<span class="loading-info"> loading ...</span>').appendTo(taskCnt);
  921. jQuery.ajax({
  922. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=FILES&ID=' + recordID,
  923. type: 'GET',
  924. dataType: 'text',
  925. data: '',
  926. async: true,
  927. success: function (data) {
  928. taskCnt.removeClass('AjaxTable-loading');
  929. //console.log('request finished L.<?php echo __LINE__; ?>', data);
  930. jQuery(data).appendTo(taskCnt);
  931. },
  932. error: function (jqXHR, textStatus, errorThrown) {
  933. //console.log('request error:', jqXHR.status, 'txt:', jqXHR.responseText, 'err:', jqXHR);
  934. taskCnt.removeClass('AjaxTable-loading');
  935. var txt = jqXHR.responseText || 'Error';
  936. if (jqXHR.status == 404) {
  937. jQuery('<div class="container"><div class="alert alert-error">' + txt + '</div></div>').appendTo(taskCnt);
  938. } else {
  939. jQuery('<div class="container"><div class="alert alert-error">' + txt + '</div></div>').appendTo(taskCnt);
  940. }
  941. }
  942. });
  943. //return false;
  944. },
  945. CREATE: function tableAjaxCreate() {
  946. var cont = jQuery('#<?php echo $this->_htmlID; ?>').parent();
  947. cont.hide();
  948. // remove previous task content
  949. var taskCnt = jQuery('#<?php echo $this->_htmlID; ?>_task');
  950. taskCnt.parent().remove();
  951. taskCnt.remove();
  952. var taskCont = jQuery('<div class="AjaxTableCont"></div>').insertBefore(cont);
  953. jQuery('<ul class="breadcrumb">' +
  954. '<li><a href="#" onclick="return treeAjaxBackToTree();"><?php echo $this->getLabelHtml(); ?></a> <span class="divider">/</span></li>' +
  955. '<li class="active">Dodaj nowy rekord</li>' +
  956. '</ul>').appendTo(taskCont);
  957. taskCnt = jQuery('<div id="<?php echo $this->_htmlID . '_task'; ?>" class="AjaxTableTaskCnt AjaxTable-loading"></div>').appendTo(taskCont);
  958. jQuery('<span class="loading-info"> loading ...</span>').appendTo(taskCnt);
  959. var reqData = {};
  960. var forceFilterInit = <?php echo json_encode($forceFilterInit);// TODO: read from TableAjax ?>;
  961. if (forceFilterInit) {
  962. $.map(forceFilterInit, function (fltrProps, fltr) {
  963. reqData['ff_' + fltr] = fltrProps;
  964. });
  965. }
  966. jQuery.ajax({
  967. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=CREATE',
  968. type: 'GET',
  969. dataType: 'text',
  970. data: reqData,
  971. async: true,
  972. success: function (data) {
  973. taskCnt.removeClass('AjaxTable-loading');
  974. //console.log('request finished L.<?php echo __LINE__; ?>');
  975. jQuery(data).appendTo(taskCnt);
  976. taskCnt.find('.se_type-date').datepicker({
  977. format: "yyyy-mm-dd"
  978. , language: 'pl'
  979. , todayBtn: "linked"
  980. });
  981. taskCnt.find('.se_type-datetime').parent().datetimepicker({
  982. language: 'pl'
  983. , format: 'yyyy-MM-dd hh:mm'
  984. , weekStart: 1
  985. });
  986. },
  987. error: function (err) {
  988. taskCnt.removeClass('AjaxTable-loading');
  989. //console.log('request error: {0}'.f(err));
  990. }
  991. });
  992. //return false;
  993. }
  994. };
  995. var routePath = location.hash;
  996. //console.log('location.hash: ' + routePath);
  997. if (location.hash == '' || location.hash == '#') {
  998. return false;
  999. }
  1000. if (routePath.charAt(0) == '#') {
  1001. routePath = routePath.substr(1);
  1002. }
  1003. //console.log('routePath: ' + routePath);
  1004. var parts = routePath.split('/');
  1005. var task = parts.shift();
  1006. //console.log('task(' + task + ') parts:');
  1007. //console.log(parts);
  1008. if (task in routes && typeof routes[task] == 'function') {
  1009. routes[task](parts);
  1010. } else {
  1011. return false;
  1012. }
  1013. },
  1014. onNodeCollapse: function() {
  1015. var node = this;
  1016. //table.treetable("unloadBranch", node);// when unloadBranch childrens are only hidden and unnecessary ajax call on expand
  1017. },
  1018. onNodeExpand: function() {
  1019. var node = this;
  1020. // prevent ajax call if childrens are only hidden
  1021. if (node.children && node.children.length > 0) {
  1022. return;
  1023. }
  1024. // Render loader/spinner while loading
  1025. $.ajax({
  1026. async: false, // Must be false, otherwise loadBranch happens after showChildren?
  1027. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=CHILDREN&ID=' + node.id,
  1028. })
  1029. .done(function(html) {
  1030. if ($.trim(html) == '') {
  1031. $(node.indenter).empty();// no children -> remove indenter
  1032. return false;
  1033. }
  1034. var rows = $(html).filter("tr");
  1035. rows.find(".folder").parents("tr").each(function() {
  1036. initializeTableRow.apply(this);
  1037. })
  1038. table.treetable("loadBranch", node, rows);
  1039. });
  1040. }
  1041. });
  1042. jQuery.fx.interval = 100;// performance tip
  1043. var tblBody = $("#<?php echo $this->_htmlID; ?>").find("tbody");
  1044. // treetable("sortBranch", parentId, columnOrFunction)
  1045. tblBody.sortable({
  1046. //connectWith: "#<?php echo $this->_htmlID; ?> tbody",
  1047. handle: ".sort-handler",
  1048. items: "tr:not(.ui-state-disabled)",
  1049. activate: function(e, ui) {// == start
  1050. //tblBody.find('.ui-state-default').addClass('ui-state-disabled');
  1051. },
  1052. start: function(e, ui) {
  1053. //console.log('start: ttId(',ui.item.data('ttId'),') ttParentId(',ui.item.data('ttParentId'),') e:', e, 'ui:', ui);
  1054. // ui.data = { ttId: "118" ttParentId: "499" }
  1055. // TODO: set class ui-state-disabled to all tr which is not under ui.data('ttParentId')
  1056. },
  1057. stop: function(e, ui) {// sort finish
  1058. },
  1059. update: function(e, ui) {// when position change - dom update
  1060. //console.log('update: ttId(',ui.item.data('ttId'),') ttParentId(',ui.item.data('ttParentId'),') e:', e, 'ui:', ui);
  1061. var prev = ui.item.next('tr'),
  1062. next = ui.item.prev('tr'),
  1063. allowMode = false,
  1064. reqData = {};
  1065. //console.log('ui.item next', prev.data('ttId'), 'pId:', prev.data('ttParentId'));
  1066. //console.log('ui.item prev', next.data('ttId'), 'pId:', next.data('ttParentId'));
  1067. if (prev && prev.data('ttParentId') == ui.item.data('ttParentId')) {
  1068. allowMode = true;
  1069. reqData = {after: prev.data('ttId')}
  1070. }
  1071. if (next && next.data('ttParentId') == ui.item.data('ttParentId')) {
  1072. allowMode = true;
  1073. reqData = {before: next.data('ttId')}
  1074. }
  1075. if (allowMode) {// && confirm("Przenieść rekord " + ui.item.data('ttId') + "?")) {
  1076. $.ajax({
  1077. data: reqData,
  1078. type: "POST",
  1079. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=MOVE_SORT&ID=' + ui.item.data('ttId'),
  1080. })
  1081. .done(function(data, textStatus, jqXHR){
  1082. //console.log('move-sort-info: ', data);
  1083. jQuery.notify('Przeniesienie udane', 'success');
  1084. })
  1085. .fail(function(jqXHR){// jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});
  1086. var txt = jqXHR.responseText || 'Error';
  1087. if (jqXHR.status == 404) {
  1088. jQuery.notify(jqXHR.responseText, 'error');
  1089. } else {
  1090. jQuery.notify(jqXHR.responseText, 'warn');
  1091. }
  1092. });
  1093. } else {
  1094. if (!allowMode) {
  1095. var notAllowMsg = 'Błąd: nie można przenieść rekordu';
  1096. jQuery.notify(notAllowMsg, 'error');
  1097. }
  1098. $(this).sortable("cancel");
  1099. }
  1100. }
  1101. // , helper: function(e, ui) {// Return a helper with preserved width of cells
  1102. // ui.children().each(function() {
  1103. // $(this).width($(this).width());
  1104. // });
  1105. // return ui;
  1106. // }
  1107. }).disableSelection();
  1108. });
  1109. </script>
  1110. <?php
  1111. $out = ob_get_contents();
  1112. ob_end_clean();
  1113. return $out;
  1114. }
  1115. private function sendAjaxChildren($id, $args) {
  1116. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1117. header("Content-type: text/html");
  1118. $out = '';
  1119. $params = array();
  1120. $params['order_by'] = 'SORT_PRIO';
  1121. $nodes = $this->_dataSource->getTreeNodes($id, $params);
  1122. if (!empty($nodes)) {
  1123. ob_start();
  1124. ?>
  1125. <?php foreach ($nodes as $node) : ?>
  1126. <?php $this->renderNode($node); ?>
  1127. <?php endforeach; ?>
  1128. <?php
  1129. $out = ob_get_contents();
  1130. ob_end_clean();
  1131. }
  1132. echo $out;
  1133. exit;
  1134. }
  1135. private function sendAjaxMove($id, $p_id, $args) {
  1136. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1137. header("Content-type: text/html");
  1138. $moved = $this->_dataSource->moveTreeNode($id, $p_id);
  1139. if ($moved) {
  1140. $node = $this->_dataSource->getTreeNode($id);
  1141. $this->renderNode($node);
  1142. } else {
  1143. header("HTTP/1.0 404 Not Found");
  1144. echo "Nie udało się przenieść {$id} pod {$p_id}";
  1145. }
  1146. exit;
  1147. }
  1148. private function sendAjaxNode($id, $args) {
  1149. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1150. header("Content-type: text/html");
  1151. $node = $this->_dataSource->getTreeNode($id);
  1152. if ($node) {
  1153. $this->renderNode($node);
  1154. } else {
  1155. header("HTTP/1.0 404 Not Found");
  1156. echo "Rekord {$id} nie istnieje";
  1157. }
  1158. exit;
  1159. }
  1160. private function sendAjaxMoveSort($id, $beforeId, $afterId, $args) {
  1161. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1162. header("Content-type: text/html");
  1163. $moved = false;
  1164. if ($beforeId > 0) {
  1165. $moved = $this->_dataSource->moveTreeNodeSortBefore($id, $beforeId);
  1166. } else if ($afterId > 0) {
  1167. $moved = $this->_dataSource->moveTreeNodeSortAfter($id, $afterId);
  1168. }
  1169. if ($moved) {
  1170. $node = $this->_dataSource->getTreeNode($id);
  1171. $this->renderNode($node);
  1172. } else {
  1173. header("HTTP/1.0 404 Not Found");
  1174. echo "Nie udało się przenieść {$id} pod {$p_id}";
  1175. }
  1176. exit;
  1177. }
  1178. /**
  1179. * ajax url: &_task=EDIT_INLINE
  1180. * @param $rowID - $_GET['ID']
  1181. * @param $fieldName - $_GET['col']
  1182. */
  1183. private function sendAjaxEditInline($rowID, $fieldName, $args) {
  1184. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1185. header("Content-type: text/plain");
  1186. die('TODO: L.' . __LINE__);
  1187. $fieldID = $this->_acl->getFieldIdByName($fieldName);
  1188. if (!$fieldID) {
  1189. echo "404: No field by name ({$fieldName})";
  1190. exit;
  1191. }
  1192. if ($DBG) echo "fieldID: {$fieldID}\n";
  1193. $row = $this->_dataSource->getItem($rowID);
  1194. if (!$row) {
  1195. echo "404: No item ID({$rowID})";
  1196. exit;
  1197. }
  1198. if (!$this->_acl->isAllowed($fieldID, 'R', $row)) {
  1199. if ($DBG) echo " R not allowed\n";
  1200. } else {
  1201. if ($DBG) echo " R allowed\n";
  1202. }
  1203. if (!$this->_acl->isAllowed($fieldID, 'W', $row)) {
  1204. if ($DBG) echo " W not allowed\n";
  1205. } else {
  1206. if ($DBG) echo " W allowed\n";
  1207. }
  1208. $fieldVal = '';
  1209. if ($this->_acl->isAllowed($fieldID, 'R', $row)) {
  1210. $fieldVal = V::get($fieldName, $fieldVal, $row);
  1211. }
  1212. $fieldVal = V::get("f{$fieldID}", $fieldVal, $_POST);
  1213. $vCol = $this->_acl->getField($fieldID);
  1214. $vCol['label'] = (!empty($vCol['label']))? $vCol['label'] : $vCol['name'];
  1215. $tsValues = array();
  1216. Lib::loadClass('Typespecial');
  1217. $typeSpecial = Typespecial::getInstance($fieldID, $vCol['name']);
  1218. if ($typeSpecial) {
  1219. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">Typespecial('.$fieldID.') (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($typeSpecial);echo'</pre>';}
  1220. $specialValues = $typeSpecial->getEditSelectedValuesByIds($this->_zasobID, $row->ID, $fieldName, V::get($fieldName, $fieldVal, $row));
  1221. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">Typespecial('.$fieldID.') specialValues (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($specialValues);echo'</pre>';}
  1222. if (!empty($specialValues)) {
  1223. $tsValues[$row->ID] = implode('<br>', $specialValues);
  1224. }
  1225. }
  1226. ?>
  1227. <label for="<?php echo "f{$fieldID}"; ?>" class="AjaxTableEdit-label">
  1228. <strong title="<?php echo "[{$fieldID}] {$fieldName}"; ?>"><?php echo "{$vCol['label']}"; ?></strong>
  1229. <?php if (!empty($vCol['opis'])) : ?>
  1230. <em><?php echo $vCol['opis']; ?></em>
  1231. <?php endif; ?>
  1232. </label>
  1233. <?php
  1234. $fieldParams = array('widthClass'=>'inside-modal', 'maxGrid'=>6);
  1235. if (!empty($tsValues[$row->ID])) {
  1236. $fieldParams['typespecialValue'] = $tsValues[$row->ID];
  1237. }
  1238. $vDefault = $this->_dataSource->getColDefault($fieldName);
  1239. if (!empty($vDefault)) {
  1240. $fieldParams['default'] = $vDefault;
  1241. }
  1242. echo $this->_acl->showFormItem('W', $fieldID, "f{$fieldID}", $fieldVal, $fieldParams, $row);
  1243. if ($typeSpecial) {
  1244. echo '<p style="padding:100px 0;"></p>';
  1245. }
  1246. exit;
  1247. }
  1248. private function sendAjaxEditInlineSave($rowID, $fieldName, $args) {
  1249. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1250. sleep(1);// TODO: RMME DBG loading
  1251. die('TODO: L.' . __LINE__);
  1252. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">TODO: save ID(' . $id . ') (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($args);echo'</pre>';}
  1253. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">acl (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_acl);echo'</pre>';}
  1254. $dbID = $this->_acl->getDB();
  1255. $db = DB::getDB($dbID);
  1256. if (!$db) {
  1257. header('HTTP/1.0 406 Not Acceptable');
  1258. exit;
  1259. }
  1260. $tblName = $this->_acl->getName();
  1261. $fieldID = $this->_acl->getFieldIdByName($fieldName);
  1262. if (!$fieldID) {
  1263. header('HTTP/1.0 404 Not Found');
  1264. echo "404: No field by name ({$fieldName})";
  1265. exit;
  1266. }
  1267. $row = $this->_dataSource->getItem($rowID);
  1268. if (!$row) {
  1269. header('HTTP/1.0 404 Not Found');
  1270. echo "404: No item ID({$rowID})";
  1271. exit;
  1272. }
  1273. if (!$this->_acl->isAllowed($fieldID, 'W', $row)) {
  1274. header('HTTP/1.0 403 Forbidden');
  1275. echo "403: field not allowed to Write ({$fieldName})";
  1276. exit;
  1277. } else {
  1278. if ($DBG) echo " Write allowed\n";
  1279. }
  1280. $sqlObj = new stdClass();
  1281. if (array_key_exists("f{$fieldID}", $args)) {
  1282. $sqlObj->{$fieldName} = $args["f{$fieldID}"];
  1283. if (empty($args["f{$fieldID}"]) && strlen($args["f{$fieldID}"]) == 0) {// fix bug in input type date and value="0000-00-00"
  1284. $sqlObj->{$fieldName} = $this->_acl->fixEmptyValueFromUser($fieldID);
  1285. }
  1286. }
  1287. else {
  1288. if ($DBG) echo " TODO: field value not set\n";
  1289. }
  1290. $sqlObj->ID = $rowID;
  1291. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">E('.$tblName.') (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sqlObj);echo'</pre>';}
  1292. $ret = $db->UPDATE_OBJ($tblName, $sqlObj);
  1293. if ($ret > 0) {
  1294. echo '<div class="alert alert-success">';
  1295. echo "Rekord zapisany pomyślnie";//"Record saved successfully";
  1296. echo '</div>';
  1297. } else if ($ret == 0) {
  1298. echo '<div class="alert alert-info">';
  1299. echo "Nie wprowadzono żadnych zmian";
  1300. if ($db->has_errors()) {
  1301. //echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">db errors: (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($db->get_errors());echo'</pre>';
  1302. }
  1303. echo '</div>';
  1304. } else {
  1305. echo '<div class="alert alert-error">';
  1306. echo '<h4>' . "Wystąpiły błędy!" . '</h4>';
  1307. if ($db->has_errors()) {
  1308. $errors = $db->get_errors();
  1309. echo implode('<br>', $errors);
  1310. }
  1311. echo '</div>';
  1312. }
  1313. exit;
  1314. }
  1315. private function sendAjaxEdit($id, $args) {
  1316. header("Content-type: text/plain");
  1317. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1318. $cols = array();
  1319. $record = $this->_dataSource->getItem($id);
  1320. if (!$this->_acl->canWriteRecord($record) && !$this->_acl->hasPermSuperWrite()) {
  1321. echo '<div class="alert alert-error">';
  1322. echo "Brak dostępu do rekordu";// TODO: more info - reason
  1323. echo '</div>';
  1324. return;
  1325. }
  1326. $fieldsList = $this->_acl->getFields();
  1327. foreach ($fieldsList as $kID => $vCol) {
  1328. if ($vCol['name'] == 'ID') {
  1329. unset($fieldsList[$kID]);
  1330. continue;
  1331. }
  1332. $cols[$kID] = '';
  1333. if ($this->_acl->isAllowed($kID, 'R', $record)) {
  1334. $cols[$kID] = V::get($vCol['name'], '', $record);
  1335. }
  1336. $cols[$kID] = V::get("f{$kID}", $cols[$kID], $_POST);
  1337. $fieldsList[$kID]['label'] = (!empty($vCol['label']))? $vCol['label'] : str_replace('_', ' ', $vCol['name']);
  1338. }
  1339. $tsValues = array();
  1340. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">fieldsList (F.' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($fieldsList);echo'</pre>';}
  1341. if (!empty($fieldsList)) {
  1342. Lib::loadClass('Typespecial');
  1343. foreach ($fieldsList as $vColID => $vCol) {
  1344. $typeSpecial = Typespecial::getInstance($vColID, $vCol['name']);
  1345. if ($typeSpecial) {
  1346. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">Typespecial('.$vColID.') (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($typeSpecial);echo'</pre>';}
  1347. $colValue = V::get($vCol['name'], '', $record);
  1348. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">V::get('.$vCol['name'].', "", $record) (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($colValue);echo'</pre>';}
  1349. $specialValues = $typeSpecial->getEditSelectedValuesByIds($this->_zasobID, $record->ID, $vCol['name'], $colValue);
  1350. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">Typespecial('.$vColID.') specialValues (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($specialValues);echo'</pre>';}
  1351. if (!empty($specialValues)) {
  1352. $tsValues[$vColID] = implode('<br>', $specialValues);
  1353. }
  1354. }
  1355. }
  1356. }
  1357. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">tsValues (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($tsValues);echo'</pre>';}
  1358. $rowFunctionsOut = '';// TODO: $this->_showRowFunctions($record->ID, array('edit', 'cp'), true);
  1359. ?>
  1360. <div class="container AjaxFrmHorizontalEdit">
  1361. <form class="form-horizontal" action="" method="post" id="EDIT_FRM_<?php echo $this->_htmlID; ?>">
  1362. <fieldset>
  1363. <legend>Edycja rekordu Nr <?php echo $record->ID; ?><span class="pull-right valign-btns-bottom"><?php echo $rowFunctionsOut; ?></span></legend>
  1364. <?php $tabindex = 0; foreach ($fieldsList as $kID => $vCol) : ?>
  1365. <?php if ($this->_acl->isAllowed($kID, 'W', $record)) : ?>
  1366. <div class="control-group">
  1367. <label class="control-label" for="<?php echo "f{$kID}"; ?>"><?php echo $vCol['label']; ?>
  1368. <i class="icon-info-sign frm-help" data-toggle="popover" data-trigger="hover" title="" data-content="<?php echo htmlspecialchars($vCol['opis']); ?>" data-original-title="<?php echo "[{$kID}] {$vCol['name']}"; ?>"></i>
  1369. </label>
  1370. <div class="controls">
  1371. <?php
  1372. $fieldParams = array('appendBack'=>true, 'tabindex'=>(++$tabindex), 'maxGrid'=>8);
  1373. if (!empty($tsValues[$kID])) {
  1374. $fieldParams['typespecialValue'] = $tsValues[$kID];
  1375. }
  1376. echo $this->_acl->showFormItem('W', $kID, "f{$kID}", $cols[$kID], $fieldParams, $record);
  1377. ?>
  1378. </div>
  1379. </div>
  1380. <?php elseif ($this->_acl->isAllowed($kID, 'R', $record)) : ?>
  1381. <div class="control-group">
  1382. <label class="control-label" for="<?php echo "f{$kID}"; ?>"><?php echo $vCol['label']; ?>
  1383. <i class="icon-info-sign frm-help" data-toggle="popover" data-trigger="hover" title="" data-content="<?php echo htmlspecialchars($vCol['opis']); ?>" data-original-title="<?php echo "[{$kID}] {$vCol['name']}"; ?>"></i>
  1384. </label>
  1385. <div class="controls">
  1386. <p style="margin-top:5px;">
  1387. <?php
  1388. //echo $this->_acl->showFormItem('R', $kID, "f{$kID}", $cols[$kID], array('appendBack'=>true), $record);
  1389. if (!empty($tsValues[$kID])) {
  1390. echo $tsValues[$kID];
  1391. } else if (!empty($record->{$vCol['name']})) {
  1392. echo $record->{$vCol['name']};
  1393. }
  1394. ?>
  1395. </p>
  1396. </div>
  1397. </div>
  1398. <?php endif; ?>
  1399. <?php endforeach; ?>
  1400. <div class="control-group">
  1401. <div class="controls">
  1402. <button type="submit" class="btn btn-primary" tabindex="<?php echo (++$tabindex); ?>">Zapisz</button>
  1403. </div>
  1404. </div>
  1405. </fieldset>
  1406. </form>
  1407. <p style="padding:100px 0;"></p>
  1408. </div>
  1409. <script>
  1410. jQuery(document).ready(function(){
  1411. jQuery('textarea').autosize();
  1412. jQuery('.frm-help').popover({trigger:'hover'});
  1413. jQuery('#EDIT_FRM_<?php echo $this->_htmlID; ?>').on('submit', function(){
  1414. var data = jQuery(this).serialize();
  1415. // TODO: change Edit btn to return to edit record with fields -> show form
  1416. var taskCont = jQuery('#<?php echo $this->_htmlID; ?>_task').parent();
  1417. //taskCont.empty();
  1418. taskCont.children().fadeOut('slow');
  1419. var alertCntWrap = jQuery('<div class="AjaxTableAlert AjaxTable-loading"></div>').prependTo(taskCont)
  1420. , alertCnt = jQuery('<div class="container"></div>').prependTo(alertCntWrap);
  1421. jQuery('<div class="alert alert-error"><div style="padding:0 0 0 20px; background:url(./icon/loading.gif) no-repeat left top;"> zapisywanie ... </div></div>').appendTo(alertCnt);
  1422. jQuery.ajax({
  1423. url: 'index-ajax.php?_zasobID=<?php echo $this->_zasobID; ?>&_cls=<?php echo __CLASS__; ?>&_hash=<?php echo $this->_htmlID; ?>&_task=EDIT_SAVE&ID=<?php echo $record->ID; ?>',
  1424. type: 'POST',
  1425. dataType: 'text',
  1426. data: data,
  1427. async: true,
  1428. success: function (data) {
  1429. alertCntWrap.removeClass('AjaxTable-loading');
  1430. //console.log('request finished L.<?php echo __LINE__; ?>');
  1431. alertCnt.empty();
  1432. var out = '';
  1433. out += data;
  1434. out += '<div class="breadcrumb">' +
  1435. ' <a href="#" onclick="return treeAjaxBackToTree();" class="btn btn-link btn-small"> <i class="icon-arrow-left"></i> Wróć do tabeli <?php echo $this->getLabelHtml(); ?></a>' +
  1436. '<span class="divider">/</span>' +
  1437. ' <a href="#EDIT/<?php echo $id; ?>/' + Math.random(1).toString().substr(2) + '" class="btn btn-link btn-small"> <i class="icon-pencil"></i> Edytuj rekord <?php echo $id; ?></a>' +
  1438. '</div>';
  1439. jQuery(out).appendTo(alertCnt);
  1440. // update node data in tree
  1441. $("#<?php echo $this->_htmlID; ?>").treetable("updateNode", <?php echo $id; ?>);
  1442. },
  1443. error: function (jhr, textStatus, errorThrown) {
  1444. var errorTxt = jhr.responseText || 'Error';
  1445. alertCntWrap.removeClass('AjaxTable-loading');
  1446. //console.log('Request Error: {0}: {1}'.f(textStatus, errorThrown));
  1447. alertCnt.empty();
  1448. jQuery(errorTxt).appendTo(alertCnt);
  1449. var errLinks = jQuery('<div class="breadcrumb"></div>').appendTo(alertCnt);
  1450. jQuery('<a href="#" onclick="return treeAjaxBackToTree();"> <i class="icon-arrow-left"></i> Wróć do tabeli <?php echo $this->getLabelHtml(); ?></a>').appendTo(errLinks);
  1451. var backToEditBtn = jQuery('<a href="#EDIT/<?php echo $id; ?>/' + Math.random(1).toString().substr(2) + '" class="btn btn-link btn-small"> <i class="icon-pencil"></i> Popraw dane <?php echo $id; ?></a>').appendTo(errLinks);
  1452. backToEditBtn.on('click', function(){
  1453. alertCnt.remove();
  1454. taskCont.children().fadeIn('slow');
  1455. return false;
  1456. });
  1457. }
  1458. });
  1459. return false;
  1460. });
  1461. jQuery('#EDIT_FRM_<?php echo $this->_htmlID; ?>').find('.show-last-value input').on('input', function(e) {
  1462. var input, btn;
  1463. input = jQuery(e.target);
  1464. btn = input.next();
  1465. if (btn.is('button')) {
  1466. if (btn.attr('title') != input.val()) {
  1467. btn.show();
  1468. } else {
  1469. btn.hide();
  1470. }
  1471. }
  1472. });
  1473. jQuery('#EDIT_FRM_<?php echo $this->_htmlID; ?>').find('.show-last-value button.btn-appendBack').on('click', function(e) {
  1474. var input, btn;
  1475. btn = jQuery(e.target);
  1476. input = btn.prev();
  1477. if (input.is('input')) {
  1478. if (btn.attr('title') != input.val()) {
  1479. input.val(btn.attr('title'));
  1480. btn.hide();
  1481. }
  1482. }
  1483. });
  1484. });
  1485. </script>
  1486. <?php
  1487. exit;
  1488. }
  1489. private function sendAjaxEditSave($id, $args) {
  1490. $DBG = ('1' == V::get('DBG', '', $_REQUEST));
  1491. sleep(1);// TODO: RMME DBG loading
  1492. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">TODO: save ID(' . $id . ') (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($args);echo'</pre>';}
  1493. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">acl (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_acl);echo'</pre>';}
  1494. $dbID = $this->_acl->getDB();
  1495. $db = DB::getDB($dbID);
  1496. if (!$db) {
  1497. header('HTTP/1.0 406 Not Acceptable');
  1498. exit;
  1499. }
  1500. $tblName = $this->_acl->getName();
  1501. $record = $db->get_by_id($tblName, $id);
  1502. if (!$this->_acl->canWriteRecord($record) && !$this->_acl->hasPermSuperWrite()) {
  1503. echo '<div class="alert alert-error">';
  1504. echo "Brak dostępu do rekordu";// TODO: more info - reason
  1505. echo '</div>';
  1506. }
  1507. $sqlObj = new stdClass();
  1508. $fields = $this->_acl->getFields();
  1509. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">fields (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($fields);echo'</pre>';}
  1510. foreach ($fields as $kID => $vField) {
  1511. if (!$this->_acl->isAllowed($kID, 'W', $record)) {
  1512. continue;
  1513. }
  1514. if (array_key_exists("f{$kID}", $args)) {
  1515. $sqlObj->{$vField['name']} = $args["f{$kID}"];
  1516. if (empty($args["f{$kID}"]) && strlen($args["f{$kID}"]) == 0) {// fix bug in input type date and value="0000-00-00"
  1517. $sqlObj->{$vField['name']} = $this->_acl->fixEmptyValueFromUser($kID);
  1518. }
  1519. }
  1520. }
  1521. $sqlObj->ID = $id;
  1522. if($DBG){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;"> (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sqlObj);echo'</pre>';}
  1523. $ret = $db->UPDATE_OBJ($tblName, $sqlObj);
  1524. if ($ret > 0) {
  1525. echo '<div class="alert alert-success">';
  1526. echo "Rekord zapisany pomyślnie";//"Record saved successfully";
  1527. echo '</div>';
  1528. } else if ($ret == 0) {
  1529. echo '<div class="alert alert-info">';
  1530. echo "Nie wprowadzono żadnych zmian";
  1531. echo '</div>';
  1532. } else {
  1533. header('HTTP/1.0 404 Not Found');
  1534. echo '<div class="alert alert-error">';
  1535. echo '<h4>' . "Wystąpiły błędy!" . '</h4>';
  1536. if ($db->has_errors()) {
  1537. $errors = $db->get_errors();
  1538. echo implode('<br>', $errors);
  1539. }
  1540. echo '</div>';
  1541. }
  1542. exit;
  1543. }
  1544. public function ajaxTask($task) {
  1545. switch ($task) {
  1546. case 'CHILDREN': {
  1547. $id = V::get('ID', 0, $_REQUEST, 'int');
  1548. if ($id > 0) {
  1549. $this->sendAjaxChildren($id, $_REQUEST);
  1550. } else {
  1551. echo '404';
  1552. }
  1553. break;
  1554. }
  1555. case 'ROOT_NODES': {
  1556. $this->sendAjaxChildren(0, $_REQUEST);
  1557. break;
  1558. }
  1559. case 'ADD': {
  1560. echo 'TODO: L.' . __LINE__;
  1561. break;
  1562. }
  1563. case 'MOVE': {
  1564. $id = V::get('ID', 0, $_REQUEST, 'int');
  1565. $p_id = V::get('MOVE_TO_ID', 0, $_REQUEST, 'int');
  1566. if ($id > 0 && $p_id > 0) {
  1567. $this->sendAjaxMove($id, $p_id, $_REQUEST);
  1568. } else {
  1569. header("HTTP/1.0 404 Not Found");
  1570. echo 'Błędne parametry';
  1571. exit;
  1572. }
  1573. break;
  1574. }
  1575. case 'MOVE_SORT': {
  1576. $id = V::get('ID', 0, $_REQUEST, 'int');
  1577. $beforeId = V::get('before', 0, $_REQUEST, 'int');
  1578. $afterId = V::get('after', 0, $_REQUEST, 'int');
  1579. if ($id > 0 && ($beforeId > 0 || $afterId > 0)) {
  1580. $this->sendAjaxMoveSort($id, $beforeId, $afterId, $_REQUEST);
  1581. } else {
  1582. header("HTTP/1.0 404 Not Found");
  1583. echo 'Błędne parametry';
  1584. exit;
  1585. }
  1586. break;
  1587. }
  1588. case 'NODE': {
  1589. $id = V::get('ID', 0, $_REQUEST, 'int');
  1590. if ($id > 0) {
  1591. $this->sendAjaxNode($id, $_REQUEST);
  1592. } else {
  1593. echo '404';
  1594. }
  1595. break;
  1596. }
  1597. case 'EDIT': { // &_task=EDIT&ID=510
  1598. $id = V::get('ID', 0, $_REQUEST, 'int');
  1599. if ($id > 0) {
  1600. $this->sendAjaxEdit($id, $_REQUEST);
  1601. } else {
  1602. echo '404';
  1603. }
  1604. break;
  1605. }
  1606. case 'EDIT_SAVE': {
  1607. $id = V::get('ID', 0, $_REQUEST, 'int');
  1608. if ($id > 0) {
  1609. $this->sendAjaxEditSave($id, $_REQUEST);
  1610. } else {
  1611. echo '404';
  1612. }
  1613. break;
  1614. }
  1615. case 'EDIT_INLINE': {
  1616. $id = V::get('ID', 0, $_REQUEST, 'int');
  1617. $col = V::get('col', '', $_REQUEST);
  1618. if ($id > 0 && !empty($col)) {
  1619. $this->sendAjaxEditInline($id, $col, $_REQUEST);
  1620. } else {
  1621. echo '404';
  1622. }
  1623. break;
  1624. }
  1625. case 'EDIT_INLINE_SAVE': {
  1626. $id = V::get('ID', 0, $_REQUEST, 'int');
  1627. $col = V::get('col', '', $_REQUEST);
  1628. if ($id > 0 && !empty($col)) {
  1629. $this->sendAjaxEditInlineSave($id, $col, $_REQUEST);
  1630. } else {
  1631. echo '404';
  1632. }
  1633. break;
  1634. }
  1635. default:
  1636. //$this->sendAjaxData($_REQUEST);
  1637. }
  1638. }
  1639. }