2016-10-22 14:57:10 +00:00
/* vim: set expandtab sw=4 ts=4 sts=4: */
/ * *
* Create advanced table ( resize , reorder , and show / hide columns ; and also grid editing ) .
* This function is designed mainly for table DOM generated from browsing a table in the database .
* For using this function in other table DOM , you may need to :
* - add "draggable" class in the table header < th > , in order to make it resizable , sortable or hidable
* - have at least one non - "draggable" header in the table DOM for placing column visibility drop - down arrow
* - pass the value "false" for the parameter "enableGridEdit"
* - adjust other parameter value , to select which features that will be enabled
*
* @ param t the table DOM element
* @ param enableResize Optional , if false , column resizing feature will be disabled
* @ param enableReorder Optional , if false , column reordering feature will be disabled
* @ param enableVisib Optional , if false , show / hide column feature will be disabled
* @ param enableGridEdit Optional , if false , grid editing feature will be disabled
* /
function PMA _makegrid ( t , enableResize , enableReorder , enableVisib , enableGridEdit ) {
var g = {
/ * * * * * * * * * * *
* Constant
* * * * * * * * * * * /
minColWidth : 15 ,
/ * * * * * * * * * * *
* Variables , assigned with default value , changed later
* * * * * * * * * * * /
actionSpan : 5 , // number of colspan in Actions header in a table
tableCreateTime : null , // table creation time, used for saving column order and visibility to server, only available in "Browse tab"
// Column reordering variables
colOrder : [ ] , // array of column order
// Column visibility variables
colVisib : [ ] , // array of column visibility
showAllColText : '' , // string, text for "show all" button under column visibility list
visibleHeadersCount : 0 , // number of visible data headers
// Table hint variables
reorderHint : '' , // string, hint for column reordering
sortHint : '' , // string, hint for column sorting
markHint : '' , // string, hint for column marking
copyHint : '' , // string, hint for copy column name
showReorderHint : false ,
showSortHint : false ,
showMarkHint : false ,
// Grid editing
isCellEditActive : false , // true if current focus is in edit cell
isEditCellTextEditable : false , // true if current edit cell is editable in the text input box (not textarea)
currentEditCell : null , // reference to <td> that currently being edited
cellEditHint : '' , // hint shown when doing grid edit
gotoLinkText : '' , // "Go to link" text
wasEditedCellNull : false , // true if last value of the edited cell was NULL
maxTruncatedLen : 0 , // number of characters that can be displayed in a cell
saveCellsAtOnce : false , // $cfg[saveCellsAtOnce]
isCellEdited : false , // true if at least one cell has been edited
saveCellWarning : '' , // string, warning text when user want to leave a page with unsaved edited data
lastXHR : null , // last XHR object used in AJAX request
isSaving : false , // true when currently saving edited data, used to handle double posting caused by pressing ENTER in grid edit text box in Chrome browser
alertNonUnique : '' , // string, alert shown when saving edited nonunique table
// Common hidden inputs
token : null ,
server : null ,
db : null ,
table : null ,
/ * * * * * * * * * * * *
* Functions
* * * * * * * * * * * * /
/ * *
* Start to resize column . Called when clicking on column separator .
*
* @ param e event
* @ param obj dragged div object
* /
2017-04-20 10:55:30 +00:00
dragStartRsz : function ( e , obj ) {
2016-10-22 14:57:10 +00:00
var n = $ ( g . cRsz ) . find ( 'div' ) . index ( obj ) ; // get the index of separator (i.e., column index)
$ ( obj ) . addClass ( 'colborder_active' ) ;
g . colRsz = {
x0 : e . pageX ,
n : n ,
obj : obj ,
objLeft : $ ( obj ) . position ( ) . left ,
objWidth : $ ( g . t ) . find ( 'th.draggable:visible:eq(' + n + ') span' ) . outerWidth ( )
} ;
$ ( document . body ) . css ( 'cursor' , 'col-resize' ) . noSelect ( ) ;
if ( g . isCellEditActive ) {
g . hideEditCell ( ) ;
}
} ,
/ * *
* Start to reorder column . Called when clicking on table header .
*
* @ param e event
* @ param obj table header object
* /
2017-04-20 10:55:30 +00:00
dragStartReorder : function ( e , obj ) {
2016-10-22 14:57:10 +00:00
// prepare the cCpy (column copy) and cPointer (column pointer) from the dragged column
$ ( g . cCpy ) . text ( $ ( obj ) . text ( ) ) ;
var objPos = $ ( obj ) . position ( ) ;
$ ( g . cCpy ) . css ( {
top : objPos . top + 20 ,
left : objPos . left ,
height : $ ( obj ) . height ( ) ,
width : $ ( obj ) . width ( )
} ) ;
$ ( g . cPointer ) . css ( {
top : objPos . top
} ) ;
// get the column index, zero-based
var n = g . getHeaderIdx ( obj ) ;
g . colReorder = {
x0 : e . pageX ,
y0 : e . pageY ,
n : n ,
newn : n ,
obj : obj ,
objTop : objPos . top ,
objLeft : objPos . left
} ;
$ ( document . body ) . css ( 'cursor' , 'move' ) . noSelect ( ) ;
if ( g . isCellEditActive ) {
g . hideEditCell ( ) ;
}
} ,
/ * *
* Handle mousemove event when dragging .
*
* @ param e event
* /
2017-04-20 10:55:30 +00:00
dragMove : function ( e ) {
2016-10-22 14:57:10 +00:00
if ( g . colRsz ) {
var dx = e . pageX - g . colRsz . x0 ;
if ( g . colRsz . objWidth + dx > g . minColWidth ) {
$ ( g . colRsz . obj ) . css ( 'left' , g . colRsz . objLeft + dx + 'px' ) ;
}
} else if ( g . colReorder ) {
// dragged column animation
var dx = e . pageX - g . colReorder . x0 ;
$ ( g . cCpy )
. css ( 'left' , g . colReorder . objLeft + dx )
. show ( ) ;
// pointer animation
var hoveredCol = g . getHoveredCol ( e ) ;
if ( hoveredCol ) {
var newn = g . getHeaderIdx ( hoveredCol ) ;
g . colReorder . newn = newn ;
if ( newn != g . colReorder . n ) {
// show the column pointer in the right place
var colPos = $ ( hoveredCol ) . position ( ) ;
var newleft = newn < g . colReorder . n ?
colPos . left :
colPos . left + $ ( hoveredCol ) . outerWidth ( ) ;
$ ( g . cPointer )
. css ( {
left : newleft ,
visibility : 'visible'
} ) ;
} else {
// no movement to other column, hide the column pointer
$ ( g . cPointer ) . css ( 'visibility' , 'hidden' ) ;
}
}
}
} ,
/ * *
* Stop the dragging action .
*
* @ param e event
* /
2017-04-20 10:55:30 +00:00
dragEnd : function ( e ) {
2016-10-22 14:57:10 +00:00
if ( g . colRsz ) {
var dx = e . pageX - g . colRsz . x0 ;
var nw = g . colRsz . objWidth + dx ;
if ( nw < g . minColWidth ) {
nw = g . minColWidth ;
}
var n = g . colRsz . n ;
// do the resizing
g . resize ( n , nw ) ;
g . reposRsz ( ) ;
g . reposDrop ( ) ;
g . colRsz = false ;
$ ( g . cRsz ) . find ( 'div' ) . removeClass ( 'colborder_active' ) ;
} else if ( g . colReorder ) {
// shift columns
if ( g . colReorder . newn != g . colReorder . n ) {
g . shiftCol ( g . colReorder . n , g . colReorder . newn ) ;
// assign new position
var objPos = $ ( g . colReorder . obj ) . position ( ) ;
g . colReorder . objTop = objPos . top ;
g . colReorder . objLeft = objPos . left ;
g . colReorder . n = g . colReorder . newn ;
// send request to server to remember the column order
if ( g . tableCreateTime ) {
g . sendColPrefs ( ) ;
}
g . refreshRestoreButton ( ) ;
}
// animate new column position
$ ( g . cCpy ) . stop ( true , true )
. animate ( {
top : g . colReorder . objTop ,
left : g . colReorder . objLeft
} , 'fast' )
. fadeOut ( ) ;
$ ( g . cPointer ) . css ( 'visibility' , 'hidden' ) ;
g . colReorder = false ;
}
$ ( document . body ) . css ( 'cursor' , 'inherit' ) . noSelect ( false ) ;
} ,
/ * *
* Resize column n to new width "nw"
*
* @ param n zero - based column index
* @ param nw new width of the column in pixel
* /
2017-04-20 10:55:30 +00:00
resize : function ( n , nw ) {
$ ( g . t ) . find ( 'tr' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
$ ( this ) . find ( 'th.draggable:visible:eq(' + n + ') span,' +
'td:visible:eq(' + ( g . actionSpan + n ) + ') span' )
. css ( 'width' , nw ) ;
} ) ;
} ,
/ * *
* Reposition column resize bars .
* /
2017-04-20 10:55:30 +00:00
reposRsz : function ( ) {
2016-10-22 14:57:10 +00:00
$ ( g . cRsz ) . find ( 'div' ) . hide ( ) ;
var $firstRowCols = $ ( g . t ) . find ( 'tr:first th.draggable:visible' ) ;
var $resizeHandles = $ ( g . cRsz ) . find ( 'div' ) . removeClass ( 'condition' ) ;
2017-04-20 10:55:30 +00:00
$ ( 'table.pma_table' ) . find ( 'thead th:first' ) . removeClass ( 'before-condition' ) ;
2016-10-22 14:57:10 +00:00
for ( var n = 0 , l = $firstRowCols . length ; n < l ; n ++ ) {
var $col = $ ( $firstRowCols [ n ] ) ;
2017-04-20 10:55:30 +00:00
$ ( $resizeHandles [ n ] ) . css ( 'left' , $col . position ( ) . left + $col . outerWidth ( true ) )
2016-10-22 14:57:10 +00:00
. show ( ) ;
if ( $col . hasClass ( 'condition' ) ) {
$ ( $resizeHandles [ n ] ) . addClass ( 'condition' ) ;
if ( n > 0 ) {
2017-04-20 10:55:30 +00:00
$ ( $resizeHandles [ n - 1 ] ) . addClass ( 'condition' ) ;
2016-10-22 14:57:10 +00:00
}
}
}
if ( $ ( $resizeHandles [ 0 ] ) . hasClass ( 'condition' ) ) {
2017-04-20 10:55:30 +00:00
$ ( 'table.pma_table' ) . find ( 'thead th:first' ) . addClass ( 'before-condition' ) ;
2016-10-22 14:57:10 +00:00
}
$ ( g . cRsz ) . css ( 'height' , $ ( g . t ) . height ( ) ) ;
} ,
/ * *
* Shift column from index oldn to newn .
*
* @ param oldn old zero - based column index
* @ param newn new zero - based column index
* /
2017-04-20 10:55:30 +00:00
shiftCol : function ( oldn , newn ) {
$ ( g . t ) . find ( 'tr' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
if ( newn < oldn ) {
$ ( this ) . find ( 'th.draggable:eq(' + newn + '),' +
'td:eq(' + ( g . actionSpan + newn ) + ')' )
. before ( $ ( this ) . find ( 'th.draggable:eq(' + oldn + '),' +
'td:eq(' + ( g . actionSpan + oldn ) + ')' ) ) ;
} else {
$ ( this ) . find ( 'th.draggable:eq(' + newn + '),' +
'td:eq(' + ( g . actionSpan + newn ) + ')' )
. after ( $ ( this ) . find ( 'th.draggable:eq(' + oldn + '),' +
'td:eq(' + ( g . actionSpan + oldn ) + ')' ) ) ;
}
} ) ;
// reposition the column resize bars
g . reposRsz ( ) ;
// adjust the column visibility list
if ( newn < oldn ) {
$ ( g . cList ) . find ( '.lDiv div:eq(' + newn + ')' )
. before ( $ ( g . cList ) . find ( '.lDiv div:eq(' + oldn + ')' ) ) ;
} else {
$ ( g . cList ) . find ( '.lDiv div:eq(' + newn + ')' )
. after ( $ ( g . cList ) . find ( '.lDiv div:eq(' + oldn + ')' ) ) ;
}
// adjust the colOrder
var tmp = g . colOrder [ oldn ] ;
g . colOrder . splice ( oldn , 1 ) ;
g . colOrder . splice ( newn , 0 , tmp ) ;
// adjust the colVisib
if ( g . colVisib . length > 0 ) {
tmp = g . colVisib [ oldn ] ;
g . colVisib . splice ( oldn , 1 ) ;
g . colVisib . splice ( newn , 0 , tmp ) ;
}
} ,
/ * *
* Find currently hovered table column ' s header ( excluding actions column ) .
*
* @ param e event
* @ return the hovered column ' s th object or undefined if no hovered column found .
* /
2017-04-20 10:55:30 +00:00
getHoveredCol : function ( e ) {
2016-10-22 14:57:10 +00:00
var hoveredCol ;
$headers = $ ( g . t ) . find ( 'th.draggable:visible' ) ;
2017-04-20 10:55:30 +00:00
$headers . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var left = $ ( this ) . offset ( ) . left ;
var right = left + $ ( this ) . outerWidth ( ) ;
if ( left <= e . pageX && e . pageX <= right ) {
hoveredCol = this ;
}
} ) ;
return hoveredCol ;
} ,
/ * *
* Get a zero - based index from a < th class = "draggable" > tag in a table .
*
* @ param obj table header < th > object
* @ return zero - based index of the specified table header in the set of table headers ( visible or not )
* /
2017-04-20 10:55:30 +00:00
getHeaderIdx : function ( obj ) {
2016-10-22 14:57:10 +00:00
return $ ( obj ) . parents ( 'tr' ) . find ( 'th.draggable' ) . index ( obj ) ;
} ,
/ * *
* Reposition the columns back to normal order .
* /
2017-04-20 10:55:30 +00:00
restoreColOrder : function ( ) {
2016-10-22 14:57:10 +00:00
// use insertion sort, since we already have shiftCol function
for ( var i = 1 ; i < g . colOrder . length ; i ++ ) {
var x = g . colOrder [ i ] ;
var j = i - 1 ;
while ( j >= 0 && x < g . colOrder [ j ] ) {
j -- ;
}
if ( j != i - 1 ) {
g . shiftCol ( i , j + 1 ) ;
}
}
if ( g . tableCreateTime ) {
// send request to server to remember the column order
g . sendColPrefs ( ) ;
}
g . refreshRestoreButton ( ) ;
} ,
/ * *
* Send column preferences ( column order and visibility ) to the server .
* /
2017-04-20 10:55:30 +00:00
sendColPrefs : function ( ) {
2016-10-22 14:57:10 +00:00
if ( $ ( g . t ) . is ( '.ajax' ) ) { // only send preferences if ajax class
var post _params = {
ajax _request : true ,
db : g . db ,
table : g . table ,
token : g . token ,
server : g . server ,
set _col _prefs : true ,
table _create _time : g . tableCreateTime
} ;
if ( g . colOrder . length > 0 ) {
$ . extend ( post _params , { col _order : g . colOrder . toString ( ) } ) ;
}
if ( g . colVisib . length > 0 ) {
$ . extend ( post _params , { col _visib : g . colVisib . toString ( ) } ) ;
}
2017-04-20 10:55:30 +00:00
$ . post ( 'sql.php' , post _params , function ( data ) {
if ( data . success != true ) {
2016-10-22 14:57:10 +00:00
var $temp _div = $ ( document . createElement ( 'div' ) ) ;
$temp _div . html ( data . error ) ;
$temp _div . addClass ( "error" ) ;
PMA _ajaxShowMessage ( $temp _div , false ) ;
}
} ) ;
}
} ,
/ * *
* Refresh restore button state .
* Make restore button disabled if the table is similar with initial state .
* /
2017-04-20 10:55:30 +00:00
refreshRestoreButton : function ( ) {
2016-10-22 14:57:10 +00:00
// check if table state is as initial state
var isInitial = true ;
for ( var i = 0 ; i < g . colOrder . length ; i ++ ) {
if ( g . colOrder [ i ] != i ) {
isInitial = false ;
break ;
}
}
// check if only one visible column left
var isOneColumn = g . visibleHeadersCount == 1 ;
// enable or disable restore button
if ( isInitial || isOneColumn ) {
2017-04-20 10:55:30 +00:00
$ ( 'div.restore_column' ) . hide ( ) ;
2016-10-22 14:57:10 +00:00
} else {
2017-04-20 10:55:30 +00:00
$ ( 'div.restore_column' ) . show ( ) ;
2016-10-22 14:57:10 +00:00
}
} ,
/ * *
* Update current hint using the boolean values ( showReorderHint , showSortHint , etc . ) .
*
* /
2017-04-20 10:55:30 +00:00
updateHint : function ( ) {
2016-10-22 14:57:10 +00:00
var text = '' ;
if ( ! g . colRsz && ! g . colReorder ) { // if not resizing or dragging
if ( g . visibleHeadersCount > 1 ) {
g . showReorderHint = true ;
}
if ( $ ( t ) . find ( 'th.marker' ) . length > 0 ) {
g . showMarkHint = true ;
}
2017-04-20 10:55:30 +00:00
if ( g . showReorderHint && g . reorderHint ) {
text += g . reorderHint ;
2016-10-22 14:57:10 +00:00
}
2017-04-20 10:55:30 +00:00
if ( g . showSortHint && g . sortHint ) {
2016-10-22 14:57:10 +00:00
text += text . length > 0 ? '<br />' : '' ;
2017-04-20 10:55:30 +00:00
text += g . sortHint ;
2016-10-22 14:57:10 +00:00
}
2017-04-20 10:55:30 +00:00
if ( g . showMarkHint && g . markHint &&
! g . showSortHint // we do not show mark hint, when sort hint is shown
2016-10-22 14:57:10 +00:00
) {
text += text . length > 0 ? '<br />' : '' ;
2017-04-20 10:55:30 +00:00
text += g . markHint ;
2016-10-22 14:57:10 +00:00
text += text . length > 0 ? '<br />' : '' ;
2017-04-20 10:55:30 +00:00
text += g . copyHint ;
2016-10-22 14:57:10 +00:00
}
}
return text ;
} ,
/ * *
* Toggle column ' s visibility .
* After calling this function and it returns true , afterToggleCol ( ) must be called .
*
* @ return boolean True if the column is toggled successfully .
* /
2017-04-20 10:55:30 +00:00
toggleCol : function ( n ) {
2016-10-22 14:57:10 +00:00
if ( g . colVisib [ n ] ) {
// can hide if more than one column is visible
if ( g . visibleHeadersCount > 1 ) {
2017-04-20 10:55:30 +00:00
$ ( g . t ) . find ( 'tr' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
$ ( this ) . find ( 'th.draggable:eq(' + n + '),' +
'td:eq(' + ( g . actionSpan + n ) + ')' )
. hide ( ) ;
} ) ;
g . colVisib [ n ] = 0 ;
$ ( g . cList ) . find ( '.lDiv div:eq(' + n + ') input' ) . prop ( 'checked' , false ) ;
} else {
// cannot hide, force the checkbox to stay checked
$ ( g . cList ) . find ( '.lDiv div:eq(' + n + ') input' ) . prop ( 'checked' , true ) ;
return false ;
}
} else { // column n is not visible
2017-04-20 10:55:30 +00:00
$ ( g . t ) . find ( 'tr' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
$ ( this ) . find ( 'th.draggable:eq(' + n + '),' +
'td:eq(' + ( g . actionSpan + n ) + ')' )
. show ( ) ;
} ) ;
g . colVisib [ n ] = 1 ;
$ ( g . cList ) . find ( '.lDiv div:eq(' + n + ') input' ) . prop ( 'checked' , true ) ;
}
return true ;
} ,
/ * *
* This must be called if toggleCol ( ) returns is true .
*
* This function is separated from toggleCol because , sometimes , we want to toggle
* some columns together at one time and do just one adjustment after it , e . g . in showAllColumns ( ) .
* /
2017-04-20 10:55:30 +00:00
afterToggleCol : function ( ) {
2016-10-22 14:57:10 +00:00
// some adjustments after hiding column
g . reposRsz ( ) ;
g . reposDrop ( ) ;
g . sendColPrefs ( ) ;
// check visible first row headers count
g . visibleHeadersCount = $ ( g . t ) . find ( 'tr:first th.draggable:visible' ) . length ;
g . refreshRestoreButton ( ) ;
} ,
/ * *
* Show columns ' visibility list .
*
* @ param obj The drop down arrow of column visibility list
* /
2017-04-20 10:55:30 +00:00
showColList : function ( obj ) {
2016-10-22 14:57:10 +00:00
// only show when not resizing or reordering
if ( ! g . colRsz && ! g . colReorder ) {
var pos = $ ( obj ) . position ( ) ;
// check if the list position is too right
if ( pos . left + $ ( g . cList ) . outerWidth ( true ) > $ ( document ) . width ( ) ) {
pos . left = $ ( document ) . width ( ) - $ ( g . cList ) . outerWidth ( true ) ;
}
$ ( g . cList ) . css ( {
left : pos . left ,
top : pos . top + $ ( obj ) . outerHeight ( true )
} )
. show ( ) ;
$ ( obj ) . addClass ( 'coldrop-hover' ) ;
}
} ,
/ * *
* Hide columns ' visibility list .
* /
2017-04-20 10:55:30 +00:00
hideColList : function ( ) {
2016-10-22 14:57:10 +00:00
$ ( g . cList ) . hide ( ) ;
$ ( g . cDrop ) . find ( '.coldrop-hover' ) . removeClass ( 'coldrop-hover' ) ;
} ,
/ * *
* Reposition the column visibility drop - down arrow .
* /
2017-04-20 10:55:30 +00:00
reposDrop : function ( ) {
2016-10-22 14:57:10 +00:00
var $th = $ ( t ) . find ( 'th:not(.draggable)' ) ;
for ( var i = 0 ; i < $th . length ; i ++ ) {
var $cd = $ ( g . cDrop ) . find ( 'div:eq(' + i + ')' ) ; // column drop-down arrow
var pos = $ ( $th [ i ] ) . position ( ) ;
$cd . css ( {
left : pos . left + $ ( $th [ i ] ) . width ( ) - $cd . width ( ) ,
top : pos . top
} ) ;
}
} ,
/ * *
* Show all hidden columns .
* /
2017-04-20 10:55:30 +00:00
showAllColumns : function ( ) {
2016-10-22 14:57:10 +00:00
for ( var i = 0 ; i < g . colVisib . length ; i ++ ) {
if ( ! g . colVisib [ i ] ) {
g . toggleCol ( i ) ;
}
}
g . afterToggleCol ( ) ;
} ,
/ * *
* Show edit cell , if it can be shown
*
* @ param cell < td > element to be edited
* /
2017-04-20 10:55:30 +00:00
showEditCell : function ( cell ) {
2016-10-22 14:57:10 +00:00
if ( $ ( cell ) . is ( '.grid_edit' ) &&
! g . colRsz && ! g . colReorder )
{
if ( ! g . isCellEditActive ) {
var $cell = $ ( cell ) ;
// remove all edit area and hide it
$ ( g . cEdit ) . find ( '.edit_area' ) . empty ( ) . hide ( ) ;
// reposition the cEdit element
$ ( g . cEdit ) . css ( {
top : $cell . position ( ) . top ,
left : $cell . position ( ) . left
} )
. show ( )
. find ( '.edit_box' )
. css ( {
width : $cell . outerWidth ( ) ,
height : $cell . outerHeight ( )
} ) ;
// fill the cell edit with text from <td>
var value = PMA _getCellValue ( cell ) ;
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( value ) ;
g . currentEditCell = cell ;
$ ( g . cEdit ) . find ( '.edit_box' ) . focus ( ) ;
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '*' ) . removeProp ( 'disabled' ) ;
2016-10-22 14:57:10 +00:00
}
}
} ,
/ * *
* Remove edit cell and the edit area , if it is shown .
*
* @ param force Optional , force to hide edit cell without saving edited field .
* @ param data Optional , data from the POST AJAX request to save the edited field
* or just specify "true" , if we want to replace the edited field with the new value .
* @ param field Optional , the edited < td > . If not specified , the function will
* use currently edited < td > from g . currentEditCell .
* /
2017-04-20 10:55:30 +00:00
hideEditCell : function ( force , data , field ) {
2016-10-22 14:57:10 +00:00
if ( g . isCellEditActive && ! force ) {
// cell is being edited, save or post the edited data
2017-04-20 10:55:30 +00:00
g . saveOrPostEditedCell ( ) ;
2016-10-22 14:57:10 +00:00
return ;
}
// cancel any previous request
2017-04-20 10:55:30 +00:00
if ( g . lastXHR != null ) {
2016-10-22 14:57:10 +00:00
g . lastXHR . abort ( ) ;
g . lastXHR = null ;
}
if ( data ) {
if ( g . currentEditCell ) { // save value of currently edited cell
// replace current edited field with the new value
var $this _field = $ ( g . currentEditCell ) ;
2017-04-20 10:55:30 +00:00
var is _null = $this _field . data ( 'value' ) == null ;
2016-10-22 14:57:10 +00:00
if ( is _null ) {
$this _field . find ( 'span' ) . html ( 'NULL' ) ;
$this _field . addClass ( 'null' ) ;
} else {
$this _field . removeClass ( 'null' ) ;
2017-04-20 10:55:30 +00:00
var new _html = data . isNeedToRecheck
2016-10-22 14:57:10 +00:00
? data . truncatableFieldValue
: $this _field . data ( 'value' ) ;
2017-04-20 10:55:30 +00:00
if ( $this _field . is ( '.truncated' ) ) {
if ( new _html . length > g . maxTruncatedLen ) {
new _html = new _html . substring ( 0 , g . maxTruncatedLen ) + '...' ;
}
2016-10-22 14:57:10 +00:00
}
2017-04-20 10:55:30 +00:00
$this _field . find ( 'span' ) . text ( new _html ) ;
2016-10-22 14:57:10 +00:00
}
}
2017-04-20 10:55:30 +00:00
if ( data . transformations != undefined ) {
$ . each ( data . transformations , function ( cell _index , value ) {
2016-10-22 14:57:10 +00:00
var $this _field = $ ( g . t ) . find ( '.to_be_saved:eq(' + cell _index + ')' ) ;
$this _field . find ( 'span' ) . html ( value ) ;
} ) ;
}
2017-04-20 10:55:30 +00:00
if ( data . relations != undefined ) {
$ . each ( data . relations , function ( cell _index , value ) {
2016-10-22 14:57:10 +00:00
var $this _field = $ ( g . t ) . find ( '.to_be_saved:eq(' + cell _index + ')' ) ;
$this _field . find ( 'span' ) . html ( value ) ;
} ) ;
}
// refresh the grid
g . reposRsz ( ) ;
g . reposDrop ( ) ;
}
// hide the cell editing area
$ ( g . cEdit ) . hide ( ) ;
$ ( g . cEdit ) . find ( '.edit_box' ) . blur ( ) ;
g . isCellEditActive = false ;
g . currentEditCell = null ;
// destroy datepicker in edit area, if exist
var $dp = $ ( g . cEdit ) . find ( '.hasDatepicker' ) ;
if ( $dp . length > 0 ) {
$dp . datepicker ( 'destroy' ) ;
// change the cursor in edit box back to normal
// (the cursor become a hand pointer when we add datepicker)
$ ( g . cEdit ) . find ( '.edit_box' ) . css ( 'cursor' , 'inherit' ) ;
}
} ,
/ * *
* Show drop - down edit area when edit cell is focused .
* /
2017-04-20 10:55:30 +00:00
showEditArea : function ( ) {
2016-10-22 14:57:10 +00:00
if ( ! g . isCellEditActive ) { // make sure the edit area has not been shown
g . isCellEditActive = true ;
g . isEditCellTextEditable = false ;
/ * *
* @ var $td current edited cell
* /
var $td = $ ( g . currentEditCell ) ;
/ * *
* @ var $editArea the editing area
* /
var $editArea = $ ( g . cEdit ) . find ( '.edit_area' ) ;
/ * *
* @ var where _clause WHERE clause for the edited cell
* /
var where _clause = $td . parent ( 'tr' ) . find ( '.where_clause' ) . val ( ) ;
/ * *
* @ var field _name String containing the name of this field .
* @ see getFieldName ( )
* /
2017-04-20 10:55:30 +00:00
var field _name = getFieldName ( $td ) ;
2016-10-22 14:57:10 +00:00
/ * *
* @ var relation _curr _value String current value of the field ( for fields that are foreign keyed ) .
* /
var relation _curr _value = $td . text ( ) ;
/ * *
* @ var relation _key _or _display _column String relational key if in 'Relational display column' mode ,
* relational display column if in 'Relational key' mode ( for fields that are foreign keyed ) .
* /
var relation _key _or _display _column = $td . find ( 'a' ) . attr ( 'title' ) ;
/ * *
* @ var curr _value String current value of the field ( for fields that are of type enum or set ) .
* /
var curr _value = $td . find ( 'span' ) . text ( ) ;
// empty all edit area, then rebuild it based on $td classes
$editArea . empty ( ) ;
2017-04-20 10:55:30 +00:00
// add show data row link if the data resulted by 'browse distinct values' in table structure
if ( $td . find ( 'input' ) . hasClass ( 'data_browse_link' ) ) {
var showDataRowLink = document . createElement ( 'div' ) ;
showDataRowLink . className = 'goto_link' ;
$ ( showDataRowLink ) . append ( "<a href='" + $td . find ( '.data_browse_link' ) . val ( ) + "'>" + g . showDataRowLinkText + "</a>" ) ;
$editArea . append ( showDataRowLink ) ;
}
2016-10-22 14:57:10 +00:00
// add goto link, if this cell contains a link
if ( $td . find ( 'a' ) . length > 0 ) {
var gotoLink = document . createElement ( 'div' ) ;
gotoLink . className = 'goto_link' ;
2017-04-20 10:55:30 +00:00
$ ( gotoLink ) . append ( g . gotoLinkText + ': ' ) . append ( $td . find ( 'a' ) . clone ( ) ) ;
2016-10-22 14:57:10 +00:00
$editArea . append ( gotoLink ) ;
}
g . wasEditedCellNull = false ;
if ( $td . is ( ':not(.not_null)' ) ) {
// append a null checkbox
2017-04-20 10:55:30 +00:00
$editArea . append ( '<div class="null_div">Null :<input type="checkbox"></div>' ) ;
2016-10-22 14:57:10 +00:00
var $checkbox = $editArea . find ( '.null_div input' ) ;
// check if current <td> is NULL
2017-04-20 10:55:30 +00:00
if ( $td . is ( '.null' ) ) {
2016-10-22 14:57:10 +00:00
$checkbox . prop ( 'checked' , true ) ;
g . wasEditedCellNull = true ;
}
// if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
if ( $td . is ( '.enum, .set' ) ) {
2017-04-20 10:55:30 +00:00
$editArea . find ( 'select' ) . live ( 'change' , function ( e ) {
2016-10-22 14:57:10 +00:00
$checkbox . prop ( 'checked' , false ) ;
} ) ;
} else if ( $td . is ( '.relation' ) ) {
2017-04-20 10:55:30 +00:00
$editArea . find ( 'select' ) . live ( 'change' , function ( e ) {
2016-10-22 14:57:10 +00:00
$checkbox . prop ( 'checked' , false ) ;
} ) ;
2017-04-20 10:55:30 +00:00
$editArea . find ( '.browse_foreign' ) . live ( 'click' , function ( e ) {
2016-10-22 14:57:10 +00:00
$checkbox . prop ( 'checked' , false ) ;
} ) ;
} else {
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . live ( 'keypress change' , function ( e ) {
2016-10-22 14:57:10 +00:00
$checkbox . prop ( 'checked' , false ) ;
} ) ;
// Capture ctrl+v (on IE and Chrome)
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . live ( 'keydown' , function ( e ) {
2016-10-22 14:57:10 +00:00
if ( e . ctrlKey && e . which == 86 ) {
$checkbox . prop ( 'checked' , false ) ;
}
} ) ;
2017-04-20 10:55:30 +00:00
$editArea . find ( 'textarea' ) . live ( 'keydown' , function ( e ) {
2016-10-22 14:57:10 +00:00
$checkbox . prop ( 'checked' , false ) ;
} ) ;
}
// if null checkbox is clicked empty the corresponding select/editor.
2017-04-20 10:55:30 +00:00
$checkbox . click ( function ( e ) {
2016-10-22 14:57:10 +00:00
if ( $td . is ( '.enum' ) ) {
$editArea . find ( 'select' ) . val ( '' ) ;
} else if ( $td . is ( '.set' ) ) {
2017-04-20 10:55:30 +00:00
$editArea . find ( 'select' ) . find ( 'option' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var $option = $ ( this ) ;
$option . prop ( 'selected' , false ) ;
} ) ;
} else if ( $td . is ( '.relation' ) ) {
// if the dropdown is there to select the foreign value
if ( $editArea . find ( 'select' ) . length > 0 ) {
$editArea . find ( 'select' ) . val ( '' ) ;
}
} else {
$editArea . find ( 'textarea' ) . val ( '' ) ;
}
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( '' ) ;
} ) ;
}
if ( $td . is ( '.relation' ) ) {
//handle relations
$editArea . addClass ( 'edit_area_loading' ) ;
// initialize the original data
$td . data ( 'original_data' , null ) ;
/ * *
* @ var post _params Object containing parameters for the POST request
* /
var post _params = {
'ajax_request' : true ,
'get_relational_values' : true ,
'server' : g . server ,
'db' : g . db ,
'table' : g . table ,
'column' : field _name ,
'token' : g . token ,
'curr_value' : relation _curr _value ,
'relation_key_or_display_column' : relation _key _or _display _column
} ;
2017-04-20 10:55:30 +00:00
g . lastXHR = $ . post ( 'sql.php' , post _params , function ( data ) {
2016-10-22 14:57:10 +00:00
g . lastXHR = null ;
$editArea . removeClass ( 'edit_area_loading' ) ;
if ( $ ( data . dropdown ) . is ( 'select' ) ) {
// save original_data
var value = $ ( data . dropdown ) . val ( ) ;
$td . data ( 'original_data' , value ) ;
// update the text input field, in case where the "Relational display column" is checked
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( value ) ;
}
$editArea . append ( data . dropdown ) ;
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
// for 'Browse foreign values' options,
// hide the value next to 'Browse foreign values' link
$editArea . find ( 'span.curr_value' ) . hide ( ) ;
// handle update for new values selected from new window
2017-04-20 10:55:30 +00:00
$editArea . find ( 'span.curr_value' ) . change ( function ( ) {
2016-10-22 14:57:10 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( $ ( this ) . text ( ) ) ;
} ) ;
} ) ; // end $.post()
$editArea . show ( ) ;
2017-04-20 10:55:30 +00:00
$editArea . find ( 'select' ) . live ( 'change' , function ( e ) {
2016-10-22 14:57:10 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
g . isEditCellTextEditable = true ;
}
else if ( $td . is ( '.enum' ) ) {
//handle enum fields
$editArea . addClass ( 'edit_area_loading' ) ;
/ * *
* @ var post _params Object containing parameters for the POST request
* /
var post _params = {
2017-04-20 10:55:30 +00:00
'ajax_request' : true ,
'get_enum_values' : true ,
'server' : g . server ,
'db' : g . db ,
'table' : g . table ,
'column' : field _name ,
'token' : g . token ,
'curr_value' : curr _value
2016-10-22 14:57:10 +00:00
} ;
2017-04-20 10:55:30 +00:00
g . lastXHR = $ . post ( 'sql.php' , post _params , function ( data ) {
2016-10-22 14:57:10 +00:00
g . lastXHR = null ;
$editArea . removeClass ( 'edit_area_loading' ) ;
$editArea . append ( data . dropdown ) ;
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
} ) ; // end $.post()
$editArea . show ( ) ;
2017-04-20 10:55:30 +00:00
$editArea . find ( 'select' ) . live ( 'change' , function ( e ) {
2016-10-22 14:57:10 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
}
else if ( $td . is ( '.set' ) ) {
//handle set fields
$editArea . addClass ( 'edit_area_loading' ) ;
/ * *
* @ var post _params Object containing parameters for the POST request
* /
var post _params = {
2017-04-20 10:55:30 +00:00
'ajax_request' : true ,
'get_set_values' : true ,
'server' : g . server ,
'db' : g . db ,
'table' : g . table ,
'column' : field _name ,
'token' : g . token ,
'curr_value' : curr _value
2016-10-22 14:57:10 +00:00
} ;
2017-04-20 10:55:30 +00:00
g . lastXHR = $ . post ( 'sql.php' , post _params , function ( data ) {
2016-10-22 14:57:10 +00:00
g . lastXHR = null ;
$editArea . removeClass ( 'edit_area_loading' ) ;
$editArea . append ( data . select ) ;
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
} ) ; // end $.post()
$editArea . show ( ) ;
2017-04-20 10:55:30 +00:00
$editArea . find ( 'select' ) . live ( 'change' , function ( e ) {
2016-10-22 14:57:10 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
}
else if ( $td . is ( '.truncated, .transformed' ) ) {
if ( $td . is ( '.to_be_saved' ) ) { // cell has been edited
var value = $td . data ( 'value' ) ;
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( value ) ;
$editArea . append ( '<textarea></textarea>' ) ;
2017-04-20 10:55:30 +00:00
$editArea . find ( 'textarea' )
. val ( value )
. live ( 'keyup' , function ( e ) {
2016-10-22 14:57:10 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . live ( 'keyup' , function ( e ) {
2016-10-22 14:57:10 +00:00
$editArea . find ( 'textarea' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
} else {
//handle truncated/transformed values values
$editArea . addClass ( 'edit_area_loading' ) ;
// initialize the original data
$td . data ( 'original_data' , null ) ;
/ * *
* @ var sql _query String containing the SQL query used to retrieve value of truncated / transformed data
* /
var sql _query = 'SELECT `' + field _name + '` FROM `' + g . table + '` WHERE ' + PMA _urldecode ( where _clause ) ;
// Make the Ajax call and get the data, wrap it and insert it
g . lastXHR = $ . post ( 'sql.php' , {
'token' : g . token ,
'server' : g . server ,
'db' : g . db ,
'ajax_request' : true ,
'sql_query' : sql _query ,
'grid_edit' : true
2017-04-20 10:55:30 +00:00
} , function ( data ) {
2016-10-22 14:57:10 +00:00
g . lastXHR = null ;
$editArea . removeClass ( 'edit_area_loading' ) ;
2017-04-20 10:55:30 +00:00
if ( data . success == true ) {
if ( $td . is ( '.truncated' ) ) {
// get the truncated data length
g . maxTruncatedLen = $ ( g . currentEditCell ) . text ( ) . length - 3 ;
}
2016-10-22 14:57:10 +00:00
$td . data ( 'original_data' , data . value ) ;
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( data . value ) ;
2017-04-20 10:55:30 +00:00
$editArea . append ( '<textarea></textarea>' ) ;
$editArea . find ( 'textarea' )
. val ( data . value )
. live ( 'keyup' , function ( e ) {
$ ( g . cEdit ) . find ( '.edit_box' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
$ ( g . cEdit ) . find ( '.edit_box' ) . live ( 'keyup' , function ( e ) {
$editArea . find ( 'textarea' ) . val ( $ ( this ) . val ( ) ) ;
} ) ;
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
2016-10-22 14:57:10 +00:00
} else {
PMA _ajaxShowMessage ( data . error , false ) ;
}
} ) ; // end $.post()
2017-04-20 10:55:30 +00:00
$editArea . show ( ) ;
2016-10-22 14:57:10 +00:00
}
g . isEditCellTextEditable = true ;
2017-04-20 10:55:30 +00:00
} else if ( $td . is ( '.datefield, .datetimefield, .timestampfield' ) ) {
2016-10-22 14:57:10 +00:00
var $input _field = $ ( g . cEdit ) . find ( '.edit_box' ) ;
// remember current datetime value in $input_field, if it is not null
2017-04-20 10:55:30 +00:00
var is _null = $td . is ( '.null' ) ;
var current _datetime _value = ! is _null ? $input _field . val ( ) : '' ;
2016-10-22 14:57:10 +00:00
2017-04-20 10:55:30 +00:00
var showTimeOption = true ;
if ( $td . is ( '.datefield' ) ) {
showTimeOption = false ;
2016-10-22 14:57:10 +00:00
}
2017-04-20 10:55:30 +00:00
PMA _addDatepicker ( $editArea , {
altField : $input _field ,
showTimepicker : showTimeOption ,
onSelect : function ( dateText , inst ) {
// remove null checkbox if it exists
$ ( g . cEdit ) . find ( '.null_div input[type=checkbox]' ) . prop ( 'checked' , false ) ;
}
2016-10-22 14:57:10 +00:00
} ) ;
// cancel any click on the datepicker element
2017-04-20 10:55:30 +00:00
$editArea . find ( '> *' ) . click ( function ( e ) {
2016-10-22 14:57:10 +00:00
e . stopPropagation ( ) ;
} ) ;
2017-04-20 10:55:30 +00:00
// force to restore modified $input_field value after adding datepicker
// (after adding a datepicker, the input field doesn't display the time anymore, only the date)
if ( is _null
|| current _datetime _value == '0000-00-00'
|| current _datetime _value == '0000-00-00 00:00:00'
) {
$input _field . val ( current _datetime _value ) ;
} else {
$editArea . datetimepicker ( 'setDate' , current _datetime _value ) ;
}
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
// remove {cursor: 'pointer'} added inside
// jquery-ui-timepicker-addon.js
$input _field . css ( 'cursor' , '' ) ;
// make the cell editable, so one can can bypass the timepicker
// and enter date/time value manually
2016-10-22 14:57:10 +00:00
g . isEditCellTextEditable = true ;
} else {
g . isEditCellTextEditable = true ;
// only append edit area hint if there is a null checkbox
if ( $editArea . children ( ) . length > 0 ) {
$editArea . append ( '<div class="cell_edit_hint">' + g . cellEditHint + '</div>' ) ;
}
}
if ( $editArea . children ( ) . length > 0 ) {
$editArea . show ( ) ;
}
}
} ,
/ * *
* Post the content of edited cell .
* /
2017-04-20 10:55:30 +00:00
postEditedCell : function ( ) {
2016-10-22 14:57:10 +00:00
if ( g . isSaving ) {
return ;
}
g . isSaving = true ;
2017-04-20 10:55:30 +00:00
2016-10-22 14:57:10 +00:00
/ * *
* @ var relation _fields Array containing the name / value pairs of relational fields
* /
var relation _fields = { } ;
/ * *
* @ var relational _display string 'K' if relational key , 'D' if relational display column
* /
2017-04-20 10:55:30 +00:00
var relational _display = $ ( "#relational_display_K" ) . prop ( 'checked' ) ? 'K' : 'D' ;
2016-10-22 14:57:10 +00:00
/ * *
* @ var transform _fields Array containing the name / value pairs for transformed fields
* /
var transform _fields = { } ;
/ * *
* @ var transformation _fields Boolean , if there are any transformed fields in the edited cells
* /
var transformation _fields = false ;
/ * *
* @ var full _sql _query String containing the complete SQL query to update this table
* /
var full _sql _query = '' ;
/ * *
* @ var rel _fields _list String , url encoded representation of { @ link relations _fields }
* /
var rel _fields _list = '' ;
/ * *
* @ var transform _fields _list String , url encoded representation of { @ link transform _fields }
* /
var transform _fields _list = '' ;
/ * *
* @ var where _clause Array containing where clause for updated fields
* /
var full _where _clause = [ ] ;
/ * *
* @ var is _unique Boolean , whether the rows in this table is unique or not
* /
2017-04-20 10:55:30 +00:00
var is _unique = $ ( 'td.edit_row_anchor' ) . is ( '.nonunique' ) ? 0 : 1 ;
2016-10-22 14:57:10 +00:00
/ * *
* multi edit variables
* /
var me _fields _name = [ ] ;
var me _fields = [ ] ;
var me _fields _null = [ ] ;
// alert user if edited table is not unique
if ( ! is _unique ) {
alert ( g . alertNonUnique ) ;
}
// loop each edited row
2017-04-20 10:55:30 +00:00
$ ( 'td.to_be_saved' ) . parents ( 'tr' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var $tr = $ ( this ) ;
var where _clause = $tr . find ( '.where_clause' ) . val ( ) ;
full _where _clause . push ( PMA _urldecode ( where _clause ) ) ;
var condition _array = jQuery . parseJSON ( $tr . find ( '.condition_array' ) . val ( ) ) ;
/ * *
* multi edit variables , for current row
* @ TODO array indices are still not correct , they should be md5 of field ' s name
* /
var fields _name = [ ] ;
var fields = [ ] ;
var fields _null = [ ] ;
// loop each edited cell in a row
2017-04-20 10:55:30 +00:00
$tr . find ( '.to_be_saved' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
/ * *
* @ var $this _field Object referring to the td that is being edited
* /
var $this _field = $ ( this ) ;
/ * *
* @ var field _name String containing the name of this field .
* @ see getFieldName ( )
* /
2017-04-20 10:55:30 +00:00
var field _name = getFieldName ( $this _field ) ;
2016-10-22 14:57:10 +00:00
/ * *
* @ var this _field _params Array temporary storage for the name / value of current field
* /
var this _field _params = { } ;
if ( $this _field . is ( '.transformed' ) ) {
transformation _fields = true ;
}
this _field _params [ field _name ] = $this _field . data ( 'value' ) ;
/ * *
* @ var is _null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked .
* /
var is _null = this _field _params [ field _name ] === null ;
fields _name . push ( field _name ) ;
if ( is _null ) {
fields _null . push ( 'on' ) ;
fields . push ( '' ) ;
} else {
fields _null . push ( '' ) ;
fields . push ( $this _field . data ( 'value' ) ) ;
var cell _index = $this _field . index ( '.to_be_saved' ) ;
if ( $this _field . is ( ":not(.relation, .enum, .set, .bit)" ) ) {
if ( $this _field . is ( '.transformed' ) ) {
transform _fields [ cell _index ] = { } ;
$ . extend ( transform _fields [ cell _index ] , this _field _params ) ;
}
} else if ( $this _field . is ( '.relation' ) ) {
relation _fields [ cell _index ] = { } ;
$ . extend ( relation _fields [ cell _index ] , this _field _params ) ;
}
}
// check if edited field appears in WHERE clause
if ( where _clause . indexOf ( PMA _urlencode ( field _name ) ) > - 1 ) {
var field _str = '`' + g . table + '`.' + '`' + field _name + '`' ;
for ( var field in condition _array ) {
if ( field . indexOf ( field _str ) > - 1 ) {
2017-04-20 10:55:30 +00:00
condition _array [ field ] = is _null ? 'IS NULL' : "= '" + this _field _params [ field _name ] . replace ( /'/g , "''" ) + "'" ;
2016-10-22 14:57:10 +00:00
break ;
}
}
}
} ) ; // end of loop for every edited cells in a row
// save new_clause
var new _clause = '' ;
for ( var field in condition _array ) {
new _clause += field + ' ' + condition _array [ field ] + ' AND ' ;
}
new _clause = new _clause . substring ( 0 , new _clause . length - 5 ) ; // remove the last AND
new _clause = PMA _urlencode ( new _clause ) ;
$tr . data ( 'new_clause' , new _clause ) ;
// save condition_array
$tr . find ( '.condition_array' ) . val ( JSON . stringify ( condition _array ) ) ;
me _fields _name . push ( fields _name ) ;
me _fields . push ( fields ) ;
me _fields _null . push ( fields _null ) ;
} ) ; // end of loop for every edited rows
rel _fields _list = $ . param ( relation _fields ) ;
transform _fields _list = $ . param ( transform _fields ) ;
// Make the Ajax post after setting all parameters
/ * *
* @ var post _params Object containing parameters for the POST request
* /
var post _params = { 'ajax_request' : true ,
'sql_query' : full _sql _query ,
'token' : g . token ,
'server' : g . server ,
'db' : g . db ,
'table' : g . table ,
'clause_is_unique' : is _unique ,
'where_clause' : full _where _clause ,
'fields[multi_edit]' : me _fields ,
'fields_name[multi_edit]' : me _fields _name ,
'fields_null[multi_edit]' : me _fields _null ,
'rel_fields_list' : rel _fields _list ,
'do_transformations' : transformation _fields ,
'transform_fields_list' : transform _fields _list ,
'relational_display' : relational _display ,
'goto' : 'sql.php' ,
'submit_type' : 'save'
} ;
if ( ! g . saveCellsAtOnce ) {
$ ( g . cEdit ) . find ( '*' ) . prop ( 'disabled' , true ) ;
$ ( g . cEdit ) . find ( '.edit_box' ) . addClass ( 'edit_box_posting' ) ;
} else {
2017-04-20 10:55:30 +00:00
$ ( 'div.save_edited' ) . addClass ( 'saving_edited_data' )
2016-10-22 14:57:10 +00:00
. find ( 'input' ) . prop ( 'disabled' , true ) ; // disable the save button
}
$ . ajax ( {
type : 'POST' ,
url : 'tbl_replace.php' ,
data : post _params ,
success :
2017-04-20 10:55:30 +00:00
function ( data ) {
2016-10-22 14:57:10 +00:00
g . isSaving = false ;
if ( ! g . saveCellsAtOnce ) {
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '*' ) . removeProp ( 'disabled' ) ;
2016-10-22 14:57:10 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . removeClass ( 'edit_box_posting' ) ;
} else {
2017-04-20 10:55:30 +00:00
$ ( 'div.save_edited' ) . removeClass ( 'saving_edited_data' )
. find ( 'input' ) . removeProp ( 'disabled' ) ; // enable the save button back
2016-10-22 14:57:10 +00:00
}
2017-04-20 10:55:30 +00:00
if ( data . success == true ) {
PMA _ajaxShowMessage ( data . message ) ;
2016-10-22 14:57:10 +00:00
// update where_clause related data in each edited row
2017-04-20 10:55:30 +00:00
$ ( 'td.to_be_saved' ) . parents ( 'tr' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var new _clause = $ ( this ) . data ( 'new_clause' ) ;
var $where _clause = $ ( this ) . find ( '.where_clause' ) ;
var old _clause = $where _clause . val ( ) ;
var decoded _old _clause = PMA _urldecode ( old _clause ) ;
var decoded _new _clause = PMA _urldecode ( new _clause ) ;
$where _clause . val ( new _clause ) ;
// update Edit, Copy, and Delete links also
2017-04-20 10:55:30 +00:00
$ ( this ) . find ( 'a' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
$ ( this ) . attr ( 'href' , $ ( this ) . attr ( 'href' ) . replace ( old _clause , new _clause ) ) ;
// update delete confirmation in Delete link
if ( $ ( this ) . attr ( 'href' ) . indexOf ( 'DELETE' ) > - 1 ) {
$ ( this ) . removeAttr ( 'onclick' )
. unbind ( 'click' )
2017-04-20 10:55:30 +00:00
. bind ( 'click' , function ( ) {
2016-10-22 14:57:10 +00:00
return confirmLink ( this , 'DELETE FROM `' + g . db + '`.`' + g . table + '` WHERE ' +
decoded _new _clause + ( is _unique ? '' : ' LIMIT 1' ) ) ;
} ) ;
}
} ) ;
// update the multi edit checkboxes
2017-04-20 10:55:30 +00:00
$ ( this ) . find ( 'input[type=checkbox]' ) . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var $checkbox = $ ( this ) ;
var checkbox _name = $checkbox . attr ( 'name' ) ;
var checkbox _value = $checkbox . val ( ) ;
$checkbox . attr ( 'name' , checkbox _name . replace ( old _clause , new _clause ) ) ;
$checkbox . val ( checkbox _value . replace ( decoded _old _clause , decoded _new _clause ) ) ;
} ) ;
} ) ;
// update the display of executed SQL query command
2017-04-20 10:55:30 +00:00
$ ( '#result_query' ) . remove ( ) ;
2016-10-22 14:57:10 +00:00
if ( typeof data . sql _query != 'undefined' ) {
2017-04-20 10:55:30 +00:00
// display feedback
$ ( '#sqlqueryresults' ) . prepend ( data . sql _query ) ;
2016-10-22 14:57:10 +00:00
}
// hide and/or update the successfully saved cells
g . hideEditCell ( true , data ) ;
// remove the "Save edited cells" button
2017-04-20 10:55:30 +00:00
$ ( 'div.save_edited' ) . hide ( ) ;
2016-10-22 14:57:10 +00:00
// update saved fields
$ ( g . t ) . find ( '.to_be_saved' )
. removeClass ( 'to_be_saved' )
. data ( 'value' , null )
. data ( 'original_data' , null ) ;
g . isCellEdited = false ;
} else {
PMA _ajaxShowMessage ( data . error , false ) ;
}
}
} ) ; // end $.ajax()
} ,
/ * *
* Save edited cell , so it can be posted later .
* /
2017-04-20 10:55:30 +00:00
saveEditedCell : function ( ) {
2016-10-22 14:57:10 +00:00
/ * *
* @ var $this _field Object referring to the td that is being edited
* /
var $this _field = $ ( g . currentEditCell ) ;
var $test _element = '' ; // to test the presence of a element
var need _to _post = false ;
/ * *
* @ var field _name String containing the name of this field .
* @ see getFieldName ( )
* /
2017-04-20 10:55:30 +00:00
var field _name = getFieldName ( $this _field ) ;
2016-10-22 14:57:10 +00:00
/ * *
* @ var this _field _params Array temporary storage for the name / value of current field
* /
var this _field _params = { } ;
/ * *
* @ var is _null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked .
* /
var is _null = $ ( g . cEdit ) . find ( 'input:checkbox' ) . is ( ':checked' ) ;
2017-04-20 10:55:30 +00:00
var value ;
2016-10-22 14:57:10 +00:00
if ( $ ( g . cEdit ) . find ( '.edit_area' ) . is ( '.edit_area_loading' ) ) {
// the edit area is still loading (retrieving cell data), no need to post
need _to _post = false ;
} else if ( is _null ) {
if ( ! g . wasEditedCellNull ) {
this _field _params [ field _name ] = null ;
need _to _post = true ;
}
} else {
if ( $this _field . is ( '.bit' ) ) {
2017-04-20 10:55:30 +00:00
this _field _params [ field _name ] = '0b' + $ ( g . cEdit ) . find ( '.edit_box' ) . val ( ) ;
2016-10-22 14:57:10 +00:00
} else if ( $this _field . is ( '.set' ) ) {
$test _element = $ ( g . cEdit ) . find ( 'select' ) ;
2017-04-20 10:55:30 +00:00
this _field _params [ field _name ] = $test _element . map ( function ( ) {
2016-10-22 14:57:10 +00:00
return $ ( this ) . val ( ) ;
} ) . get ( ) . join ( "," ) ;
} else if ( $this _field . is ( '.relation, .enum' ) ) {
// for relation and enumeration, take the results from edit box value,
// because selected value from drop-down, new window or multiple
// selection list will always be updated to the edit box
this _field _params [ field _name ] = $ ( g . cEdit ) . find ( '.edit_box' ) . val ( ) ;
} else {
this _field _params [ field _name ] = $ ( g . cEdit ) . find ( '.edit_box' ) . val ( ) ;
}
if ( g . wasEditedCellNull || this _field _params [ field _name ] != PMA _getCellValue ( g . currentEditCell ) ) {
need _to _post = true ;
}
}
if ( need _to _post ) {
$ ( g . currentEditCell ) . addClass ( 'to_be_saved' )
. data ( 'value' , this _field _params [ field _name ] ) ;
if ( g . saveCellsAtOnce ) {
2017-04-20 10:55:30 +00:00
$ ( 'div.save_edited' ) . show ( ) ;
2016-10-22 14:57:10 +00:00
}
g . isCellEdited = true ;
}
return need _to _post ;
} ,
/ * *
* Save or post currently edited cell , depending on the "saveCellsAtOnce" configuration .
* /
2017-04-20 10:55:30 +00:00
saveOrPostEditedCell : function ( ) {
2016-10-22 14:57:10 +00:00
var saved = g . saveEditedCell ( ) ;
if ( ! g . saveCellsAtOnce ) {
if ( saved ) {
2017-04-20 10:55:30 +00:00
g . postEditedCell ( ) ;
2016-10-22 14:57:10 +00:00
} else {
2017-04-20 10:55:30 +00:00
g . hideEditCell ( true ) ;
2016-10-22 14:57:10 +00:00
}
} else {
if ( saved ) {
2017-04-20 10:55:30 +00:00
g . hideEditCell ( true , true ) ;
2016-10-22 14:57:10 +00:00
} else {
2017-04-20 10:55:30 +00:00
g . hideEditCell ( true ) ;
2016-10-22 14:57:10 +00:00
}
}
} ,
/ * *
* Initialize column resize feature .
* /
2017-04-20 10:55:30 +00:00
initColResize : function ( ) {
2016-10-22 14:57:10 +00:00
// create column resizer div
g . cRsz = document . createElement ( 'div' ) ;
g . cRsz . className = 'cRsz' ;
// get data columns in the first row of the table
var $firstRowCols = $ ( g . t ) . find ( 'tr:first th.draggable' ) ;
// create column borders
2017-04-20 10:55:30 +00:00
$firstRowCols . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var cb = document . createElement ( 'div' ) ; // column border
$ ( cb ) . addClass ( 'colborder' )
2017-04-20 10:55:30 +00:00
. mousedown ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . dragStartRsz ( e , this ) ;
} ) ;
$ ( g . cRsz ) . append ( cb ) ;
} ) ;
g . reposRsz ( ) ;
// attach to global div
$ ( g . gDiv ) . prepend ( g . cRsz ) ;
} ,
/ * *
* Initialize column reordering feature .
* /
2017-04-20 10:55:30 +00:00
initColReorder : function ( ) {
2016-10-22 14:57:10 +00:00
g . cCpy = document . createElement ( 'div' ) ; // column copy, to store copy of dragged column header
g . cPointer = document . createElement ( 'div' ) ; // column pointer, used when reordering column
// adjust g.cCpy
g . cCpy . className = 'cCpy' ;
$ ( g . cCpy ) . hide ( ) ;
// adjust g.cPointer
g . cPointer . className = 'cPointer' ;
$ ( g . cPointer ) . css ( 'visibility' , 'hidden' ) ; // set visibility to hidden instead of calling hide() to force browsers to cache the image in cPointer class
// assign column reordering hint
2017-04-20 10:55:30 +00:00
g . reorderHint = PMA _messages [ 'strColOrderHint' ] ;
2016-10-22 14:57:10 +00:00
// get data columns in the first row of the table
var $firstRowCols = $ ( g . t ) . find ( 'tr:first th.draggable' ) ;
// initialize column order
2017-04-20 10:55:30 +00:00
$col _order = $ ( '#col_order' ) ; // check if column order is passed from PHP
2016-10-22 14:57:10 +00:00
if ( $col _order . length > 0 ) {
g . colOrder = $col _order . val ( ) . split ( ',' ) ;
for ( var i = 0 ; i < g . colOrder . length ; i ++ ) {
2017-04-20 10:55:30 +00:00
g . colOrder [ i ] = parseInt ( g . colOrder [ i ] ) ;
2016-10-22 14:57:10 +00:00
}
} else {
g . colOrder = [ ] ;
for ( var i = 0 ; i < $firstRowCols . length ; i ++ ) {
g . colOrder . push ( i ) ;
}
}
// register events
2017-04-20 10:55:30 +00:00
$ ( t ) . find ( 'th.draggable' )
. mousedown ( function ( e ) {
2016-10-22 14:57:10 +00:00
if ( g . visibleHeadersCount > 1 ) {
g . dragStartReorder ( e , this ) ;
}
} )
2017-04-20 10:55:30 +00:00
. mouseenter ( function ( e ) {
2016-10-22 14:57:10 +00:00
if ( g . visibleHeadersCount > 1 ) {
$ ( this ) . css ( 'cursor' , 'move' ) ;
} else {
$ ( this ) . css ( 'cursor' , 'inherit' ) ;
}
} )
2017-04-20 10:55:30 +00:00
. mouseleave ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . showReorderHint = false ;
$ ( this ) . tooltip ( "option" , {
content : g . updateHint ( )
2017-04-20 10:55:30 +00:00
} ) ;
2016-10-22 14:57:10 +00:00
} )
2017-04-20 10:55:30 +00:00
. dblclick ( function ( e ) {
2016-10-22 14:57:10 +00:00
e . preventDefault ( ) ;
$ ( "<div/>" )
2017-04-20 10:55:30 +00:00
. prop ( "title" , PMA _messages [ "strColNameCopyTitle" ] )
2016-10-22 14:57:10 +00:00
. addClass ( "modal-copy" )
2017-04-20 10:55:30 +00:00
. text ( PMA _messages [ "strColNameCopyText" ] )
2016-10-22 14:57:10 +00:00
. append (
$ ( "<input/>" )
. prop ( "readonly" , true )
. val ( $ ( this ) . data ( "column" ) )
)
. dialog ( {
resizable : false ,
modal : true
} )
. find ( "input" ) . focus ( ) . select ( ) ;
} ) ;
// restore column order when the restore button is clicked
2017-04-20 10:55:30 +00:00
$ ( 'div.restore_column' ) . click ( function ( ) {
2016-10-22 14:57:10 +00:00
g . restoreColOrder ( ) ;
} ) ;
// attach to global div
$ ( g . gDiv ) . append ( g . cPointer ) ;
$ ( g . gDiv ) . append ( g . cCpy ) ;
// prevent default "dragstart" event when dragging a link
2017-04-20 10:55:30 +00:00
$ ( t ) . find ( 'th a' ) . bind ( 'dragstart' , function ( ) {
2016-10-22 14:57:10 +00:00
return false ;
} ) ;
// refresh the restore column button state
g . refreshRestoreButton ( ) ;
} ,
/ * *
* Initialize column visibility feature .
* /
2017-04-20 10:55:30 +00:00
initColVisib : function ( ) {
2016-10-22 14:57:10 +00:00
g . cDrop = document . createElement ( 'div' ) ; // column drop-down arrows
g . cList = document . createElement ( 'div' ) ; // column visibility list
// adjust g.cDrop
g . cDrop . className = 'cDrop' ;
// adjust g.cList
g . cList . className = 'cList' ;
$ ( g . cList ) . hide ( ) ;
// assign column visibility related hints
2017-04-20 10:55:30 +00:00
g . showAllColText = PMA _messages [ 'strShowAllCol' ] ;
2016-10-22 14:57:10 +00:00
// get data columns in the first row of the table
var $firstRowCols = $ ( g . t ) . find ( 'tr:first th.draggable' ) ;
// initialize column visibility
2017-04-20 10:55:30 +00:00
var $col _visib = $ ( '#col_visib' ) ; // check if column visibility is passed from PHP
2016-10-22 14:57:10 +00:00
if ( $col _visib . length > 0 ) {
g . colVisib = $col _visib . val ( ) . split ( ',' ) ;
2017-04-20 10:55:30 +00:00
for ( var i = 0 ; i < g . colVisib . length ; i ++ ) {
g . colVisib [ i ] = parseInt ( g . colVisib [ i ] ) ;
2016-10-22 14:57:10 +00:00
}
} else {
g . colVisib = [ ] ;
2017-04-20 10:55:30 +00:00
for ( var i = 0 ; i < $firstRowCols . length ; i ++ ) {
2016-10-22 14:57:10 +00:00
g . colVisib . push ( 1 ) ;
}
}
// make sure we have more than one column
if ( $firstRowCols . length > 1 ) {
var $colVisibTh = $ ( g . t ) . find ( 'th:not(.draggable)' ) ;
PMA _tooltip (
$colVisibTh ,
'th' ,
2017-04-20 10:55:30 +00:00
PMA _messages [ 'strColVisibHint' ]
2016-10-22 14:57:10 +00:00
) ;
// create column visibility drop-down arrow(s)
2017-04-20 10:55:30 +00:00
$colVisibTh . each ( function ( ) {
2016-10-22 14:57:10 +00:00
var $th = $ ( this ) ;
var cd = document . createElement ( 'div' ) ; // column drop-down arrow
var pos = $th . position ( ) ;
$ ( cd ) . addClass ( 'coldrop' )
2017-04-20 10:55:30 +00:00
. click ( function ( ) {
2016-10-22 14:57:10 +00:00
if ( g . cList . style . display == 'none' ) {
g . showColList ( this ) ;
} else {
g . hideColList ( ) ;
}
} ) ;
$ ( g . cDrop ) . append ( cd ) ;
} ) ;
// add column visibility control
g . cList . innerHTML = '<div class="lDiv"></div>' ;
var $listDiv = $ ( g . cList ) . find ( 'div' ) ;
2017-04-20 10:55:30 +00:00
for ( var i = 0 ; i < $firstRowCols . length ; i ++ ) {
2016-10-22 14:57:10 +00:00
var currHeader = $firstRowCols [ i ] ;
var listElmt = document . createElement ( 'div' ) ;
$ ( listElmt ) . text ( $ ( currHeader ) . text ( ) )
. prepend ( '<input type="checkbox" ' + ( g . colVisib [ i ] ? 'checked="checked" ' : '' ) + '/>' ) ;
$listDiv . append ( listElmt ) ;
// add event on click
2017-04-20 10:55:30 +00:00
$ ( listElmt ) . click ( function ( ) {
if ( g . toggleCol ( $ ( this ) . index ( ) ) ) {
g . afterToggleCol ( ) ;
}
} ) ;
2016-10-22 14:57:10 +00:00
}
// add "show all column" button
var showAll = document . createElement ( 'div' ) ;
$ ( showAll ) . addClass ( 'showAllColBtn' )
. text ( g . showAllColText ) ;
$ ( g . cList ) . append ( showAll ) ;
2017-04-20 10:55:30 +00:00
$ ( showAll ) . click ( function ( ) {
2016-10-22 14:57:10 +00:00
g . showAllColumns ( ) ;
} ) ;
// prepend "show all column" button at top if the list is too long
if ( $firstRowCols . length > 10 ) {
var clone = showAll . cloneNode ( true ) ;
$ ( g . cList ) . prepend ( clone ) ;
2017-04-20 10:55:30 +00:00
$ ( clone ) . click ( function ( ) {
2016-10-22 14:57:10 +00:00
g . showAllColumns ( ) ;
} ) ;
}
}
// hide column visibility list if we move outside the list
2017-04-20 10:55:30 +00:00
$ ( t ) . find ( 'td, th.draggable' ) . mouseenter ( function ( ) {
2016-10-22 14:57:10 +00:00
g . hideColList ( ) ;
} ) ;
// attach to global div
$ ( g . gDiv ) . append ( g . cDrop ) ;
$ ( g . gDiv ) . append ( g . cList ) ;
// some adjustment
g . reposDrop ( ) ;
} ,
/ * *
* Initialize grid editing feature .
* /
2017-04-20 10:55:30 +00:00
initGridEdit : function ( ) {
2016-10-22 14:57:10 +00:00
function startGridEditing ( e , cell ) {
if ( g . isCellEditActive ) {
g . saveOrPostEditedCell ( ) ;
} else {
g . showEditCell ( cell ) ;
}
e . stopPropagation ( ) ;
}
// create cell edit wrapper element
2017-04-20 10:55:30 +00:00
g . cEdit = document . createElement ( 'div' ) ;
2016-10-22 14:57:10 +00:00
// adjust g.cEdit
2017-04-20 10:55:30 +00:00
g . cEdit . className = 'cEdit' ;
$ ( g . cEdit ) . html ( '<textarea class="edit_box" rows="1" ></textarea><div class="edit_area" />' ) ;
$ ( g . cEdit ) . hide ( ) ;
2016-10-22 14:57:10 +00:00
// assign cell editing hint
2017-04-20 10:55:30 +00:00
g . cellEditHint = PMA _messages [ 'strCellEditHint' ] ;
g . saveCellWarning = PMA _messages [ 'strSaveCellWarning' ] ;
g . alertNonUnique = PMA _messages [ 'strAlertNonUnique' ] ;
g . gotoLinkText = PMA _messages [ 'strGoToLink' ] ;
g . showDataRowLinkText = PMA _messages [ 'strShowDataRowLink' ] ;
2016-10-22 14:57:10 +00:00
// initialize cell editing configuration
2017-04-20 10:55:30 +00:00
g . saveCellsAtOnce = $ ( '#save_cells_at_once' ) . val ( ) ;
2016-10-22 14:57:10 +00:00
// register events
2017-04-20 10:55:30 +00:00
$ ( t ) . find ( 'td.data.click1' )
. click ( function ( e ) {
2016-10-22 14:57:10 +00:00
startGridEditing ( e , this ) ;
// prevent default action when clicking on "link" in a table
if ( $ ( e . target ) . is ( '.grid_edit a' ) ) {
e . preventDefault ( ) ;
}
} ) ;
2017-04-20 10:55:30 +00:00
$ ( t ) . find ( 'td.data.click2' )
. click ( function ( e ) {
$cell = $ ( this ) ;
2016-10-22 14:57:10 +00:00
// In the case of relational link, We want single click on the link
// to goto the link and double click to start grid-editing.
var $link = $ ( e . target ) ;
if ( $link . is ( '.grid_edit.relation a' ) ) {
e . preventDefault ( ) ;
// get the click count and increase
var clicks = $cell . data ( 'clicks' ) ;
2017-04-20 10:55:30 +00:00
clicks = ( clicks == null ) ? 1 : clicks + 1 ;
2016-10-22 14:57:10 +00:00
if ( clicks == 1 ) {
// if there are no previous clicks,
// start the single click timer
2017-04-20 10:55:30 +00:00
timer = setTimeout ( function ( ) {
2016-10-22 14:57:10 +00:00
// temporarily remove ajax class so the page loader will not handle it,
// submit and then add it back
$link . removeClass ( 'ajax' ) ;
AJAX . requestHandler . call ( $link [ 0 ] ) ;
$link . addClass ( 'ajax' ) ;
$cell . data ( 'clicks' , 0 ) ;
} , 700 ) ;
$cell . data ( 'clicks' , clicks ) ;
$cell . data ( 'timer' , timer ) ;
} else {
// this is a double click, cancel the single click timer
// and make the click count 0
clearTimeout ( $cell . data ( 'timer' ) ) ;
$cell . data ( 'clicks' , 0 ) ;
// start grid-editing
startGridEditing ( e , this ) ;
}
}
} )
2017-04-20 10:55:30 +00:00
. dblclick ( function ( e ) {
2016-10-22 14:57:10 +00:00
if ( $ ( e . target ) . is ( '.grid_edit a' ) ) {
e . preventDefault ( ) ;
} else {
startGridEditing ( e , this ) ;
}
} ) ;
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '.edit_box' ) . focus ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . showEditArea ( ) ;
} ) ;
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . find ( '.edit_box, select' ) . live ( 'keydown' , function ( e ) {
2016-10-22 14:57:10 +00:00
if ( e . which == 13 ) {
// post on pressing "Enter"
e . preventDefault ( ) ;
g . saveOrPostEditedCell ( ) ;
}
} ) ;
2017-04-20 10:55:30 +00:00
$ ( g . cEdit ) . keydown ( function ( e ) {
2016-10-22 14:57:10 +00:00
if ( ! g . isEditCellTextEditable ) {
// prevent text editing
e . preventDefault ( ) ;
}
} ) ;
2017-04-20 10:55:30 +00:00
$ ( 'html' ) . click ( function ( e ) {
// hide edit cell if the click is not from g.cEdit
if ( $ ( e . target ) . parents ( ) . index ( g . cEdit ) == - 1 ) {
2016-10-22 14:57:10 +00:00
g . hideEditCell ( ) ;
}
2017-04-20 10:55:30 +00:00
} ) . keydown ( function ( e ) {
2016-10-22 14:57:10 +00:00
if ( e . which == 27 && g . isCellEditActive ) {
// cancel on pressing "Esc"
g . hideEditCell ( true ) ;
}
} ) ;
2017-04-20 10:55:30 +00:00
$ ( 'div.save_edited' ) . click ( function ( ) {
2016-10-22 14:57:10 +00:00
g . hideEditCell ( ) ;
g . postEditedCell ( ) ;
} ) ;
2017-04-20 10:55:30 +00:00
$ ( window ) . bind ( 'beforeunload' , function ( e ) {
2016-10-22 14:57:10 +00:00
if ( g . isCellEdited ) {
return g . saveCellWarning ;
}
} ) ;
// attach to global div
2017-04-20 10:55:30 +00:00
$ ( g . gDiv ) . append ( g . cEdit ) ;
2016-10-22 14:57:10 +00:00
// add hint for grid editing feature when hovering "Edit" link in each table row
2017-04-20 10:55:30 +00:00
if ( PMA _messages [ 'strGridEditFeatureHint' ] != undefined ) {
2016-10-22 14:57:10 +00:00
PMA _tooltip (
$ ( g . t ) . find ( '.edit_row_anchor a' ) ,
'a' ,
2017-04-20 10:55:30 +00:00
PMA _messages [ 'strGridEditFeatureHint' ]
2016-10-22 14:57:10 +00:00
) ;
}
}
} ;
/ * * * * * * * * * * * * * * * * * *
* Initialize grid
* * * * * * * * * * * * * * * * * * /
2017-04-20 10:55:30 +00:00
// wrap all data cells, except actions cell, with span
2016-10-22 14:57:10 +00:00
$ ( t ) . find ( 'th, td:not(:has(span))' )
. wrapInner ( '<span />' ) ;
// create grid elements
g . gDiv = document . createElement ( 'div' ) ; // create global div
// initialize the table variable
g . t = t ;
// get data columns in the first row of the table
var $firstRowCols = $ ( t ) . find ( 'tr:first th.draggable' ) ;
// initialize visible headers count
g . visibleHeadersCount = $firstRowCols . filter ( ':visible' ) . length ;
// assign first column (actions) span
if ( ! $ ( t ) . find ( 'tr:first th:first' ) . hasClass ( 'draggable' ) ) { // action header exist
g . actionSpan = $ ( t ) . find ( 'tr:first th:first' ) . prop ( 'colspan' ) ;
} else {
g . actionSpan = 0 ;
}
// assign table create time
2017-04-20 10:55:30 +00:00
// #table_create_time will only available if we are in "Browse" tab
g . tableCreateTime = $ ( '#table_create_time' ) . val ( ) ;
2016-10-22 14:57:10 +00:00
// assign the hints
2017-04-20 10:55:30 +00:00
g . sortHint = PMA _messages [ 'strSortHint' ] ;
g . markHint = PMA _messages [ 'strColMarkHint' ] ;
g . copyHint = PMA _messages [ 'strColNameCopyHint' ] ;
2016-10-22 14:57:10 +00:00
// assign common hidden inputs
2017-04-20 10:55:30 +00:00
var $common _hidden _inputs = $ ( 'div.common_hidden_inputs' ) ;
2016-10-22 14:57:10 +00:00
g . token = $common _hidden _inputs . find ( 'input[name=token]' ) . val ( ) ;
g . server = $common _hidden _inputs . find ( 'input[name=server]' ) . val ( ) ;
g . db = $common _hidden _inputs . find ( 'input[name=db]' ) . val ( ) ;
g . table = $common _hidden _inputs . find ( 'input[name=table]' ) . val ( ) ;
// add table class
$ ( t ) . addClass ( 'pma_table' ) ;
// add relative position to global div so that resize handlers are correctly positioned
$ ( g . gDiv ) . css ( 'position' , 'relative' ) ;
// link the global div
$ ( t ) . before ( g . gDiv ) ;
$ ( g . gDiv ) . append ( t ) ;
// FEATURES
2017-04-20 10:55:30 +00:00
enableResize = enableResize == undefined ? true : enableResize ;
enableReorder = enableReorder == undefined ? true : enableReorder ;
enableVisib = enableVisib == undefined ? true : enableVisib ;
enableGridEdit = enableGridEdit == undefined ? true : enableGridEdit ;
2016-10-22 14:57:10 +00:00
if ( enableResize ) {
g . initColResize ( ) ;
}
if ( enableReorder &&
2017-04-20 10:55:30 +00:00
$ ( 'table.navigation' ) . length > 0 ) // disable reordering for result from EXPLAIN or SHOW syntax, which do not have a table navigation panel
2016-10-22 14:57:10 +00:00
{
g . initColReorder ( ) ;
}
if ( enableVisib ) {
g . initColVisib ( ) ;
}
if ( enableGridEdit &&
$ ( t ) . is ( '.ajax' ) ) // make sure we have the ajax class
{
g . initGridEdit ( ) ;
}
// create tooltip for each <th> with draggable class
PMA _tooltip (
$ ( t ) . find ( "th.draggable" ) ,
'th' ,
g . updateHint ( )
) ;
// register events for hint tooltip (anchors inside draggable th)
$ ( t ) . find ( 'th.draggable a' )
2017-04-20 10:55:30 +00:00
. mouseenter ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . showSortHint = true ;
$ ( t ) . find ( "th.draggable" ) . tooltip ( "option" , {
content : g . updateHint ( )
} ) ;
} )
2017-04-20 10:55:30 +00:00
. mouseleave ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . showSortHint = false ;
$ ( t ) . find ( "th.draggable" ) . tooltip ( "option" , {
content : g . updateHint ( )
} ) ;
} ) ;
// register events for dragging-related feature
if ( enableResize || enableReorder ) {
2017-04-20 10:55:30 +00:00
$ ( document ) . mousemove ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . dragMove ( e ) ;
} ) ;
2017-04-20 10:55:30 +00:00
$ ( document ) . mouseup ( function ( e ) {
2016-10-22 14:57:10 +00:00
g . dragEnd ( e ) ;
} ) ;
}
// some adjustment
$ ( t ) . removeClass ( 'data' ) ;
$ ( g . gDiv ) . addClass ( 'data' ) ;
}