コード例 #1
0
ファイル: jqgrid_dist.php プロジェクト: mabulabastide/VD
    /**
     * Generate JSON array for grid rendering
     * @param $grid_id Unique ID for grid
     */
    function render($grid_id)
    {
        // render grid for first time (non ajax), but specific grid on ajax calls
        $is_ajax = isset($_REQUEST["nd"]) || isset($_REQUEST["oper"]) || isset($_REQUEST["export"]);
        if ($is_ajax && $_REQUEST["grid_id"] != $grid_id) {
            return;
        }
        $append_by = strpos($this->options["url"], "?") === false ? "?" : "&";
        $this->options["url"] .= $append_by . "grid_id={$grid_id}";
        $this->options["editurl"] .= $append_by . "grid_id={$grid_id}";
        $this->options["cellurl"] .= $append_by . "grid_id={$grid_id}";
        if (isset($_REQUEST["subgrid"])) {
            $grid_id = "_" . $_REQUEST["subgrid"];
            #$grid_id = "_".preg_replace("/[^a-zA-Z0-9]+/", "", $grid_id);
        }
        $this->id = $grid_id;
        ### P ###
        // custom on select event execution
        if (!empty($this->events["on_select"])) {
            $func = $this->events["on_select"][0];
            $obj = $this->events["on_select"][1];
            $continue = $this->events["on_select"][2];
            $event_sql = "";
            $event_sql_count = "";
            if ($obj) {
                call_user_func(array($obj, $func), array("param" => $_REQUEST, "grid" => $this, "sql" => &$event_sql, "sql_count" => &$event_sql_count));
            } else {
                call_user_func($func, array("param" => $_REQUEST, "grid" => $this, "sql" => &$event_sql, "sql_count" => &$event_sql_count));
            }
            $this->internal["sql_count"] = $event_sql_count;
            $this->internal["sql"] = $event_sql;
        }
        // generate column names, if not defined
        if (!$this->options["colNames"]) {
            $this->set_columns();
        }
        ### P ###
        // persist search if asked
        if ($this->options["persistsearch"] === true) {
            $this->options["search"] = true;
            $this->options["postData"] = array("filters" => $_SESSION["jqgrid_{$grid_id}_searchstr"]);
            // this performs the search
            $array_of_search_values = json_decode($_SESSION["jqgrid_{$grid_id}_searchstr"], true);
            foreach ($array_of_search_values["rules"] as &$rules) {
                foreach ($this->options["colModel"] as &$col) {
                    if ($rules['field'] == $col["name"]) {
                        $search_word = $rules['data'];
                        $col["searchoptions"] = array("defaultValue" => $search_word);
                    }
                }
            }
        }
        ### P ###
        // manage uploaded files (grid_id check for master-detail fix || subgrid check)
        if (count($_FILES) && ($_REQUEST["grid_id"] == $grid_id || "_" . $_REQUEST["subgrid"] == $grid_id)) {
            $files = array_keys($_FILES);
            $fileElementName = $files[0];
            if (!empty($_FILES[$fileElementName]['error'])) {
                switch ($_FILES[$fileElementName]['error']) {
                    case '1':
                        $error = 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
                        break;
                    case '2':
                        $error = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
                        break;
                    case '3':
                        $error = 'The uploaded file was only partially uploaded';
                        break;
                    case '4':
                        $error = 'No file was uploaded.';
                        break;
                    case '6':
                        $error = 'Missing a temporary folder';
                        break;
                    case '7':
                        $error = 'Failed to write file to disk';
                        break;
                    case '8':
                        $error = 'File upload stopped by extension';
                        break;
                    case '999':
                    default:
                        $error = 'No error code avaiable';
                }
            } elseif (empty($_FILES[$fileElementName]['tmp_name']) || $_FILES[$fileElementName]['tmp_name'] == 'none') {
                $error = 'No file was uploaded';
            } else {
                foreach ($this->options["colModel"] as $c) {
                    if ($c["upload_dir"] != "" && $c["name"] . "_file" == $fileElementName) {
                        $tmp_name = $_FILES[$fileElementName]["tmp_name"];
                        $name = $_FILES[$fileElementName]["name"];
                        $uploads_dir = $c["upload_dir"];
                        @mkdir($uploads_dir, 0755, true);
                        // set to rename file by default
                        if (empty($c["editrules"]["ifexist"])) {
                            $c["editrules"]["ifexist"] = "rename";
                        }
                        // check if required
                        if ($c["editrules"]["ifexist"] == "error") {
                            if (file_exists("{$uploads_dir}/{$name}")) {
                                $error = "File already exist: {$uploads_dir}/{$name}";
                                break;
                            }
                        } else {
                            if ($c["editrules"]["ifexist"] == "rename") {
                                // rename file if exist
                                $ext = strrchr($name, '.');
                                $prefix = substr($name, 0, -strlen($ext));
                                $i = 0;
                                while (file_exists("{$uploads_dir}/{$name}")) {
                                    $name = $prefix . "_" . ++$i . $ext;
                                }
                            }
                        }
                        if (@move_uploaded_file($tmp_name, "{$uploads_dir}/{$name}")) {
                            $msg = "{$uploads_dir}/{$name}";
                        } else {
                            $error = "Unable to move to desired folder {$uploads_dir}/{$name}";
                        }
                        break;
                    }
                }
            }
            echo "{";
            echo "error: '" . $error . "',";
            echo "msg: '" . $msg . "'";
            echo "}//";
            # fix for upload lib, it get response from doc body that include <canvas>
            die;
        }
        ### P-END ###
        if (isset($_POST['oper'])) {
            $op = $_POST['oper'];
            $data = $_POST;
            $pk_field = $this->options["colModel"][0]["index"];
            // fix for dialog edit v/s inline edit
            $id = isset($data[$pk_field]) ? $data[$pk_field] : $data["id"];
            // fix for mssql utf8 fix
            if (strpos($this->db_driver, "mssql") !== false) {
                $data = array_utf8_decode_recursive($data);
            }
            // formatters array for k->v
            $is_numeric = array();
            // reformat date w.r.t mysql
            foreach ($this->options["colModel"] as $c) {
                // don't fix vars that are not posted (celledit mode)
                if (!isset($data[$c["index"]])) {
                    continue;
                }
                // fix for short weekday name
                if (strstr($c["formatoptions"]["newformat"], "D")) {
                    $data[$c["index"]] = str_ireplace(array("sun", "mon", "tue", "wed", "thu", "fri", "sat"), "", $data[$c["index"]]);
                    $data[$c["index"]] = trim($data[$c["index"]]);
                }
                // fix for d/m/Y date format. strtotime expects m/d/Y
                if (strstr($c["formatoptions"]["newformat"], "d/m/Y")) {
                    $tmp = explode("/", $data[$c["index"]]);
                    $data[$c["index"]] = $tmp[1] . "/" . $tmp[0] . "/" . $tmp[2];
                }
                // put zeros for blank date field
                if (($c["formatter"] == "date" || $c["formatter"] == "datetime") && (empty($data[$c["index"]]) || $data[$c["index"]] == "//")) {
                    $data[$c["index"]] = "NULL";
                } else {
                    if ($c["isnull"] && empty($data[$c["index"]])) {
                        $data[$c["index"]] = "NULL";
                    } else {
                        if ($c["formatter"] == "date") {
                            $data[$c["index"]] = date("Y-m-d", strtotime($data[$c["index"]]));
                        } else {
                            if ($c["formatter"] == "datetime") {
                                $data[$c["index"]] = date("Y-m-d H:i:s", strtotime($data[$c["index"]]));
                            } else {
                                if ($c["formatter"] == "autocomplete" && $c["index"] != $c["formatoptions"]["update_field"]) {
                                    unset($data[$c["index"]]);
                                } else {
                                    if ($c["formatter"] == "password" && $data[$c["index"]] == "*****") {
                                        unset($data[$c["index"]]);
                                    }
                                }
                            }
                        }
                    }
                }
                // isnumeric check for sql '' issue
                if ($c["isnum"] === true) {
                    $is_numeric[$c["index"]] = true;
                }
            }
            // handle grid operations of CRUD
            switch ($op) {
                ### P ###
                case "autocomplete":
                    $field = $data['element'];
                    $term = $data['term'];
                    foreach ($this->options["colModel"] as $c) {
                        if ($c["index"] == $field) {
                            // if subqurey
                            if (preg_match('/SELECT (.*) \\((.*)\\) (.*)/', $c["formatoptions"]["sql"], $match)) {
                                if (preg_match('/SELECT .* \\((.*)\\) (.*) WHERE (.*)/', $c["formatoptions"]["sql"], $match)) {
                                    $cond = "AND";
                                } else {
                                    $cond = "WHERE";
                                }
                            } else {
                                if (stristr($c["formatoptions"]["sql"], " WHERE ")) {
                                    $cond = "AND";
                                } else {
                                    $cond = "WHERE";
                                }
                            }
                            $sql = $c["formatoptions"]["sql"] . " {$cond} {$c["formatoptions"]["search_on"]} like '{$term}%'";
                            $result = $this->execute_query($sql);
                            if ($this->con) {
                                $rows = $result->GetArray();
                                foreach ($rows as $key => $row) {
                                    $arr = array();
                                    $arr['id'] = isset($row["K"]) ? $row["K"] : $row["k"];
                                    $arr['label'] = isset($row["V"]) ? $row["V"] : $row["v"];
                                    $arr['value'] = isset($row["V"]) ? $row["V"] : $row["v"];
                                    $data_arr[] = $arr;
                                }
                            } else {
                                while ($row = mysql_fetch_assoc($result)) {
                                    $arr = array();
                                    $arr['id'] = $row['k'];
                                    $arr['label'] = $row['v'];
                                    $arr['value'] = $row['v'];
                                    $data_arr[] = $arr;
                                }
                            }
                            header('Content-type: application/json');
                            echo json_encode($data_arr);
                            die;
                        }
                    }
                    break;
                    ### P ###
                ### P ###
                case "clone":
                    // only clone if grid id is matched (fix for master-detail)
                    if ($data["grid_id"] != $grid_id) {
                        break;
                    }
                    $src_id = $data['id'];
                    // get columns to build INSERT - SELECT query
                    $sql = "SELECT * FROM " . $this->table . " LIMIT 1 OFFSET 0";
                    $sql = $this->prepare_sql($sql, $this->db_driver);
                    $result = $this->execute_query($sql);
                    // and exclude PK
                    if ($this->con) {
                        $arr = $result->FetchRow();
                        foreach ($arr as $k => $rs) {
                            if ($k != $pk_field) {
                                $f[] = $k;
                            }
                        }
                    } else {
                        $numfields = mysql_num_fields($result);
                        for ($i = 0; $i < $numfields; $i++) {
                            $k = mysql_field_name($result, $i);
                            if ($k != $pk_field) {
                                $f[] = $k;
                            }
                        }
                    }
                    // custom onclone event execution
                    if (!empty($this->events["on_clone"])) {
                        $func = $this->events["on_clone"][0];
                        $obj = $this->events["on_clone"][1];
                        $continue = $this->events["on_clone"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $src_id, "params" => &$f));
                        } else {
                            call_user_func($func, array($pk_field => $src_id, "params" => &$f));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    $fields_str = implode(",", $f);
                    $sql = "INSERT INTO {$this->table} ({$fields_str}) SELECT {$fields_str} FROM {$this->table} WHERE {$pk_field} = {$src_id}";
                    $insert_id = $this->execute_query($sql, "insert_id");
                    if (intval($insert_id) > 0) {
                        $res = array("id" => $insert_id, "success" => true);
                    } else {
                        $res = array("id" => 0, "success" => false);
                    }
                    echo json_encode($res);
                    break;
                case "add":
                    if ($pk_field != "id") {
                        unset($data['id']);
                    }
                    unset($data['oper']);
                    $update_str = array();
                    ### P ###
                    // custom oninsert event execution
                    if (!empty($this->events["on_insert"])) {
                        $func = $this->events["on_insert"][0];
                        $obj = $this->events["on_insert"][1];
                        $continue = $this->events["on_insert"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $id, "params" => &$data));
                        } else {
                            call_user_func($func, array($pk_field => $id, "params" => &$data));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    foreach ($data as $k => $v) {
                        // skip first column while insert, unless autoid = false
                        if ($k == $pk_field && $this->options["colModel"][0]["autoid"] !== false) {
                            continue;
                        }
                        $k = addslashes($k);
                        $v = $this->escape_string($v);
                        $v = $v == "NULL" || $is_numeric[$k] === true ? $v : "'{$v}'";
                        $values_str[] = "{$v}";
                        // add tilde sign for mysql
                        if (strpos($this->db_driver, "mysql") !== false || !isset($this->db_driver)) {
                            $k = "`{$k}`";
                        }
                        $fields_str[] = "{$k}";
                    }
                    $insert_str = "(" . implode(",", $fields_str) . ") VALUES (" . implode(",", $values_str) . ")";
                    $sql = "INSERT INTO {$this->table} {$insert_str}";
                    $insert_id = $this->execute_query($sql, "insert_id");
                    ### P ###
                    // custom onupdate event execution
                    if (!empty($this->events["on_after_insert"])) {
                        $func = $this->events["on_after_insert"][0];
                        $obj = $this->events["on_after_insert"][1];
                        $continue = $this->events["on_after_insert"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $insert_id, "params" => &$data));
                        } else {
                            call_user_func($func, array($pk_field => $insert_id, "params" => &$data));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    // for inline row addition, return insert id to update PK of grid (e.g. order_id#33)
                    if ($id == "new_row") {
                        die($pk_field . "#" . $insert_id);
                    }
                    // return JSON response for insert id
                    if (intval($insert_id) > 0) {
                        $res = array("id" => $insert_id, "success" => true);
                    } else {
                        $res = array("id" => 0, "success" => false);
                    }
                    echo json_encode($res);
                    break;
                case "edit":
                    //pr($_POST);
                    if ($pk_field != "id") {
                        unset($data['id']);
                    }
                    unset($data['oper']);
                    $update_str = array();
                    ### P ###
                    // custom onupdate event execution
                    if (!empty($this->events["on_update"])) {
                        $func = $this->events["on_update"][0];
                        $obj = $this->events["on_update"][1];
                        $continue = $this->events["on_update"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $id, "params" => &$data));
                        } else {
                            call_user_func($func, array($pk_field => $id, "params" => &$data));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    foreach ($data as $k => $v) {
                        $k = addslashes($k);
                        // skip PK in update sql
                        if ($k == $pk_field) {
                            continue;
                        }
                        // add tilde sign for mysql
                        if (strpos($this->db_driver, "mysql") !== false || !isset($this->db_driver)) {
                            $k = "`{$k}`";
                        }
                        $v = $this->escape_string($v);
                        // dont update blank fields in case of bulk edit
                        if (strstr($id, ",") !== false && ($v === "" || $v == "NULL")) {
                            continue;
                        }
                        $v = $v == "NULL" || $is_numeric[$k] === true ? $v : "'{$v}'";
                        $update_str[] = "{$k}={$v}";
                    }
                    // don't run update if no field is changed (in bulk edit)
                    if (count($update_str) == 0) {
                        break;
                    }
                    $update_str = "SET " . implode(",", $update_str);
                    $id = "'" . implode("','", explode(",", $id)) . "'";
                    $sql = "UPDATE {$this->table} {$update_str} WHERE {$pk_field} IN ({$id})";
                    $ret = $this->execute_query($sql);
                    ### P ###
                    // custom on after update event execution
                    if (!empty($this->events["on_after_update"])) {
                        $func = $this->events["on_after_update"][0];
                        $obj = $this->events["on_after_update"][1];
                        $continue = $this->events["on_after_update"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $id, "params" => &$data));
                        } else {
                            call_user_func($func, array($pk_field => $id, "params" => &$data));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    // return JSON response for update (passing id that was updated)
                    if ($ret) {
                        $res = array("id" => $id, "success" => true);
                    } else {
                        $res = array("id" => 0, "success" => false);
                    }
                    echo json_encode($res);
                    break;
                case "del":
                    // row to delete is passed as id
                    $id = $data["id"];
                    ### P ###
                    // custom on delete event execution
                    if (!empty($this->events["on_delete"])) {
                        $func = $this->events["on_delete"][0];
                        $obj = $this->events["on_delete"][1];
                        $continue = $this->events["on_delete"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $id));
                        } else {
                            call_user_func($func, array($pk_field => $id));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    $id = "'" . implode("','", explode(",", $id)) . "'";
                    $sql = "DELETE FROM {$this->table} WHERE {$pk_field} IN ({$id})";
                    $this->execute_query($sql);
                    ### P ###
                    // custom on after delete event execution
                    if (!empty($this->events["on_after_delete"])) {
                        $func = $this->events["on_after_delete"][0];
                        $obj = $this->events["on_after_delete"][1];
                        $continue = $this->events["on_after_delete"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array($pk_field => $id));
                        } else {
                            call_user_func($func, array($pk_field => $id));
                        }
                        if (!$continue) {
                            break;
                        }
                    }
                    break;
            }
            die;
        }
        // apply search conditions (where clause)
        $wh = "";
        if (!isset($_REQUEST['_search'])) {
            $_REQUEST['_search'] = "";
        }
        $searchOn = $this->strip($_REQUEST['_search']);
        if ($searchOn == 'true') {
            $fld = $this->strip($_REQUEST['searchField']);
            $cols = array();
            foreach ($this->options["colModel"] as $col) {
                $cols[] = $col["index"];
            }
            // quick search bar
            if (!$fld) {
                $searchstr = $this->strip($_REQUEST['filters']);
                // persist search string
                $_SESSION["jqgrid_{$this->id}_searchstr"] = $searchstr;
                $wh = $this->construct_where($searchstr);
            } else {
                if (in_array($fld, $cols)) {
                    $fldata = $this->strip($_REQUEST['searchString']);
                    $foper = $this->strip($_REQUEST['searchOper']);
                    // costruct where
                    $wh .= " AND " . $fld;
                    switch ($foper) {
                        case "eq":
                            if (is_numeric($fldata)) {
                                $wh .= " = " . $fldata;
                            } else {
                                $wh .= " = '" . $fldata . "'";
                            }
                            break;
                        case "ne":
                            if (is_numeric($fldata)) {
                                $wh .= " <> " . $fldata;
                            } else {
                                $wh .= " <> '" . $fldata . "'";
                            }
                            break;
                        case "lt":
                            if (is_numeric($fldata)) {
                                $wh .= " < " . $fldata;
                            } else {
                                $wh .= " < '" . $fldata . "'";
                            }
                            break;
                        case "le":
                            if (is_numeric($fldata)) {
                                $wh .= " <= " . $fldata;
                            } else {
                                $wh .= " <= '" . $fldata . "'";
                            }
                            break;
                        case "gt":
                            if (is_numeric($fldata)) {
                                $wh .= " > " . $fldata;
                            } else {
                                $wh .= " > '" . $fldata . "'";
                            }
                            break;
                        case "ge":
                            if (is_numeric($fldata)) {
                                $wh .= " >= " . $fldata;
                            } else {
                                $wh .= " >= '" . $fldata . "'";
                            }
                            break;
                        case "ew":
                            $wh .= " LIKE '%" . $fldata . "'";
                            break;
                        case "en":
                            $wh .= " NOT LIKE '%" . $fldata . "'";
                            break;
                        case "cn":
                            $wh .= " LIKE '%" . $fldata . "%'";
                            break;
                        case "nc":
                            $wh .= " NOT LIKE '%" . $fldata . "%'";
                            break;
                        case "in":
                            $wh .= " IN (" . $fldata . ")";
                            break;
                        case "ni":
                            $wh .= " NOT IN (" . $fldata . ")";
                            break;
                        case "nu":
                            $wh .= " IS NULL";
                            break;
                        case "nn":
                            $wh .= " IS NOT NULL";
                            break;
                        case "bw":
                        default:
                            $fldata .= "%";
                            $wh .= " LIKE '" . $fldata . "'";
                            break;
                    }
                }
            }
            // setting to persist where clause in export option
            $_SESSION["jqgrid_{$grid_id}_filter"] = $wh;
            $_SESSION["jqgrid_{$grid_id}_filter_request"] = $_REQUEST["filters"];
        } elseif ($searchOn == 'false') {
            unset($_SESSION["jqgrid_{$grid_id}_filter"]);
            unset($_SESSION["jqgrid_{$grid_id}_filter_request"]);
        }
        // generate main json
        if (isset($_GET['jqgrid_page'])) {
            $page = $_GET['jqgrid_page'];
            // get the requested page
            $limit = $_GET['rows'];
            // get how many rows we want to have into the grid
            $sidx = $_GET['sidx'];
            // get index row - i.e. user click to sort
            $sord = $_GET['sord'];
            // get the direction
            if (!$sidx) {
                $sidx = 1;
            }
            if (!$limit) {
                $limit = 20;
            }
            // persist for export data
            if (isset($_GET["export"])) {
                $sidx = $_SESSION["jqgrid_{$grid_id}_sort_by"];
                $sord = $_SESSION["jqgrid_{$grid_id}_sort_order"];
                $limit = $_SESSION["jqgrid_{$grid_id}_rows"];
            } else {
                $_SESSION["jqgrid_{$grid_id}_sort_by"] = $sidx;
                $_SESSION["jqgrid_{$grid_id}_sort_order"] = $sord;
                $_SESSION["jqgrid_{$grid_id}_rows"] = $limit;
            }
            ### P ###
            // if export option is requested
            if (isset($_GET["export"])) {
                set_time_limit(0);
                $arr = array();
                // export data array (if grid loaded from array)
                if (is_array($this->table)) {
                    $t = $this->table;
                    foreach ($t[0] as $k => $v) {
                        $temp[$k] = ucwords($k);
                    }
                    $arr[] = $temp;
                    foreach ($t as $key => $value) {
                        $arr[] = $value;
                    }
                    // custom export function if needed
                    if (!empty($this->events["on_export"])) {
                        $func = $this->events["on_export"][0];
                        $obj = $this->events["on_export"][1];
                        $continue = $this->events["on_export"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array("data" => $arr, "grid" => &$this));
                        } else {
                            call_user_func($func, array("data" => $arr, "grid" => &$this));
                        }
                        if (!$continue) {
                            exit(0);
                        }
                    }
                } else {
                    // by default export all
                    $export_where = "";
                    if ($this->options["export"]["range"] == "filtered") {
                        $export_where = $_SESSION["jqgrid_{$grid_id}_filter"];
                    }
                    $limit_sql = "";
                    if ($this->options["export"]["paged"] == "1") {
                        $offset = $limit * $page - $limit;
                        // do not put $limit*($page - 1)
                        if ($offset < 0) {
                            $offset = 0;
                        }
                        $limit_sql = "LIMIT {$limit} OFFSET {$offset}";
                    }
                    // if sql is set on on_select event
                    if (!empty($this->internal["sql"])) {
                        $SQL = $this->internal["sql"] . " {$limit_sql}";
                    } else {
                        if (($p = stripos($this->select_command, "GROUP BY")) !== false) {
                            $start = substr($this->select_command, 0, $p);
                            $end = substr($this->select_command, $p);
                            $SQL = $start . $export_where . $end . " ORDER BY {$sidx} {$sord} {$limit_sql}";
                        } else {
                            $SQL = $this->select_command . $export_where . " ORDER BY {$sidx} {$sord} {$limit_sql}";
                        }
                    }
                    // custom export function if needed
                    if (!empty($this->events["on_export"])) {
                        $func = $this->events["on_export"][0];
                        $obj = $this->events["on_export"][1];
                        $continue = $this->events["on_export"][2];
                        if ($obj) {
                            call_user_func(array($obj, $func), array("sql" => $SQL, "grid" => &$this));
                        } else {
                            call_user_func($func, array("sql" => $SQL, "grid" => &$this));
                        }
                        if (!$continue) {
                            exit(0);
                        }
                    }
                    $SQL = $this->prepare_sql($SQL, $this->db_driver);
                    $result = $this->execute_query($SQL);
                    foreach ($this->options["colModel"] as $c) {
                        $header[$c["name"]] = $c["title"];
                    }
                    $arr[] = $header;
                    if ($this->con) {
                        $rows = $result->GetRows();
                        foreach ($rows as $row) {
                            $export_data = array();
                            foreach ($header as $k => $v) {
                                $export_data[$k] = $row[$k];
                            }
                            $arr[] = $export_data;
                        }
                    } else {
                        while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
                            $export_data = array();
                            foreach ($header as $k => $v) {
                                $export_data[$k] = $row[$k];
                            }
                            $arr[] = $export_data;
                        }
                    }
                }
                $col_widths = array();
                // export only selected columns
                $cols_not_to_export = array();
                $cols_to_export = array();
                if ($this->options["colModel"]) {
                    foreach ($this->options["colModel"] as $c) {
                        // column chooser integration with export
                        if (isset($_COOKIE["jqgrid_colchooser"])) {
                            $colchooser = explode(",", $_COOKIE["jqgrid_colchooser"]);
                            if (!in_array($c["name"], $colchooser)) {
                                $c["export"] = false;
                            }
                        }
                        if ($c["export"] === false) {
                            $cols_not_to_export[] = $c["name"];
                        } else {
                            $cols_to_export[] = $c["name"];
                            $col_widths[$c["name"]] = !empty($c["width"]) ? $c["width"] : 'auto';
                        }
                    }
                }
                // custom on_data_display event execution (for export)
                if (!empty($this->events["on_data_display"])) {
                    $func = $this->events["on_data_display"][0];
                    $obj = $this->events["on_data_display"][1];
                    // remove header
                    $h = array_shift($arr);
                    if ($obj) {
                        call_user_func(array($obj, $func), array("params" => &$arr));
                    } else {
                        call_user_func($func, array("params" => &$arr));
                    }
                    // add header
                    array_unshift($arr, $h);
                }
                // fix for d/m/Y date format in export. strtotime expects m/d/Y
                foreach ($this->options["colModel"] as $c) {
                    foreach ($arr as &$rec) {
                        // skip header from date format conversion
                        if ($rec === $arr[0]) {
                            continue;
                        }
                        // show masked data in password
                        if (isset($c["formatter"]) && $c["formatter"] == "password") {
                            $rec[$c["name"]] = "*****";
                        }
                        if (!empty($rec[$c["name"]]) && ($c["formatter"] == "date" || $c["formatter"] == "datetime")) {
                            $dt = $rec[$c["name"]];
                            $js_dt_fmt = $c["formatoptions"]["newformat"];
                            $js_dt_fmt = str_replace("yy", "Y", $js_dt_fmt);
                            $js_dt_fmt = str_replace("mm", "m", $js_dt_fmt);
                            $js_dt_fmt = str_replace("dd", "d", $js_dt_fmt);
                            $rec[$c["name"]] = date($js_dt_fmt, strtotime($dt));
                        }
                        ### P ###
                        // Replace condition data in pdf export
                        $col_name = $c["name"];
                        if (isset($c["default"]) && !isset($rec[$col_name])) {
                            $rec[$col_name] = $c["default"];
                        }
                        // link data in grid to any given url
                        if (!empty($link_c["default"])) {
                            // replace any param in link e.g. http://domain.com?id={id} given that, there is a $col["name"] = "id" exist
                            $rec[$col_name] = $this->replace_row_data($rec, $c["default"]);
                        }
                        // check conditional data
                        if (!empty($c["condition"][0])) {
                            $r = true;
                            // replace {} placeholders from connditional data
                            $c["condition"][1] = $this->replace_row_data($rec, $c["condition"][1]);
                            $c["condition"][2] = $this->replace_row_data($rec, $c["condition"][2]);
                            $row = $rec;
                            eval("\$r = " . $c["condition"][0] . ";");
                            $rec[$col_name] = $r ? $c["condition"][1] : $c["condition"][2];
                            $rec[$col_name] = strip_tags($rec[$col_name]);
                        }
                        // check data filter (alternate of grid on_data_display, but for current column)
                        if (!empty($c["on_data_display"])) {
                            $func = $c["on_data_display"][0];
                            $obj = $c["on_data_display"][1];
                            if ($obj) {
                                $row[$col_name] = call_user_func(array($obj, $func), $rec);
                            } else {
                                $row[$col_name] = call_user_func($func, $rec);
                            }
                        }
                    }
                }
                // remove db columns as well as virtual columns
                if (!empty($cols_to_export)) {
                    $export_arr = array();
                    foreach ($arr as $arr_item) {
                        foreach ($arr_item as $k => $i) {
                            if (!in_array($k, $cols_to_export)) {
                                unset($arr_item[$k]);
                            }
                        }
                        $export_arr[] = $arr_item;
                    }
                    $arr = $export_arr;
                }
                // fix for mssql utf8 fix
                if (strpos($this->db_driver, "mssql") !== false) {
                    $arr = array_utf8_encode_recursive($arr);
                }
                if (!$this->options["export"]["filename"]) {
                    $this->options["export"]["filename"] = $grid_id;
                }
                if (!$this->options["export"]["sheetname"]) {
                    $this->options["export"]["sheetname"] = ucwords($grid_id) . " Sheet";
                }
                // fix for ie - http://support.microsoft.com/kb/316431
                if (preg_match('/(?i)msie /', $_SERVER['HTTP_USER_AGENT'])) {
                    header('Cache-control: cache,must-revalidate');
                }
                if ($this->options["export"]["format"] == "pdf") {
                    if ($this->options["export"]["render_type"] == "html") {
                        $html = "";
                        // if customized pdf render is defined, use that
                        if (!empty($this->events["on_render_pdf"])) {
                            $func = $this->events["on_render_pdf"][0];
                            $obj = $this->events["on_render_pdf"][1];
                            if ($obj) {
                                $html = call_user_method($func, $obj, array("grid" => $this, "data" => $arr));
                            } else {
                                $html = call_user_func($func, array("grid" => $this, "data" => $arr));
                            }
                        } else {
                            $html .= "<h1>" . $this->options["export"]["heading"] . "</h1>";
                            $html .= '<table border="0" cellpadding="4" cellspacing="2">';
                            $i = 0;
                            foreach ($arr as $v) {
                                $shade = $i++ % 2 ? 'bgcolor="#efefef"' : '';
                                $html .= "<tr>";
                                foreach ($v as $d) {
                                    // bold header
                                    if ($i == 1) {
                                        $html .= "<td bgcolor=\"lightgrey\"><strong>{$d}</strong></td>";
                                    } else {
                                        $html .= "<td {$shade}>{$d}</td>";
                                    }
                                }
                                $html .= "</tr>";
                            }
                            $html .= "</table>";
                        }
                    }
                    $orientation = $this->options["export"]["orientation"];
                    if ($orientation == "landscape") {
                        $orientation = "L";
                    } else {
                        $orientation = "P";
                    }
                    $paper = $this->options["export"]["paper"];
                    // Using opensource TCPdf lib
                    // for more options visit http://www.tcpdf.org/examples.php
                    require_once 'tcpdf/config/lang/eng.php';
                    require_once 'tcpdf/class.TCPDF.EasyTable.php';
                    // create new PDF document
                    $pdf = new TCPDF_EasyTable($orientation, PDF_UNIT, $paper, true, 'UTF-8', false);
                    // set document information
                    $pdf->SetCreator("www.phpgrid.org");
                    $pdf->SetAuthor('www.phpgrid.org');
                    $pdf->SetTitle('www.phpgrid.org');
                    $pdf->SetSubject($this->options["caption"]);
                    $pdf->SetKeywords('www.phpgrid.org');
                    // remove default header/footer
                    $pdf->setPrintHeader(true);
                    $pdf->setPrintFooter(true);
                    // set default monospaced font
                    $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
                    $pdf->setFontSubsetting(false);
                    //set margins
                    $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
                    //set auto page breaks
                    $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
                    //set image scale factor
                    $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
                    // set some language dependent data:
                    // lines for rtl pdf generation
                    if ($this->options["direction"] == "rtl") {
                        $lg = array();
                        $lg['a_meta_charset'] = 'UTF-8';
                        $lg['a_meta_dir'] = 'rtl';
                        $lg['a_meta_language'] = 'fa';
                        $lg['w_page'] = 'page';
                    }
                    $pdf->setLanguageArray($lg);
                    // To set your custom font
                    // $fontname = $pdf->addTTFfont('/path-to-font/DejaVuSans.ttf', 'TrueTypeUnicode', '', 32);
                    // set font http://www.tcexam.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045
                    # Table parameters
                    $pdf->SetFont('helvetica', '', 12);
                    // for special charset language, uncoment this line
                    // $pdf->SetFont('cid0jp', '', 10);
                    // add a page
                    $pdf->AddPage();
                    // output the HTML content
                    if ($this->options["export"]["render_type"] == "html") {
                        $pdf->writeHTML($html, true, false, true, false, '');
                        $pdf->Output($this->options["export"]["filename"] . ".pdf", 'I');
                        die;
                    }
                    $pdf->SetY(10, true);
                    $pdf->Cell(0, 15, $this->options["export"]["heading"], 0, 1);
                    $pdf->SetHeaderCellsFontStyle('');
                    // 'b'
                    $pdf->SetHeaderCellsFillColor(150, 150, 150);
                    $pdf->SetHeaderCellsFontColor(0, 0, 0);
                    $pdf->SetFillColor(240, 240, 240);
                    // for cells background
                    $pdf->SetCellFontColor(0, 0, 0);
                    // auto set column widths based on grid column width
                    $margins = $pdf->GetMargins();
                    $pdf_page_width = $pdf->GetPageWidth() - $margins['left'] - $margins['right'];
                    $total_width = 0;
                    foreach ($col_widths as $key => $value) {
                        $total_width += $value;
                    }
                    $new_widths = array();
                    foreach ($col_widths as $key => $value) {
                        $new_widths[$key] = $pdf_page_width * ($value / $total_width);
                        $new_widths[] = $pdf_page_width * ($value / $total_width);
                    }
                    $pdf->SetCellWidths($new_widths);
                    $pdf->SetCellFillStyle(2);
                    $pdf->SetCellPadding(1);
                    $pdf->SetCellMinimumHeight(null);
                    // if customized pdf render is defined, use that
                    if (!empty($this->events["on_render_pdf"])) {
                        $func = $this->events["on_render_pdf"][0];
                        $obj = $this->events["on_render_pdf"][1];
                        if ($obj) {
                            call_user_func(array($obj, $func), array("pdf" => &$pdf, "data" => &$arr));
                        } else {
                            call_user_func($func, array("pdf" => &$pdf, "data" => &$arr));
                        }
                    }
                    $h = $arr[0];
                    array_shift($arr);
                    $pdf->EasyTable($arr, $h);
                    if (strstr($this->options["export"]["filename"], ".pdf") === false) {
                        $this->options["export"]["filename"] .= ".pdf";
                    }
                    //Close and output PDF document
                    $pdf->Output($this->options["export"]["filename"], 'I');
                    die;
                } else {
                    if ($this->options["export"]["format"] == "csv") {
                        if (strstr($this->options["export"]["filename"], ".csv") === false) {
                            $this->options["export"]["filename"] .= ".csv";
                        }
                        header('Content-Type: text/csv');
                        header('Content-Disposition: attachment;filename=' . $this->options["export"]["filename"]);
                        $fp = fopen('php://output', 'w');
                        foreach ($arr as $key => $value) {
                            fputcsv($fp, $value);
                        }
                        die;
                    } else {
                        include_once "php-export-data.class.php";
                        $excel = new ExportDataExcel('browser');
                        if (strstr($this->options["export"]["filename"], ".xls") === false && strstr($this->options["export"]["filename"], ".xlsx") === false) {
                            $this->options["export"]["filename"] .= ".xls";
                        }
                        $excel->filename = $this->options["export"]["filename"];
                        $excel->initialize();
                        foreach ($arr as $row) {
                            $excel->addRow($row);
                        }
                        $excel->finalize();
                        die;
                    }
                }
            }
            // if defined in on_select event
            if (!empty($this->internal["sql_count"])) {
                $sql_count = $this->internal["sql_count"];
            } else {
                if (!empty($this->select_count)) {
                    $sql_count = $this->select_count . $wh;
                } else {
                    if (($p = stripos($this->select_command, "GROUP BY")) !== false) {
                        $sql_count = $this->select_command;
                        $p = stripos($sql_count, "GROUP BY");
                        $start_q = substr($sql_count, 0, $p);
                        $end_q = substr($sql_count, $p);
                        $sql_count = "SELECT count(*) as c FROM ({$start_q} {$wh} {$end_q}) pg_tmp";
                    } else {
                        $sql_count = $this->select_command . $wh;
                        $sql_count = "SELECT count(*) as c FROM (" . $sql_count . ") pg_tmp";
                    }
                }
            }
            # print_r($sql_count);
            $result = $this->execute_query($sql_count);
            if ($this->con) {
                $row = $result->FetchRow();
            } else {
                $row = mysql_fetch_array($result, MYSQL_ASSOC);
            }
            $count = $row['c'];
            // fix for oracle, alias in capitals
            if (empty($count)) {
                $count = $row['C'];
            }
            if ($count > 0) {
                $total_pages = ceil($count / $limit);
            } else {
                $total_pages = 0;
            }
            if ($page > $total_pages) {
                $page = $total_pages;
            }
            $start = $limit * $page - $limit;
            // do not put $limit*($page - 1)
            if ($start < 0) {
                $start = 0;
            }
            $responce = new stdClass();
            $responce->page = $page;
            $responce->total = $total_pages;
            $responce->records = $count;
            if (!empty($this->internal["sql"])) {
                $SQL = $this->internal["sql"] . " LIMIT {$limit} OFFSET {$start}";
            } else {
                if (($p = stripos($this->select_command, "GROUP BY")) !== false) {
                    $start_q = substr($this->select_command, 0, $p);
                    $end_q = substr($this->select_command, $p);
                    $SQL = "{$start_q} {$wh} {$end_q} ORDER BY {$sidx} {$sord} LIMIT {$limit} OFFSET {$start}";
                } else {
                    $SQL = $this->select_command . $wh . " ORDER BY {$sidx} {$sord} LIMIT {$limit} OFFSET {$start}";
                }
            }
            $SQL = $this->prepare_sql($SQL, $this->db_driver);
            $result = $this->execute_query($SQL);
            if ($this->con) {
                $rows = $result->GetRows();
                // simulate artificial paging for mssql
                if (count($rows) > $limit) {
                    $rows = array_slice($rows, count($rows) - $limit);
                }
            } else {
                $rows = array();
                while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
                    $rows[] = $row;
                }
            }
            ### P ###
            // custom on_data_display event execution
            if (!empty($this->events["on_data_display"])) {
                $func = $this->events["on_data_display"][0];
                $obj = $this->events["on_data_display"][1];
                if ($obj) {
                    call_user_func(array($obj, $func), array("params" => &$rows));
                } else {
                    call_user_func($func, array("params" => &$rows));
                }
            }
            // preserve userdata for response
            if (!empty($rows["userdata"])) {
                $userdata = $rows["userdata"];
                unset($rows["userdata"]);
            }
            foreach ($rows as $row) {
                $orig_row = $row;
                // apply php level formatter for image url 30.12.10
                foreach ($this->options["colModel"] as $c) {
                    $col_name = $c["name"];
                    ### P ###
                    if (isset($c["default"]) && !isset($row[$col_name])) {
                        $row[$col_name] = $c["default"];
                    }
                    // link data in grid to any given url
                    if (!empty($c["default"])) {
                        // replace any param in link e.g. http://domain.com?id={id} given that, there is a $col["name"] = "id" exist
                        $row[$col_name] = $this->replace_row_data($orig_row, $c["default"]);
                    }
                    // check conditional data
                    if (!empty($c["condition"][0])) {
                        $r = true;
                        // replace {} placeholders from connditional data
                        $c["condition"][1] = $this->replace_row_data($orig_row, $c["condition"][1]);
                        $c["condition"][2] = $this->replace_row_data($orig_row, $c["condition"][2]);
                        eval("\$r = " . $c["condition"][0] . ";");
                        $row[$col_name] = $r ? $c["condition"][1] : $c["condition"][2];
                    }
                    // check data filter (alternate of grid on_data_display, but for current column)
                    if (!empty($c["on_data_display"])) {
                        $func = $c["on_data_display"][0];
                        $obj = $c["on_data_display"][1];
                        if ($obj) {
                            $row[$col_name] = call_user_func(array($obj, $func), $row);
                        } else {
                            $row[$col_name] = call_user_func($func, $row);
                        }
                    }
                    ### P-END ###
                    // link data in grid to any given url
                    if (!empty($c["link"])) {
                        // replace any param in link e.g. http://domain.com?id={id} given that, there is a $col["name"] = "id" exist
                        // replace_row_data not used due to urlencode work
                        foreach ($this->options["colModel"] as $link_c) {
                            // if there is url in data, don't urlencode
                            if (strstr($orig_row[$link_c["name"]], "http://")) {
                                $link_row_data = $orig_row[$link_c["name"]];
                            } else {
                                $link_row_data = urlencode($orig_row[$link_c["name"]]);
                            }
                            $c["link"] = str_replace("{" . $link_c["name"] . "}", $link_row_data, $c["link"]);
                        }
                        $attr = "";
                        if (!empty($c["linkoptions"])) {
                            $attr = $c["linkoptions"];
                        }
                        // fix for mssql utf8 fix
                        if (strpos($this->db_driver, "mssql") !== false) {
                            $row[$col_name] = htmlentities(utf8_encode($row[$col_name]), ENT_QUOTES, "UTF-8");
                        } else {
                            $row[$col_name] = htmlentities($row[$col_name], ENT_QUOTES, "UTF-8");
                        }
                        // if link is made with custom date format
                        if (isset($c["formatoptions"]["newformat"])) {
                            $js_dt_fmt = $c["formatoptions"]["newformat"];
                            $js_dt_fmt = str_replace("yy", "Y", $js_dt_fmt);
                            $js_dt_fmt = str_replace("mm", "m", $js_dt_fmt);
                            $js_dt_fmt = str_replace("dd", "d", $js_dt_fmt);
                            $row[$col_name] = date($c["formatoptions"]["newformat"], strtotime($row[$col_name]));
                        }
                        $row[$col_name] = "<a {$attr} href='{$c["link"]}'>{$row[$col_name]}</a>";
                    }
                    // render row data as "src" value of <img> tag
                    if (isset($c["formatter"]) && $c["formatter"] == "image") {
                        $attr = array();
                        foreach ($c["formatoptions"] as $k => $v) {
                            $attr[] = "{$k}='{$v}'";
                        }
                        $attr = implode(" ", $attr);
                        $row[$col_name] = "<img {$attr} src='" . $row[$col_name] . "'>";
                    }
                    // show masked data in password
                    if (isset($c["formatter"]) && $c["formatter"] == "password") {
                        $row[$col_name] = "*****";
                    }
                }
                foreach ($row as $k => $r) {
                    $row[$k] = stripslashes($row[$k]);
                }
                $responce->rows[] = $row;
            }
            // set custom userdata in footer (controlled with on_data_display event)
            if (!empty($userdata)) {
                $responce->userdata = $userdata;
            }
            // fix for mssql utf8 fix
            if (strpos($this->db_driver, "mssql") !== false) {
                $responce = array_utf8_encode_recursive($responce);
            }
            echo json_encode($responce);
            die;
        }
        ### P ###
        // if loading from array
        if (is_array($this->table)) {
            $this->options["data"] = json_encode($this->table);
            $this->options["datatype"] = "local";
            $this->actions["rowactions"] = false;
            $this->actions["add"] = false;
            $this->actions["edit"] = false;
            $this->actions["delete"] = false;
        }
        // few overides - pagination fixes
        $this->options["pager"] = '#' . $grid_id . "_pager";
        $this->options["jsonReader"] = array("repeatitems" => false, "id" => "0");
        // allow/disallow edit,del operations
        if ($this->actions["edit"] === false && $this->actions["delete"] === false || $this->options["cellEdit"] === true) {
            $this->actions["rowactions"] = false;
        }
        if ($this->actions["rowactions"] !== false) {
            // CRUD operation column
            $f = false;
            $defined = false;
            foreach ($this->options["colModel"] as &$c) {
                if ($c["name"] == "act") {
                    $defined =& $c;
                }
                if (!empty($c["width"])) {
                    $f = true;
                }
            }
            // icon col fix, text links as old behavior (fixed:true, mean exact px)
            if ($this->internal["actionicon"] === true) {
                $w = $this->actions["clone"] === true ? "80" : "55";
            } else {
                $w = $this->actions["clone"] === true ? "120" : "100";
            }
            // width adjustment for row actions column
            $action_column = array("name" => "act", "fixed" => true, "align" => "center", "index" => "act", "width" => "{$w}", "sortable" => false, "search" => false, "viewable" => false);
            if (!$defined) {
                $this->options["colNames"][] = "Actions";
                $this->options["colModel"][] = $action_column;
            } else {
                $defined = array_merge($action_column, $defined);
            }
        }
        // simulate field access right options
        $str_add_form = '';
        $str_edit_form = '';
        $str_delete_form = '';
        $str_edit_access = '';
        $str_inline_access = '';
        foreach ($this->options["colModel"] as &$c) {
            // auto reload & edit for link pattern fix
            if (!empty($c["link"])) {
                $this->options["reloadedit"] = true;
                $c["formatter"] = "function(cellvalue, options, rowObject){ \n\n\t\t\t\t\t\t\t\t\t\tarr = jQuery(document).data('link_{$c["name"]}');\n\t\t\t\t\t\t\t\t\t\tif (!arr) arr = {};\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tif (jQuery(cellvalue).text() != '')\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tarr[jQuery(cellvalue).text()] = cellvalue;\n\t\t\t\t\t\t\t\t\t\t\tjQuery(document).data('link_{$c["name"]}',arr);\n\t\t\t\t\t\t\t\t\t\t\treturn arr[jQuery(cellvalue).text()];\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// fix for link text 'undefined'\n\t\t\t\t\t\t\t\t\t\t\tif (typeof(arr[cellvalue]) == 'undefined')\n\t\t\t\t\t\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\treturn arr[cellvalue];\n\t\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\t}";
                $c["unformat"] = "function(cellvalue, options, cell){return jQuery(cell).text();}";
            }
            // make readonly field while editing
            if (isset($c["editrules"]["readonly"])) {
                if ($c["editrules"]["readonly"] === true) {
                    $tag = "input";
                    if (!empty($c["edittype"])) {
                        $tag = $c["edittype"];
                    }
                    if (!empty($c["editrules"]["readonly-when"])) {
                        $cond = $c["editrules"]["readonly-when"];
                        if (!is_numeric($cond[1])) {
                            $cond[1] = '"' . $cond[1] . '"';
                        }
                        $str_edit_access .= 'if (jQuery("#tr_' . $c["index"] . ' .DataTD ' . $tag . '",formid).val() ' . $cond[0] . ' ' . $cond[1] . ')';
                        $str_inline_access .= 'if (jQuery("' . $tag . '[name=' . $c["index"] . ']:last").val() ' . $cond[0] . ' ' . $cond[1] . ')';
                    }
                    // make textbox hidden, for postback
                    $str_edit_access .= '{';
                    if ($tag == "select") {
                        $str_edit_access .= 'jQuery("#tr_' . $c["index"] . ' .DataTD",formid).append("&nbsp;" + jQuery("#tr_' . $c["index"] . ' .DataTD ' . $tag . ' option:selected",formid).text());';
                    } else {
                        $str_edit_access .= 'jQuery("#tr_' . $c["index"] . ' .DataTD",formid).append("&nbsp;" + jQuery("#tr_' . $c["index"] . ' .DataTD ' . $tag . '",formid).val());';
                    }
                    $str_edit_access .= 'jQuery("#tr_' . $c["index"] . ' .DataTD ' . $tag . '",formid).hide();';
                    // remove required (*) from readonly
                    $str_edit_access .= 'jQuery("#tr_' . $c["index"] . ' .DataTD font",formid).hide();';
                    $str_edit_access .= '}';
                    $str_inline_access .= '{';
                    $str_inline_access .= 'jQuery("' . $tag . '[name=' . $c["index"] . ']:last").hide();';
                    $str_inline_access .= 'jQuery("' . $tag . '[name=' . $c["index"] . ']:last").parent().not(":has(span)").append("<span></span>");';
                    $str_inline_access .= 'jQuery("' . $tag . '[name=' . $c["index"] . ']:last").parent().children("span").html(jQuery("' . $tag . '[name=' . $c["index"] . ']:last").val());';
                    $str_inline_access .= '}';
                }
            }
            if (!empty($c["show"])) {
                if ($c["show"]["list"] === false) {
                    $c["hidden"] = true;
                } else {
                    $c["hidden"] = false;
                }
                if ($c["formoptions"]["rowpos"]) {
                    $str_pos = '';
                    $str_pos .= 'jQuery("#TblGrid_' . $grid_id . ' tr:eq(' . ($c["formoptions"]["rowpos"] + 1) . ') td:nth-child(' . $c["formoptions"]["colpos"] * 2 . ')").html("");';
                    $str_pos .= 'jQuery("#TblGrid_' . $grid_id . ' tr:eq(' . ($c["formoptions"]["rowpos"] + 1) . ') td:nth-child(' . ($c["formoptions"]["colpos"] * 2 - 1) . ')").html("");';
                }
                if ($c["show"]["edit"] === false) {
                    $str_edit_access .= 'jQuery("#tr_' . $c["index"] . '",formid).hide();';
                    if (!empty($str_pos)) {
                        $str_edit_access .= $str_pos;
                    }
                } else {
                    $str_edit_access .= 'jQuery("#tr_' . $c["index"] . '",formid).show();';
                }
                if ($c["show"]["add"] === false) {
                    $str_add_access .= 'jQuery("#tr_' . $c["index"] . '",formid).hide();';
                    if (!empty($str_pos)) {
                        $str_add_access .= $str_pos;
                    }
                } else {
                    $str_add_access .= 'jQuery("#tr_' . $c["index"] . '",formid).show();';
                }
                if ($c["show"]["view"] === false) {
                    $str_view_access .= 'jQuery("#trv_' . $c["index"] . '").hide();';
                    if ($c["formoptions"]["rowpos"]) {
                        $str_pos = '';
                        $str_pos .= 'jQuery("#ViewTbl_' . $grid_id . ' tr:eq(' . ($c["formoptions"]["rowpos"] - 1) . ') td:nth-child(' . $c["formoptions"]["colpos"] * 2 . ')").html("");';
                        $str_pos .= 'jQuery("#ViewTbl_' . $grid_id . ' tr:eq(' . ($c["formoptions"]["rowpos"] - 1) . ') td:nth-child(' . ($c["formoptions"]["colpos"] * 2 - 1) . ')").html("");';
                        $str_view_access .= $str_pos;
                    }
                } else {
                    $str_view_access .= 'jQuery("#trv_' . $c["index"] . '").show();';
                }
                unset($c["show"]);
            }
        }
        // set before show form events
        if (!empty($this->internal["add_options"]["beforeShowForm"])) {
            $str_add_form = $str_add_access . $this->internal["add_options"]["beforeShowForm"];
        } else {
            $str_add_form = $str_add_access;
        }
        if (!empty($this->internal["edit_options"]["beforeShowForm"])) {
            $str_edit_form = $str_edit_access . $this->internal["edit_options"]["beforeShowForm"];
        } else {
            $str_edit_form = $str_edit_access;
        }
        if (!empty($this->internal["delete_options"]["beforeShowForm"])) {
            $str_delete_form = $str_delete_access . $this->internal["delete_options"]["beforeShowForm"];
        } else {
            $str_delete_form = $str_delete_access;
        }
        if (!empty($this->internal["view_options"]["beforeShowForm"])) {
            $str_view_form = $str_view_access . $this->internal["view_options"]["beforeShowForm"];
        } else {
            $str_view_form = $str_view_access;
        }
        ### P ###
        $this->options["add_options"]["beforeShowForm"] = 'function(formid) { ' . $str_add_form . ' }';
        $this->options["edit_options"]["beforeShowForm"] = 'function(formid) { ' . $str_edit_form . ' }';
        $this->options["delete_options"]["beforeShowForm"] = 'function(formid) { ' . $str_delete_form . ' }';
        // append view options beforeShowForm implementation
        $fx = "";
        if (!empty($this->options["view_options"]["beforeShowForm"])) {
            $fx = "var o=" . $this->options["view_options"]["beforeShowForm"] . "; o(formid);";
        }
        $this->options["view_options"]["beforeShowForm"] = 'function(formid) { ' . $str_view_form . $fx . ' }';
        // focus / select newly inserted row
        $this->options["add_options"]["afterComplete"] = "function (response, postdata) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tr = JSON.parse(response.responseText); \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery( document ).ajaxComplete(function() {\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').setSelection(r.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery( document ).unbind('ajaxComplete');\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}";
        // event for dialog < > navigation
        $this->options["view_options"]["afterclickPgButtons"] = 'function(formid) { ' . $str_view_access . ' }';
        ### P-END ###
        $reload_after_edit = "";
        // after save callback
        if (!empty($this->options["onAfterSave"])) {
            $reload_after_edit .= "var fx_save = {$this->options["onAfterSave"]}; fx_save();";
        }
        if ($this->options["reloadedit"] === true) {
            $reload_after_edit .= "jQuery('#{$grid_id}').jqGrid().trigger('reloadGrid',[{jqgrid_page:1}]);";
        }
        ### P ###
        if (empty($this->options["add_options"]["success_msg"])) {
            $this->options["add_options"]["success_msg"] = "Enr&eacute;gistrement ajout&eacute;";
        }
        if (empty($this->options["edit_options"]["success_msg"])) {
            $this->options["edit_options"]["success_msg"] = "Enr&eacute;gistrement mis &agrave; jour";
        }
        if (empty($this->options["edit_options"]["success_msg_bulk"])) {
            $this->options["edit_options"]["success_msg_bulk"] = "Enr&eacute;gistrements ajout&eacute;s";
        }
        if (empty($this->options["delete_options"]["success_msg"])) {
            $this->options["delete_options"]["success_msg"] = "Enr&eacute;gistrement effac&eacute";
        }
        if (empty($this->options["add_options"]["afterSubmit"])) {
            $this->options["add_options"]["afterSubmit"] = 'function(response) { if(response.status == 200)
																				{ 
																					fx_success_msg("' . $this->options["add_options"]["success_msg"] . '",1);
																			      	return [true,""];
																				} 
																			}';
        }
        if (empty($this->options["edit_options"]["afterSubmit"])) {
            $this->options["edit_options"]["afterSubmit"] = 'function(response) { if(response.status == 200)
																				{ 
																					' . $reload_after_edit . '
																					fx_success_msg("' . $this->options["edit_options"]["success_msg"] . '",1);
																			      	return [true,""];
																				} 
																			}';
        }
        if (empty($this->options["delete_options"]["afterSubmit"])) {
            $this->options["delete_options"]["afterSubmit"] = 'function(response) { if(response.status == 200)
																				{ 
																					fx_success_msg("' . $this->options["delete_options"]["success_msg"] . '",1);
																			      	return [true,""];
																				} 
																			}';
        }
        ### P-END ###
        // search options for templates
        $this->options["search_options"]["closeAfterSearch"] = true;
        $this->options["search_options"]["multipleSearch"] = $this->actions["search"] == "advance" ? true : false;
        $this->options["search_options"]["sopt"] = array('eq', 'ne', 'lt', 'le', 'gt', 'ge', 'bw', 'bn', 'in', 'ni', 'ew', 'en', 'cn', 'nc', 'nu', 'nn');
        $out = json_encode_jsfunc($this->options);
        $out = substr($out, 0, strlen($out) - 1);
        // create Edit/Delete - Save/Cancel column in grid
        if ($this->actions["rowactions"] !== false) {
            $act_links = array();
            ### P-START ###
            if ($this->internal["actionicon"] === true) {
                if ($this->actions["edit"] !== false) {
                    $act_links[] = "<a class=\"ui-custom-icon ui-icon ui-icon-pencil\" title=\"Editer la ligne\" href=\"javascript:void(0);\" onclick=\"jQuery(this).dblclick();\"></a>";
                }
                ### P ###
                if ($this->actions["clone"] === true) {
                    $act_links[] = "<a class=\"ui-custom-icon ui-icon ui-icon-copy\" title=\"Cloner la ligne\" href=\"javascript:void(0);\" onclick=\"fx_clone_row(\\'{$grid_id}\\',\\''+cl+'\\'); \"></a>";
                }
                ### P-END ###
                if ($this->actions["delete"] !== false) {
                    $act_links[] = "<a class=\"ui-custom-icon ui-icon ui-icon-trash\" title=\"Effacer la ligne\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}\\').delGridRow(\\''+cl+'\\',{errorTextFormat:function(r){ return r.responseText;}}); jQuery(\\'#delmod{$grid_id}\\').abscenter(); \"></a>";
                }
                $act_links = implode("", $act_links);
                $out .= ",'gridComplete': function()\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar ids = jQuery('#{$grid_id}').jqGrid('getDataIDs');\n\t\t\t\t\t\t\t\tfor(var i=0;i < ids.length;i++)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tvar cl = ids[i];\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbe = '{$act_links}';\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t// il_save, ilcancel, iledit are clicked for inlineNav button reset\n\t\t\t\t\t\t\t\t\tse = '<a class=\"ui-custom-icon ui-icon ui-icon-disk\" title=\"Save this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilsave\\').click(); if (jQuery(\\'#{$grid_id}\\').saveRow(\\''+cl+'\\') || jQuery(\\'.editable\\').length==0) { jQuery(this).parent().hide(); jQuery(this).parent().prev().show(); " . addslashes($reload_after_edit) . " }\"></a>';\n\t\t\t\t\t\t\t\t\tce = '<a class=\"ui-custom-icon ui-icon ui-icon-cancel\" title=\"Restore this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilcancel\\').click(); jQuery(\\'#{$grid_id}\\').restoreRow(\\''+cl+'\\'); jQuery(this).parent().hide(); jQuery(this).parent().prev().show();\"></a>';\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t// for inline add option\n\t\t\t\t\t\t\t\t\tif (ids[i].indexOf('jqg') != -1)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tse = '<a class=\"ui-custom-icon ui-icon ui-icon-disk\" title=\"Save this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilsave\\').click(); \">Save</a>';\n\t\t\t\t\t\t\t\t\t\tce = '<a class=\"ui-custom-icon ui-icon ui-icon-cancel\" title=\"Restore this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilcancel\\').click(); jQuery(this).parent().hide(); jQuery(this).parent().prev().show();\">Cancel</a>';\n\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').jqGrid('setRowData',ids[i],{act:'<span style=display:none id=\"edit_row_{$grid_id}_'+cl+'\">'+be+'</span>'+'<span id=\"save_row_{$grid_id}_'+cl+'\">'+se+ce+'</span>'});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').jqGrid('setRowData',ids[i],{act:'<span id=\"edit_row_{$grid_id}_'+cl+'\">'+be+'</span>'+'<span style=display:none id=\"save_row_{$grid_id}_'+cl+'\">'+se+ce+'</span>'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}";
            } else {
                if ($this->actions["edit"] !== false) {
                    $act_links[] = "<a title=\"Editer la ligne\" href=\"javascript:void(0);\" onclick=\"jQuery(this).dblclick();\">Edit</a>";
                }
                ### P ###
                if ($this->actions["clone"] === true) {
                    $act_links[] = "<a title=\"Cloner la ligne\" href=\"javascript:void(0);\" onclick=\"fx_clone_row(\\'{$grid_id}\\',\\''+cl+'\\'); \">Clone</a>";
                }
                ### P-END ###
                if ($this->actions["delete"] !== false) {
                    $act_links[] = "<a title=\"Effacer la ligne\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}\\').delGridRow(\\''+cl+'\\',{errorTextFormat:function(r){ return r.responseText;}}); jQuery(\\'#delmod{$grid_id}\\').abscenter(); \">Delete</a>";
                }
                $act_links = implode(" | ", $act_links);
                $out .= ",'gridComplete': function()\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\tvar ids = jQuery('#{$grid_id}').jqGrid('getDataIDs');\n\t\t\t\t\t\t\t\tfor(var i=0;i < ids.length;i++)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar cl = ids[i];\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tbe = '{$act_links}'; \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// il_save, ilcancel, iledit are clicked for inlineNav button reset\n\t\t\t\t\t\t\tse = ' <a title=\"Save this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilsave\\').click(); if (jQuery(\\'#{$grid_id}\\').saveRow(\\''+cl+'\\') || jQuery(\\'.editable\\').length==0) { jQuery(this).parent().hide(); jQuery(this).parent().prev().show(); " . addslashes($reload_after_edit) . " }\">Save</a>'; \n\t\t\t\t\t\t\tce = ' | <a title=\"Restore this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilcancel\\').click(); jQuery(\\'#{$grid_id}\\').restoreRow(\\''+cl+'\\'); jQuery(this).parent().hide(); jQuery(this).parent().prev().show();\">Cancel</a>'; \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// for inline add option\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (ids[i].indexOf('jqg') != -1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tse = ' <a title=\"Save this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilsave\\').click(); \">Save</a>'; \n\t\t\t\t\t\t\t\tce = ' | <a title=\"Restore this row\" href=\"javascript:void(0);\" onclick=\"jQuery(\\'#{$grid_id}_ilcancel\\').click(); jQuery(this).parent().hide(); jQuery(this).parent().prev().show();\">Cancel</a>'; \n\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').jqGrid('setRowData',ids[i],{act:'<span style=display:none id=\"edit_row_{$grid_id}_'+cl+'\">'+be+'</span>'+'<span id=\"save_row_{$grid_id}_'+cl+'\">'+se+ce+'</span>'});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').jqGrid('setRowData',ids[i],{act:'<span id=\"edit_row_{$grid_id}_'+cl+'\">'+be+'</span>'+'<span style=display:none id=\"save_row_{$grid_id}_'+cl+'\">'+se+ce+'</span>'});\n\t\t\t\t\t\t}\t\n\t\t\t\t\t}";
            }
        }
        $out .= ",'ondblClickRow': function (id, iRow, iCol, e) {";
        // double click editing option
        if ($this->actions["rowactions"] !== false && $this->actions["edit"] !== false && $this->options["cellEdit"] !== true) {
            $out .= "\n\t\t\t\t\t\t\tif (!e) e = window.event;\n\t\t\t\t\t\t\tvar element = e.target || e.srcElement;\n\n\t\t\t\t\t\t\tif(id && id!==lastSel && lastSel != 'jqg1')\n\t\t\t\t\t\t\t{ \n\t\t\t\t\t\t\t\t// reset data msg, for new row edit without save last row\n\t\t\t\t\t\t\t\tif (typeof(lastSel) != 'undefined' && jQuery('.editable').length >0 && !confirm('Changes are not saved, Reset changes?'))\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').restoreRow(lastSel); \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t// to enable autosave on dblclick new row + dont edit on validation error\n\t\t\t\t\t\t\t\t// if (typeof(lastSel) != 'undefined')\n\t\t\t\t\t\t\t\t\t// if (!jQuery('#{$grid_id}').saveRow(lastSel))\n\t\t\t\t\t\t\t\t\t\t// return;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t// disabled previously edit icons\n\t\t\t\t\t\t\t\tjQuery('#edit_row_{$grid_id}_'+lastSel).show();\n\t\t\t\t\t\t\t\tjQuery('#save_row_{$grid_id}_'+lastSel).hide();\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tlastSel=id; \t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tjQuery('#{$grid_id}').editRow(id, true, function()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// focus on dblclicked element\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetTimeout(function(){ jQuery('input, select, textarea', element).focus(); },100);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfunction()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#edit_row_{$grid_id}_'+id).show();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#save_row_{$grid_id}_'+id).hide();\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},null,null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfunction()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// force reload grid after inline save\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{$reload_after_edit}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfunction()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#edit_row_{$grid_id}_'+id).show();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#save_row_{$grid_id}_'+id).hide();\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t); \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// for inlineNav edit button fix\n\t\t\t\t\t\t\tif (jQuery('#{$grid_id}_iledit').length)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tjQuery('#{$grid_id}').setSelection(id, true);\n\t\t\t\t\t\t\t\tjQuery('#{$grid_id}_iledit').click();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tjQuery('#edit_row_{$grid_id}_'+id).hide();\n\t\t\t\t\t\t\tjQuery('#save_row_{$grid_id}_'+id).show();\n\n\t\t\t\t\t\t\t{$str_inline_access}";
        }
        // chain 'onSelectRow' function with base working
        if (!empty($this->options["ondblClickRow"])) {
            $out .= "var fx = " . $this->options["ondblClickRow"] . "; fx(id, iRow, iCol);";
            unset($this->options["ondblClickRow"]);
        }
        $out .= "}";
        ### P ###
        // if subgrid is there, enable subgrid feature
        if (isset($this->options["subgridurl"]) && $this->options["subgridurl"] != '') {
            // we pass two parameters
            // subgrid_id is a id of the div tag created within a table
            // the row_id is the id of the row
            // If we want to pass additional parameters to the url we can use
            // the method getRowData(row_id) - which returns associative array in type name-value
            // here we can easy construct the following
            $pass_params = "false";
            if (!empty($this->options["subgridparams"])) {
                $pass_params = "true";
            }
            // chain 'subGridRowExpanded' function with base working
            if (!empty($this->options["subGridRowExpanded"])) {
                $str_fx = "var fx = " . $this->options["subGridRowExpanded"] . "; fx();";
                unset($this->options["subGridRowExpanded"]);
            }
            $out .= ",'subGridRowExpanded': function(subgridid, id) \n\t\t\t\t\t\t\t\t\t\t\t{ \n\t\t\t\t\t\t\t\t\t\t\t\tvar data = {subgrid:subgridid, rowid:id};\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\tif('{$pass_params}' == 'true') {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar anm= '" . $this->options["subgridparams"] . "';\n\t\t\t\t\t\t\t\t\t\t\t\t\tanm = anm.split(',');\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar rd = jQuery('#" . $grid_id . "').jqGrid('getRowData', id);\n\t\t\t\t\t\t\t\t\t\t\t\t\tif(rd) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfor(var i=0; i<anm.length; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif(rd[anm[i]]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata[anm[i]] = rd[anm[i]];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#'+jQuery.jgrid.jqID(subgridid)).load('" . $this->options["subgridurl"] . "',data,function(){ " . $str_fx . " });\n\t\t\t\t\t\t\t\t\t\t\t}";
        }
        // on error
        $out .= ",'loadError': function(xhr,status, err) { \n\t\t\t\t\ttry \n\t\t\t\t\t{\n\t\t\t\t\t\tjQuery.jgrid.info_dialog(jQuery.jgrid.errors.errcap,'<div class=\"ui-state-error\">'+ xhr.responseText +'</div>', \n\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery.jgrid.edit.bClose,{buttonalign:'right'});\n\n\t\t\t\t\t} \n\t\t\t\t\tcatch(e) { alert(xhr.responseText);}\n\t\t\t\t}\n\t\t\t\t";
        // on row selection operation
        $out .= ",'onSelectRow': function(ids) { ";
        ### P ###
        if (isset($this->options["detail_grid_id"]) && $this->options["detail_grid_id"] != '') {
            $detail_grid_id = $this->options["detail_grid_id"];
            $d_grids = explode(",", $detail_grid_id);
            foreach ($d_grids as $detail_grid_id) {
                $detail_url = $this->options["url"];
                // remove master grid's grid_id param
                $detail_url = str_replace('grid_id=', '', $detail_url);
                // append grid_id param for detail grid
                $s = strstr($this->options["url"], "?") ? "&" : "?";
                $detail_url .= $s . "grid_id=" . $detail_grid_id;
                $out .= "\n\t\t\n\t\t\t\t\t\tvar data = '';\n\t\t\t\t\t\tif ('{$this->options["subgridparams"]}'.length > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar anm = '" . $this->options["subgridparams"] . "';\n\t\t\t\t\t\t\tanm = anm.split(',');\n\t\t\t\t\t\t\tvar rd = jQuery('#" . $grid_id . "').jqGrid('getRowData', ids);\n\t\t\t\t\t\t\tif(rd) {\n\t\t\t\t\t\t\t\tfor(var i=0; i<anm.length; i++) {\n\t\t\t\t\t\t\t\t\tif(rd[anm[i]]) {\n\t\t\t\t\t\t\t\t\t\tdata += '&' + anm[i] + '=' + rd[anm[i]];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tif(ids == null) \n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tids=0;\n\t\t\t\t\t\t\tif(jQuery('#" . $detail_grid_id . "').jqGrid('getGridParam','records') >0 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').jqGrid('setGridParam',{url:'" . $detail_url . "&rowid='+ids+data,editurl:'" . $detail_url . "&rowid='+ids,jqgrid_page:1});\n\t\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').trigger('reloadGrid',[{jqgrid_page:1}]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\t\t\t\t\t\telse \n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').jqGrid('setGridParam',{url:'" . $detail_url . "&rowid='+ids+data,editurl:'" . $detail_url . "&rowid='+ids,jqgrid_page:1});\n\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').trigger('reloadGrid',[{jqgrid_page:1}]);\t\t\t\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// enable detail grid buttons if master row selected\n\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "_pager_left .ui-pg-button').not(':has(span.ui-separator)').removeClass('ui-state-disabled');\n\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "_ilsave, #" . $detail_grid_id . "_ilcancel').addClass('ui-state-disabled');\n\t\t\t\t\t\t\n\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').data('jqgrid_detail_grid_params','&rowid='+ids+data);\n\t\t\t\t\t\t";
            }
        }
        ### P ###
        // obseleted now
        if (!empty($this->events["js_on_select_row"])) {
            $out .= "if (typeof({$this->events["js_on_select_row"]}) != 'undefined') {$this->events["js_on_select_row"]}(ids);";
        }
        // chain 'onSelectRow' function with base working
        if (!empty($this->options["onSelectRow"])) {
            $out .= "var fx = " . $this->options["onSelectRow"] . "; fx(ids);";
            unset($this->options["onSelectRow"]);
        }
        // closing of select row events
        $out .= "}";
        // fix for formatting, to apply on only new records of virtual scroll
        if ($this->options["scroll"] == true) {
            $out .= ",'beforeRequest': function() {";
            $out .= "jQuery('#{$grid_id}').data('jqgrid_rows',jQuery('#{$grid_id} tr.jqgrow').length);";
            $out .= "}";
        }
        // on load complete operation
        $out .= ",'loadComplete': function(ids) {";
        // In case 'All' param is used in pager
        $out .= "jQuery('#{$grid_id}_pager option[value=\"All\"]').val(99999);";
        // show no record message at center
        $out .= "if (jQuery('#{$grid_id}').getGridParam('records') == 0) \n\t\t\t\t\t\t{ \n\t\t\t\t\t\t\tif (jQuery('#div_no_record_{$grid_id}').length==0) \n\t\t\t\t\t\t\t\tjQuery('#gbox_{$grid_id} .ui-jqgrid-bdiv').not('.frozen-bdiv').append('<div id=\"div_no_record_{$grid_id}\" align=\"center\" style=\"padding:30px 0;\">'+jQuery.jgrid.defaults.emptyrecords+'</div>'); \n\t\t\t\t\t\t\telse \n\t\t\t\t\t\t\t\tjQuery('#div_no_record_{$grid_id}').show();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tjQuery('#div_no_record_{$grid_id}').hide();\n\t\t\t\t\t\t}";
        if (isset($this->options["detail_grid_id"]) && $this->options["detail_grid_id"] != '') {
            $detail_grid_id = $this->options["detail_grid_id"];
            $d_grids = explode(",", $detail_grid_id);
            foreach ($d_grids as $detail_grid_id) {
                $detail_url = $this->options["url"];
                $s = strstr($this->options["url"], "?") ? "&" : "?";
                $detail_url .= $s . "grid_id=" . $detail_grid_id;
                $out .= "\n\t\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').jqGrid('setGridParam',{url:'" . $detail_url . "&rowid=',editurl:'" . $detail_url . "&rowid=',jqgrid_page:1});\n\t\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').trigger('reloadGrid',[{jqgrid_page:1}]);\n\t\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "').data('jqgrid_detail_grid_params','');\n\t\t\t\t\t\t\t\tjQuery('#" . $detail_grid_id . "_pager_left .ui-pg-button').addClass('ui-state-disabled');\n\t\t\t\t\t\t\t\t";
            }
        }
        // formatting fix for virtual scrolling
        $fix_format = "";
        if ($this->options["scroll"] == true) {
            $fix_format .= " var last_rows = 0;\n\t\t\t\t\t\t\t\t\tif (typeof(jQuery('#{$grid_id}').data('jqgrid_rows')) != 'undefined')\n\t\t\t\t\t\t\t\t\t\ti = i + jQuery('#{$grid_id}').data('jqgrid_rows');\n\t\t\t\t\t\t\t\t\t";
        }
        // celledit option and readonly mode
        if ($this->options["cellEdit"] === true) {
            foreach ($this->options["colModel"] as $t) {
                if ($t["editrules"]["readonly"] == true) {
                    $fix_format .= "jQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$t[name]}]').addClass('not-editable-cell');";
                }
            }
        }
        $out .= "if(ids && ids.rows) jQuery.each(ids.rows,function(i){\n\t\t\t\t\t\t\t{$fix_format}\n\t\t\t\t\t\t\t";
        ### P ###
        if (count($this->conditional_css)) {
            foreach ($this->conditional_css as $value) {
                // if wrong column specified, skip formatting
                $out .= "if (typeof(this.{$value[column]}) == 'undefined') return;";
                // using {column} placeholder in formatting value
                preg_match('/{(.*)}/', $value[value], $match);
                if (count($match)) {
                    // if html remove it using text(), if string convert toString(), if numeric use parseFloat
                    if ($value["op"] == "cn" || $value["op"] == "eq" || $value["op"] == "=") {
                        $value[value] = "'+ (jQuery(this.{$match['1']}).html() ? jQuery(this.{$match['1']}).text() : (jQuery.isNumeric(this.{$match['1']}) ? parseFloat(this.{$match['1']}) : this.{$match['1']}.toString()) )+ '";
                    } else {
                        $value[value] = "(jQuery(this.{$match['1']}).html() ? jQuery(this.{$match['1']}).text() : (jQuery.isNumeric(this.{$match['1']}) ? parseFloat(this.{$match['1']}) : this.{$match['1']}.toString()) )";
                    }
                }
                $out .= "this.{$value[column]} = this.{$value[column]}.replace(/(<([^>]+)>)/ig,'');";
                if ($value["op"] == "cn") {
                    $out .= "\n\t\t\t\t\t\t\t\t\t\tif (this.{$value[column]}.toLowerCase().indexOf('{$value[value]}'.toLowerCase()) != -1)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif ('" . $value["class"] . "' != '')\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').addClass('" . $value["class"] . "');\n\t\t\t\t\t\t\t\t\t\t\telse if (\"" . $value["css"] . "\" != '')\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit').css({{$value[css]}});\n\t\t\t\t\t\t\t\t\t\t\telse if ('" . $value["cellclass"] . "' != '')\n\t\t\t\t\t\t\t\t\t\t\t{ \n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit'); \n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$value[column]}]').addClass('" . $value["cellclass"] . "');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse if (\"" . $value["cellcss"] . "\" != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit');\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$value[column]}]').css('background','inherit').css({{$value[cellcss]}});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}";
                } else {
                    if ($value["op"] == "eq" || $value["op"] == "=") {
                        $out .= "\n\t\t\t\t\t\t\t\t\t\tif (this.{$value[column]}.toLowerCase() == '{$value[value]}'.toLowerCase())\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif ('" . $value["class"] . "' != '')\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').addClass('" . $value["class"] . "');\n\t\t\t\t\t\t\t\t\t\t\telse if (\"" . $value["css"] . "\" != '')\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit').css({{$value[css]}});\n\t\t\t\t\t\t\t\t\t\t\telse if ('" . $value["cellclass"] . "' != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit');\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$value[column]}]').addClass('" . $value["cellclass"] . "');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse if (\"" . $value["cellcss"] . "\" != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit');\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$value[column]}]').css('background','inherit').css({{$value[cellcss]}});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}";
                    } else {
                        if ($value["op"] == "<" || $value["op"] == "<=" || $value["op"] == ">" || $value["op"] == ">=" || $value["op"] == "!=") {
                            $out .= "\n\t\t\t\t\t\t\t\t\t\tif (parseFloat(this.{$value[column]}) {$value["op"]} {$value[value]})\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif ('" . $value["class"] . "' != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').addClass('" . $value["class"] . "');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse if (\"" . $value["css"] . "\" != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit').css({{$value[css]}});\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') a').css('background-image','inherit').css({{$value[css]}});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse if ('" . $value["cellclass"] . "' != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit');\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$value[column]}]').addClass('" . $value["cellclass"] . "');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse if (\"" . $value["cellcss"] . "\" != '')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+')').css('background-image','inherit');\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} tr.jqgrow:eq('+i+') td[aria-describedby={$grid_id}_{$value[column]}]').css('background','inherit').css({{$value[cellcss]}});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}";
                        } else {
                            if (empty($value["op"]) && !empty($value["column"]) && !empty($value["css"])) {
                                $out .= "\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (jQuery.browser.msie)\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} td[aria-describedby={$grid_id}_{$value["column"]}]').css('background','inherit').css({{$value[css]}});\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery('#{$grid_id} td[aria-describedby={$grid_id}_{$value["column"]}]').removeClass('.ui-widget-content').css({{$value[css]}});\n\t\t\t\t\t\t\t\t\t\t}";
                            }
                        }
                    }
                }
            }
        }
        ### P-END ###
        $out .= "});";
        ### P ###
        // obseleted now
        if (!empty($this->events["js_on_load_complete"])) {
            $out .= "if (typeof({$this->events["js_on_load_complete"]}) != 'undefined') {$this->events["js_on_load_complete"]}(ids);";
        }
        // chain 'loadComplete' function with base working
        if (!empty($this->options["loadComplete"])) {
            $out .= "var fx = " . $this->options["loadComplete"] . "; fx(ids);";
            unset($this->options["loadComplete"]);
        }
        // closing of load complete events
        $out .= "}";
        // closing of param list
        $out .= "}";
        // Navigational grid params
        if (!isset($this->navgrid["param"])) {
            $this->navgrid["param"]["edit"] = $this->actions["edit"] === false ? false : true;
            $this->navgrid["param"]["add"] = $this->actions["add"] === false ? false : true;
            $this->navgrid["param"]["del"] = $this->actions["delete"] === false ? false : true;
            $this->navgrid["param"]["view"] = $this->actions["view"] === true ? true : false;
            $this->navgrid["param"]["refresh"] = $this->actions["refresh"] === false ? false : true;
            ### P ### -- turn false
            $this->navgrid["param"]["search"] = $this->actions["search"] === false ? false : true;
            // fix for del and delete text
            if (!empty($this->navgrid["param"]["delete"])) {
                $this->navgrid["param"]["del"] = $this->navgrid["param"]["delete"];
            }
        }
        // Generate HTML/JS code
        ob_start();
        ?>
			<table id="<?php 
        echo $grid_id;
        ?>
"></table> 
			<div id="<?php 
        echo $grid_id . "_pager";
        ?>
"></div> 
			<script>
			var phpgrid = jQuery("#<?php 
        echo $grid_id;
        ?>
");
			var phpgrid_pager = jQuery("#<?php 
        echo $grid_id . "_pager";
        ?>
");
			var fx_ajax_file_upload;
			var fx_replace_upload;
			var fx_bulk_update;
			var fx_get_dropdown;

			jQuery(document).ready(function(){
				<?php 
        echo $this->render_js($grid_id, $out);
        ?>
			});	

			</script>	
		<?php 
        return ob_get_clean();
    }