From f463fa980ac455e3f5b65a8b8ed596dd3f5d79e7 Mon Sep 17 00:00:00 2001 From: Karson Date: Sat, 16 Dec 2017 17:29:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ebuttons=E9=85=8D=E7=BD=AEsucc?= =?UTF-8?q?ess/error/callback=E5=9B=9E=E8=B0=83=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9Ebuttons=E9=85=8D=E7=BD=AEconfirm=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E6=A1=86=E5=8A=9F=E8=83=BD=20=E6=96=B0=E5=A2=9Ebutton?= =?UTF-8?q?s=E7=9A=84URL=E6=9B=BF=E6=8D=A2=E8=A1=8C=E5=85=B6=E5=AE=83?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=20=E5=AE=8C=E5=96=84btn-ajax/btn-addtabs/btn?= =?UTF-8?q?-dialog=E7=9A=84=E5=8A=9F=E8=83=BD=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=90=8E=E5=8F=B0=E7=B3=BB=E7=BB=9F=E9=85=8D=E7=BD=AE=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=A4=8D=E9=80=89=E6=A1=86=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/lang/zh-cn/general/profile.php | 1 + public/assets/js/backend.js | 65 ++++++- public/assets/js/require-backend.min.js | 183 ++++++++++++------ public/assets/js/require-form.js | 4 +- public/assets/js/require-table.js | 113 +++++------ 5 files changed, 238 insertions(+), 128 deletions(-) diff --git a/application/admin/lang/zh-cn/general/profile.php b/application/admin/lang/zh-cn/general/profile.php index e851f9c0..1c707bd3 100644 --- a/application/admin/lang/zh-cn/general/profile.php +++ b/application/admin/lang/zh-cn/general/profile.php @@ -4,6 +4,7 @@ return [ 'Url' => '链接', 'Userame' => '用户名', 'Createtime' => '操作时间', + 'Click to edit' => '点击编辑', 'Admin log' => '操作日志', 'Leave password blank if dont want to change' => '不修改密码请留空', ]; diff --git a/public/assets/js/backend.js b/public/assets/js/backend.js index 74059014..7efe4d0e 100755 --- a/public/assets/js/backend.js +++ b/public/assets/js/backend.js @@ -111,23 +111,74 @@ define(['fast', 'moment'], function (Fast, Moment) { Toastr.options.positionClass = Config.controllername === 'index' ? "toast-top-right-index" : "toast-top-right"; //点击包含.btn-dialog的元素时弹出dialog $(document).on('click', '.btn-dialog,.dialogit', function (e) { - var options = $(this).data() || {}; - Backend.api.open(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr('title'), options); + var that = this; + var options = $(that).data() || {}; + if (typeof options.tableId !== 'undefined' && typeof options.columnIndex !== 'undefined' && typeof options.buttonIndex !== 'undefined') { + var tableOptions = $("#" + options.tableId).bootstrapTable('getOptions'); + if (tableOptions) { + var button = tableOptions.columns[0][options.columnIndex]['buttons'][options.buttonIndex]; + if (button && typeof button.callback === 'function') { + options.callback = button.callback; + } + } + } + if (typeof options.confirm !== 'undefined') { + Layer.confirm(options.confirm, function (index) { + Backend.api.open(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr('title'), options); + Layer.close(index); + }); + } else { + Backend.api.open(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr('title'), options); + } return false; }); //点击包含.btn-addtabs的元素时新增选项卡 $(document).on('click', '.btn-addtabs,.addtabsit', function (e) { - Backend.api.addtabs(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr("title")); + var that = this; + var options = $(that).data() || {}; + if (typeof options.confirm !== 'undefined') { + Layer.confirm(options.confirm, function (index) { + Backend.api.addtabs(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr("title")); + Layer.close(index); + }); + } else { + Backend.api.addtabs(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr("title")); + } + return false; }); //点击包含.btn-ajax的元素时发送Ajax请求 $(document).on('click', '.btn-ajax,.ajaxit', function (e) { - var options = $(this).data(); - if (typeof options.url === 'undefined' && $(this).attr("href")) { - options.url = $(this).attr("href"); + var that = this; + var options = $(that).data() || {}; + if (typeof options.url === 'undefined' && $(that).attr("href")) { + options.url = $(that).attr("href"); } options.url = Backend.api.replaceids(this, options.url); - Backend.api.ajax(options); + var success = typeof options.success === 'function' ? options.success : null; + var error = typeof options.error === 'function' ? options.error : null; + delete options.success; + delete options.error; + if (typeof options.tableId !== 'undefined' && typeof options.columnIndex !== 'undefined' && typeof options.buttonIndex !== 'undefined') { + var tableOptions = $("#" + options.tableId).bootstrapTable('getOptions'); + if (tableOptions) { + var button = tableOptions.columns[0][options.columnIndex]['buttons'][options.buttonIndex]; + if (button && typeof button.success === 'function') { + success = button.success; + } + if (button && typeof button.error === 'function') { + error = button.error; + } + } + } + if (typeof options.confirm !== 'undefined') { + Layer.confirm(options.confirm, function (index) { + Backend.api.ajax(options, success, error); + Layer.close(index); + }); + } else { + Backend.api.ajax(options, success, error); + } return false; }); //修复含有fixed-footer类的body边距 diff --git a/public/assets/js/require-backend.min.js b/public/assets/js/require-backend.min.js index 054e6a87..dce302a7 100644 --- a/public/assets/js/require-backend.min.js +++ b/public/assets/js/require-backend.min.js @@ -6909,23 +6909,74 @@ define('backend',['fast', 'moment'], function (Fast, Moment) { Toastr.options.positionClass = Config.controllername === 'index' ? "toast-top-right-index" : "toast-top-right"; //点击包含.btn-dialog的元素时弹出dialog $(document).on('click', '.btn-dialog,.dialogit', function (e) { - var options = $(this).data() || {}; - Backend.api.open(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr('title'), options); + var that = this; + var options = $(that).data() || {}; + if (typeof options.tableId !== 'undefined' && typeof options.columnIndex !== 'undefined' && typeof options.buttonIndex !== 'undefined') { + var tableOptions = $("#" + options.tableId).bootstrapTable('getOptions'); + if (tableOptions) { + var button = tableOptions.columns[0][options.columnIndex]['buttons'][options.buttonIndex]; + if (button && typeof button.callback === 'function') { + options.callback = button.callback; + } + } + } + if (typeof options.confirm !== 'undefined') { + Layer.confirm(options.confirm, function (index) { + Backend.api.open(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr('title'), options); + Layer.close(index); + }); + } else { + Backend.api.open(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr('title'), options); + } return false; }); //点击包含.btn-addtabs的元素时新增选项卡 $(document).on('click', '.btn-addtabs,.addtabsit', function (e) { - Backend.api.addtabs(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr("title")); + var that = this; + var options = $(that).data() || {}; + if (typeof options.confirm !== 'undefined') { + Layer.confirm(options.confirm, function (index) { + Backend.api.addtabs(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr("title")); + Layer.close(index); + }); + } else { + Backend.api.addtabs(Backend.api.replaceids(that, $(that).attr('href')), $(that).attr("title")); + } + return false; }); //点击包含.btn-ajax的元素时发送Ajax请求 $(document).on('click', '.btn-ajax,.ajaxit', function (e) { - var options = $(this).data(); - if (typeof options.url === 'undefined' && $(this).attr("href")) { - options.url = $(this).attr("href"); + var that = this; + var options = $(that).data() || {}; + if (typeof options.url === 'undefined' && $(that).attr("href")) { + options.url = $(that).attr("href"); } options.url = Backend.api.replaceids(this, options.url); - Backend.api.ajax(options); + var success = typeof options.success === 'function' ? options.success : null; + var error = typeof options.error === 'function' ? options.error : null; + delete options.success; + delete options.error; + if (typeof options.tableId !== 'undefined' && typeof options.columnIndex !== 'undefined' && typeof options.buttonIndex !== 'undefined') { + var tableOptions = $("#" + options.tableId).bootstrapTable('getOptions'); + if (tableOptions) { + var button = tableOptions.columns[0][options.columnIndex]['buttons'][options.buttonIndex]; + if (button && typeof button.success === 'function') { + success = button.success; + } + if (button && typeof button.error === 'function') { + error = button.error; + } + } + } + if (typeof options.confirm !== 'undefined') { + Layer.confirm(options.confirm, function (index) { + Backend.api.ajax(options, success, error); + Layer.close(index); + }); + } else { + Backend.api.ajax(options, success, error); + } return false; }); //修复含有fixed-footer类的body边距 @@ -9707,10 +9758,10 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr $(toolbar).on('click', Table.config.delbtn, function () { var that = this; var ids = Table.api.selectedids(table); - var index = Layer.confirm( + Layer.confirm( __('Are you sure you want to delete the %s selected item?', ids.length), {icon: 3, title: __('Warning'), offset: 0, shadeClose: true}, - function () { + function (index) { Table.api.multi("del", ids, table, that); Layer.close(index); } @@ -9765,10 +9816,10 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr e.preventDefault(); var id = $(this).data("id"); var that = this; - var index = Layer.confirm( + Layer.confirm( __('Are you sure you want to delete this item?'), {icon: 3, title: __('Warning'), shadeClose: true}, - function () { + function (index) { Table.api.multi("del", id, table, that); Layer.close(index); } @@ -9811,10 +9862,10 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr if ($(window).width() < 480) { top = left = undefined; } - var index = Layer.confirm( + Layer.confirm( __('Are you sure you want to delete this item?'), {icon: 3, title: __('Warning'), offset: [top, left], shadeClose: true}, - function () { + function (index) { var table = $(that).closest('table'); var options = table.bootstrapTable('getOptions'); Table.api.multi("del", row[options.pk], table, that); @@ -9916,65 +9967,69 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr buttons.push({name: 'dragsort', icon: 'fa fa-arrows', classname: 'btn btn-xs btn-primary btn-dragsort'}); buttons.push({name: 'edit', icon: 'fa fa-pencil', classname: 'btn btn-xs btn-success btn-editone', url: options.extend.edit_url}); buttons.push({name: 'del', icon: 'fa fa-trash', classname: 'btn btn-xs btn-danger btn-delone'}); - var html = []; - var url, classname, icon, text, title, extend; - $.each(buttons, function (i, j) { + return Table.api.buttonlink(this, buttons, value, row, index, 'operate'); + }, + buttons: function (value, row, index) { + // 默认按钮组 + var buttons = $.extend([], this.buttons || []); + return Table.api.buttonlink(this, buttons, value, row, index, 'buttons'); + } + }, + buttonlink: function (column, buttons, value, row, index, type) { + var table = column.table; + type = typeof type === 'undefined' ? 'buttons' : type; + // 操作配置 + var options = table ? table.bootstrapTable('getOptions') : {}; + var html = []; + var url, classname, icon, text, title, extend; + var columnIndex = options.columns[0].findIndex(function (element) { + return element === column; + }); + $.each(buttons, function (i, j) { + if (type === 'operate') { if (j.name === 'dragsort' && typeof row[Table.config.dragsortfield] === 'undefined') { return true; } if (['add', 'edit', 'del', 'multi', 'dragsort'].indexOf(j.name) > -1 && !options.extend[j.name + "_url"]) { return true; } - var attr = table.data("operate-" + j.name); - if (typeof attr === 'undefined' || attr) { - url = j.url ? j.url : ''; - if (url.indexOf("{ids}") === -1) { - url = url ? url + (url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk] : ''; - } - url = Table.api.replaceurl(url, value, row, table); - url = url ? Fast.api.fixurl(url) : 'javascript:;'; - classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one'; - icon = j.icon ? j.icon : ''; - text = j.text ? j.text : ''; - title = j.title ? j.title : text; - extend = j.extend ? j.extend : ''; - html.push('' + (text ? ' ' + text : '') + ''); + } + var attr = table.data(type + "-" + j.name); + if (typeof attr === 'undefined' || attr) { + url = j.url ? j.url : ''; + if (!url.match(/\{(.*?)\}/i)) { + url = url ? url + (url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk] : ''; } - }); - return html.join(' '); - }, - buttons: function (value, row, index) { - var table = this.table; - // 操作配置 - var options = table ? table.bootstrapTable('getOptions') : {}; - // 默认按钮组 - var buttons = $.extend([], this.buttons || []); - var html = []; - var url, classname, icon, text, title, extend; - $.each(buttons, function (i, j) { - var attr = table.data("buttons-" + j.name); - if (typeof attr === 'undefined' || attr) { - url = j.url ? j.url : ''; - if (url.indexOf("{ids}") === -1) { - url = url ? url + (url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk] : ''; - } - url = Table.api.replaceurl(url, value, row, table); - url = url ? Fast.api.fixurl(url) : 'javascript:;'; - classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one'; - icon = j.icon ? j.icon : ''; - text = j.text ? j.text : ''; - title = j.title ? j.title : text; - extend = j.extend ? j.extend : ''; - html.push('' + (text ? ' ' + text : '') + ''); - } - }); - return html.join(' '); - } + url = Table.api.replaceurl(url, value, row, table); + url = url ? Fast.api.fixurl(url) : 'javascript:;'; + classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one'; + icon = j.icon ? j.icon : ''; + text = j.text ? j.text : ''; + title = j.title ? j.title : text; + confirm = j.confirm ? 'data-confirm="' + j.confirm + '"' : ''; + extend = j.extend ? j.extend : ''; + html.push('' + (text ? ' ' + text : '') + ''); + } + }); + return html.join(' '); }, - //替换URL中的{ids}和{value} + //替换URL中的数据 replaceurl: function (url, value, row, table) { - url = url ? url : ''; url = url.replace(/\{value\}/ig, value); + url = url.replace(/\{(.*?)\}/gi, function (matched) { + matched = matched.substring(1, matched.length - 1); + if (matched.indexOf(".") !== -1) { + var temp = row; + var arr = matched.split(/\./); + for (var i = 0; i < arr.length; i++) { + if (typeof temp[arr[i]] !== 'undefined') { + temp = temp[arr[i]]; + } + } + return typeof temp === 'object' ? '' : temp; + } + return row[matched]; + }); if (table) { var options = table.bootstrapTable('getOptions'); url = url.replace(/\{ids\}/ig, row[options.pk]); @@ -12836,7 +12891,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef url = url ? url : location.href; //修复当存在多选项元素时提交的BUG var params = {}; - var multipleList = $("[name$='[]']"); + var multipleList = $("[name$='[]']", form); if (multipleList.size() > 0) { var postFields = form.serializeArray().map(function (obj) { return $(obj).prop("name"); @@ -12851,7 +12906,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef Fast.api.ajax({ type: type, url: url, - data: form.serialize() + (params ? '&' + $.param(params) : ''), + data: form.serialize() + (Object.keys(params).length > 0 ? '&' + $.param(params) : ''), dataType: 'json', complete: function (xhr) { var token = xhr.getResponseHeader('__token__'); diff --git a/public/assets/js/require-form.js b/public/assets/js/require-form.js index 6b5fa420..365e48bb 100755 --- a/public/assets/js/require-form.js +++ b/public/assets/js/require-form.js @@ -216,7 +216,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U url = url ? url : location.href; //修复当存在多选项元素时提交的BUG var params = {}; - var multipleList = $("[name$='[]']"); + var multipleList = $("[name$='[]']", form); if (multipleList.size() > 0) { var postFields = form.serializeArray().map(function (obj) { return $(obj).prop("name"); @@ -231,7 +231,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U Fast.api.ajax({ type: type, url: url, - data: form.serialize() + (params ? '&' + $.param(params) : ''), + data: form.serialize() + (Object.keys(params).length > 0 ? '&' + $.param(params) : ''), dataType: 'json', complete: function (xhr) { var token = xhr.getResponseHeader('__token__'); diff --git a/public/assets/js/require-table.js b/public/assets/js/require-table.js index fc14db46..150f1526 100644 --- a/public/assets/js/require-table.js +++ b/public/assets/js/require-table.js @@ -189,10 +189,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table $(toolbar).on('click', Table.config.delbtn, function () { var that = this; var ids = Table.api.selectedids(table); - var index = Layer.confirm( + Layer.confirm( __('Are you sure you want to delete the %s selected item?', ids.length), {icon: 3, title: __('Warning'), offset: 0, shadeClose: true}, - function () { + function (index) { Table.api.multi("del", ids, table, that); Layer.close(index); } @@ -247,10 +247,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table e.preventDefault(); var id = $(this).data("id"); var that = this; - var index = Layer.confirm( + Layer.confirm( __('Are you sure you want to delete this item?'), {icon: 3, title: __('Warning'), shadeClose: true}, - function () { + function (index) { Table.api.multi("del", id, table, that); Layer.close(index); } @@ -293,10 +293,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table if ($(window).width() < 480) { top = left = undefined; } - var index = Layer.confirm( + Layer.confirm( __('Are you sure you want to delete this item?'), {icon: 3, title: __('Warning'), offset: [top, left], shadeClose: true}, - function () { + function (index) { var table = $(that).closest('table'); var options = table.bootstrapTable('getOptions'); Table.api.multi("del", row[options.pk], table, that); @@ -398,65 +398,68 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table buttons.push({name: 'dragsort', icon: 'fa fa-arrows', classname: 'btn btn-xs btn-primary btn-dragsort'}); buttons.push({name: 'edit', icon: 'fa fa-pencil', classname: 'btn btn-xs btn-success btn-editone', url: options.extend.edit_url}); buttons.push({name: 'del', icon: 'fa fa-trash', classname: 'btn btn-xs btn-danger btn-delone'}); - var html = []; - var url, classname, icon, text, title, extend; - $.each(buttons, function (i, j) { + return Table.api.buttonlink(this, buttons, value, row, index, 'operate'); + }, + buttons: function (value, row, index) { + // 默认按钮组 + var buttons = $.extend([], this.buttons || []); + return Table.api.buttonlink(this, buttons, value, row, index, 'buttons'); + } + }, + buttonlink: function (column, buttons, value, row, index, type) { + var table = column.table; + type = typeof type === 'undefined' ? 'buttons' : type; + var options = table ? table.bootstrapTable('getOptions') : {}; + var html = []; + var url, classname, icon, text, title, extend; + var columnIndex = options.columns[0].findIndex(function (element) { + return element === column; + }); + $.each(buttons, function (i, j) { + if (type === 'operate') { if (j.name === 'dragsort' && typeof row[Table.config.dragsortfield] === 'undefined') { return true; } if (['add', 'edit', 'del', 'multi', 'dragsort'].indexOf(j.name) > -1 && !options.extend[j.name + "_url"]) { return true; } - var attr = table.data("operate-" + j.name); - if (typeof attr === 'undefined' || attr) { - url = j.url ? j.url : ''; - if (url.indexOf("{ids}") === -1) { - url = url ? url + (url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk] : ''; - } - url = Table.api.replaceurl(url, value, row, table); - url = url ? Fast.api.fixurl(url) : 'javascript:;'; - classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one'; - icon = j.icon ? j.icon : ''; - text = j.text ? j.text : ''; - title = j.title ? j.title : text; - extend = j.extend ? j.extend : ''; - html.push('' + (text ? ' ' + text : '') + ''); + } + var attr = table.data(type + "-" + j.name); + if (typeof attr === 'undefined' || attr) { + url = j.url ? j.url : ''; + if (!url.match(/\{(.*?)\}/i)) { + url = url ? url + (url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk] : ''; } - }); - return html.join(' '); - }, - buttons: function (value, row, index) { - var table = this.table; - // 操作配置 - var options = table ? table.bootstrapTable('getOptions') : {}; - // 默认按钮组 - var buttons = $.extend([], this.buttons || []); - var html = []; - var url, classname, icon, text, title, extend; - $.each(buttons, function (i, j) { - var attr = table.data("buttons-" + j.name); - if (typeof attr === 'undefined' || attr) { - url = j.url ? j.url : ''; - if (url.indexOf("{ids}") === -1) { - url = url ? url + (url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk] : ''; - } - url = Table.api.replaceurl(url, value, row, table); - url = url ? Fast.api.fixurl(url) : 'javascript:;'; - classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one'; - icon = j.icon ? j.icon : ''; - text = j.text ? j.text : ''; - title = j.title ? j.title : text; - extend = j.extend ? j.extend : ''; - html.push('' + (text ? ' ' + text : '') + ''); - } - }); - return html.join(' '); - } + url = Table.api.replaceurl(url, value, row, table); + url = url ? Fast.api.fixurl(url) : 'javascript:;'; + classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one'; + icon = j.icon ? j.icon : ''; + text = j.text ? j.text : ''; + title = j.title ? j.title : text; + confirm = j.confirm ? 'data-confirm="' + j.confirm + '"' : ''; + extend = j.extend ? j.extend : ''; + html.push('' + (text ? ' ' + text : '') + ''); + } + }); + return html.join(' '); }, - //替换URL中的{ids}和{value} + //替换URL中的数据 replaceurl: function (url, value, row, table) { - url = url ? url : ''; url = url.replace(/\{value\}/ig, value); + url = url.replace(/\{(.*?)\}/gi, function (matched) { + matched = matched.substring(1, matched.length - 1); + if (matched.indexOf(".") !== -1) { + var temp = row; + var arr = matched.split(/\./); + for (var i = 0; i < arr.length; i++) { + if (typeof temp[arr[i]] !== 'undefined') { + temp = temp[arr[i]]; + } + } + return typeof temp === 'object' ? '' : temp; + } + return row[matched]; + }); if (table) { var options = table.bootstrapTable('getOptions'); url = url.replace(/\{ids\}/ig, row[options.pk]);