TreeAjax.php 59 KB

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