最近使用bootstrap這個前端框架其中的模態對話框效果,我們知道國外的東西用在國內項目上最頭疼的就是傳值亂碼問題,這里先介紹下模態對話框傳值的介紹(不是直接訪問靜態html或者直接打開寫在當前界面的一個層里而是打開一個后台,將所需要的值處理好再傳值前台的模態對話框).首先看下英文介紹:諸如
<a data-toggle="modal"href="remote.html"data-target="#modal">click me</a> 這樣的例子,當然還需要個目的顯示層。廢話不多說,下面貼出筆者自己修改的模態對話框部分的代碼,使用者可以自行覆蓋bootstrap.js的相關模塊,這里如果不商用應該不涉及版權問題。下面代碼的重點是將遠程url的參數分解,即以"?"划分請求正文部分和參數部分。這里url對應的對象是this.options.remote,我們只要對這個對象處理就好了,讀者可以打印下這個對象,它本身只是個url字符串,我們所遇到的亂碼問題也是源自此。jquery的load()函數最全的屬性設置如下"
$("#feeds").load("feeds.php", {limit: 25}, function(){
alert("The last 25 entries in the feed have been loaded");
});
"(該例子引自jquery1.7.2的文檔)。bootstrap源碼this.options.remote && this.$element.find('.modal-body').load( this.options.remote);(為下面代碼修改后的line24)似乎並沒有考慮中文參數的問題,所以才出現這種情況因此我們要做的只是變更它的方法樣式就可以實現中文亂碼的解決方案了。另外筆者這里還解決了如果重復點擊模態下拉的按鈕會卡並且重復顯示相同數據的問題(這里的原因是對數據進行了緩存)這里就不做介紹了。
1 /* MODAL CLASS DEFINITION 2 * ====================== */ 3 4 var Modal = function (element, options) { 5 this.options = options 6 this.$element = $(element) 7 .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) 8 this.options.remote && this.$element.find('.modal-body').empty(); 9 var str=this.options.remote; 10 var sendok=str.substr(0,str.lastIndexOf("?")); 11 str=str.substr(str.lastIndexOf("?")+1,str.length); 12 if(str!=""){ 13 var params=str.split("&"); 14 var sendpara="{"; 15 for(var i=0;i<params.length;i++){ 16 if(params[i]!=""){ 17 var paramsd=params[i].split("="); 18 sendpara+=("\""+paramsd[0]+"\""+":"+"\""+paramsd[1]+"\"")+","; 19 } 20 } 21 } 22 sendpara=sendpara.substring(0,sendpara.lastIndexOf(","))+"}"; 23 sendpara= eval("("+sendpara+")"); 24 this.options.remote && this.$element.find('.modal-body').load(sendok,sendpara); 25 } 26 27 Modal.prototype = { 28 29 constructor: Modal 30 31 , toggle: function () { 32 // return this[!this.isShown ? 'show' : 'hide']() 33 } 34 35 , show: function () { 36 var that = this 37 , e = $.Event('show') 38 this.$element.trigger(e) 39 if (this.isShown || e.isDefaultPrevented()) return 40 this.isShown = true 41 this.escape() 42 this.backdrop(function () { 43 var transition = $.support.transition && that.$element.hasClass('fade') 44 45 if (!that.$element.parent().length) { 46 that.$element.appendTo(document.body) //don't move modals dom position 47 } 48 that.$element.show() 49 if (transition) { 50 that.$element[0].offsetWidth // force reflow 51 } 52 that.$element 53 .addClass('in') 54 .attr('aria-hidden', false) 55 that.enforceFocus() 56 transition ? 57 that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) : 58 that.$element.focus().trigger('shown') 59 60 }) 61 } 62 63 , hide: function (e) { 64 e && e.preventDefault() 65 66 var that = this 67 68 e = $.Event('hide') 69 70 this.$element.trigger(e) 71 72 if (!this.isShown || e.isDefaultPrevented()) return 73 74 this.isShown = false 75 76 this.escape() 77 78 $(document).off('focusin.modal') 79 80 this.$element 81 .removeClass('in') 82 .attr('aria-hidden', true) 83 $.support.transition && this.$element.hasClass('fade') ? 84 this.hideWithTransition() : 85 this.hideModal() 86 $(".showall").each(function(index) { 87 $(this).remove(); 88 }) 89 } 90 91 , enforceFocus: function () { 92 var that = this 93 $(document).on('focusin.modal', function (e) { 94 if (that.$element[0] !== e.target && !that.$element.has(e.target).length) { 95 that.$element.focus() 96 } 97 }) 98 } 99 100 , escape: function () { 101 var that = this 102 if (this.isShown && this.options.keyboard) { 103 this.$element.on('keyup.dismiss.modal', function ( e ) { 104 e.which == 27 && that.hide() 105 }) 106 } else if (!this.isShown) { 107 this.$element.off('keyup.dismiss.modal') 108 } 109 } 110 111 , hideWithTransition: function () { 112 var that = this 113 , timeout = setTimeout(function () { 114 that.$element.off($.support.transition.end) 115 that.hideModal() 116 }, 500) 117 118 this.$element.one($.support.transition.end, function () { 119 clearTimeout(timeout) 120 that.hideModal() 121 }) 122 } 123 124 , hideModal: function () { 125 var that = this 126 this.$element.hide() 127 this.backdrop(function () { 128 that.removeBackdrop() 129 that.$element.trigger('hidden') 130 }) 131 } 132 133 , removeBackdrop: function () { 134 this.$backdrop && this.$backdrop.remove() 135 this.$backdrop = null 136 } 137 138 , backdrop: function (callback) { 139 var that = this 140 , 141 animate = this.$element.hasClass('fade') ? 'fade' : '' 142 if (this.isShown && this.options.backdrop) { 143 var doAnimate = $.support.transition && animate 144 $(".showall").each(function(index) { 145 $(this).remove(); 146 }) 147 this.$backdrop = $('<div class="modal-backdrop ' + animate + ' showall " />') 148 .appendTo(document.body) 149 this.$backdrop.click( 150 ) 151 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 152 153 this.$backdrop.addClass('in') 154 if (!callback) return 155 doAnimate ? 156 this.$backdrop.one($.support.transition.end, callback) : 157 callback() 158 159 } else if (!this.isShown && this.$backdrop) { 160 this.$backdrop.removeClass('in') 161 162 $.support.transition && this.$element.hasClass('fade')? 163 this.$backdrop.one($.support.transition.end, callback) : 164 callback() 165 166 } else if (callback) { 167 callback() 168 } 169 } 170 }
當然這只是一部分,剩下的靠讀者自己研究。至於url轉化為this.options.remote對象的相關代碼如下
1 $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) { 2 var $this = $(this) 3 , href = $this.attr('href') 4 , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 5 , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data()) 6 7 e.preventDefault() 8 9 $target 10 .modal(option) 11 .one('hide', function () { 12 $this.focus() 13 }) 14 }) 15 16 }(window.jQuery);
這段代碼在bs的1037行(- -這里是我的行數,我是直接在它的bs上改的,你的應該再往上一點點)順便說下!function($){}(window.jQuery)這種寫法是一種匿名函數的寫法具體可以參見http://www.jb51.net/article/21948.htm;然后大家看這代碼的第一行就是定義點擊帶有[data-toggle]=‘modal’]這樣的參數的組件響應函數,第二行是將傳遞的當前對象封裝為jquey,第三行是獲得當前的超鏈接內容然后看第五行是設置參數option ,這里判斷$target.data('modal')的值最初為undefined所以要用擴展的方式增加,擴展的第一個參數又使用了正則判斷得到的href是不是#,不是則傳遞href的值也就能得到我們的url,剩下的就是拿到這個url后先以?分離utl正文和參數,然后將參數封裝為json字符創,網上給出的用封裝好的js對象將字符串處理為json貌似不對於是自己寫,具體內容相信了解簡單字符串處理的讀者能看懂,不了解的就需要自己補補了。其實這樣處理僅僅是為了兼容ie的效果,想ff這類的瀏覽器是不用做任何處理就可以使用bs的,天殺的ie你究竟要折磨多少開發者才滿意。