呃,系統自帶的alert、confirm等彈出框實在是難看,做爲一個顏控,這能忍?php
這裏我用的是kartik-v/yii2-dialog,這個是基於bootstrap3-dialog這個來作了一些經常使用alert、confirm和dialog的小部件封裝,固然了,本質上仍是bootstrap3-dialog,能夠用原生的方法,原生方法的用法點這裏,而bootstrap3-dialog又是基於bootstrap3的modals作的封裝。嗯,基本關係就是這樣。在搜索這個相關知識時,常常會看到有人提到bootbox,這個一樣是流行的一個美化插件,基本原理相似,用法稍微不一樣,在packagist搜索yii2 bootbox會發現也有人爲Yii2作了集成(或者本身集成也行,後面會講到),一樣值得推薦。css
按照說明安裝,最好是按照github的說明,由於最新的通常都會在這裏先更新。composer中要用@dev。能夠看這裏的說明,若是不成功,先composer self-update,再試下,當初安裝時也是各類報錯不行,後來忽然就行了。稍微注意的是confirm,dialog調用時要求必須寫回調,不然就報錯。git
仍是蠻漂亮的。可是像是Yii框架Gridview自帶的confirm(像是刪除按鈕),點擊時仍是原生的,由於它的源碼就是用的confirm命令,好在Yii框架提供了方法,可讓咱們覆蓋confirm方法。具體可以下操做:github
一、咱們能夠先看下在vendor/yiisoft/yii2/assets/yii.js文件中的confirm方法:註釋中就能夠看到,能夠用yii.confirm來重寫此設置。web
/** * Displays a confirmation dialog. * The default implementation simply displays a js confirmation dialog. * You may override this by setting `yii.confirm`. * @param message the confirmation message. * @param ok a callback to be called when the user confirms the message * @param cancel a callback to be called when the user cancels the confirmation */ confirm: function (message, ok, cancel) { if (confirm(message)) { !ok || ok(); } else { !cancel || cancel(); } },
二、那咱們就重寫,能夠在backend/web/js中新建confirm.js文件,而後從新,可參照此文章,這是設置bootbox的,並且版本有點過期,不過下方的評論有最新方法。而咱們的設置與此原理是一致的,只不過是改爲kartik-v/yii2-dialog所需求的參數樣式:bootstrap
yii.confirm = function (message, ok, cancel) { krajeeDialog.confirm(message,function(data){ if (data) { !ok || ok(); } else { !cancel || cancel(); } }); // confirm will always return false on the first call // to cancel click handler return false; }
三、咱們須要註冊此js,能夠在backend/assets/Appasset.php中添加上方的js文件:數組
class AppAsset extends AssetBundle { public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'css/site.css', ]; public $js = [ 'js/confirm.js',//就是這裏了 ]; public $depends = [ 'yii\web\YiiAsset', 'yii\bootstrap\BootstrapAsset', ]; }
這樣一來,在點擊刪除按鈕便會發現能夠調用了:yii2
因爲咱們用的是kartik-GridView,它的兩個功能展現所有記錄和導出csv等的提示,都是用的原生的confirm,強迫症的咱們能忍嗎?好吧,我忍了,這裏只給出改的思路,尤爲是隻懂基礎js的我來講,先把時間放在其它地方吧。(2017.03.31注:3.1.2版本以上的kartik-GridView中會自動帶有yii2-dialog來提示,因此下面修改js什麼的沒什麼用了。)cookie
在改以前,首先咱們須要明確kartik-v/yii2-dialog的confirm(bootbox一樣)和原生confirm的不一樣。原生confirm是同步的,而kartik-v/yii2-dialog的confirm方法是異步回調的。這致使原生的confirm能夠直接這樣寫:session
function abc(){ return window.confirm('123');//confirm點擊確認返回true,取消返回false,不點擊就等着用戶點擊 } if(abc()){ alert('456');//點擊是,會彈出alert彈窗 }
而若是你用kartik-v/yii2-dialog的confirm也這樣寫,則永遠不會彈窗,由於是異步回調的,不會去等你點擊。
function abc(){ krajeeDialog.confirm('123',function(result){ if(result){ return true; }else{ return false; } }); } if(abc()){ alert('456');//因爲是異步回調,因此無論點不點都不會彈窗 }
可能有人會想(好比我)這樣寫行不行?不行,不支持這樣的寫法,bootstrap3-dialog中這樣寫返回的是窗口有沒有open。
if(krajeeDialog.confirm('123',function(result){}){ return true; }else{ return false; }
因此要想在kartik-v/yii2-dialog的confirm中執行alert,只能將alert放在回調函數中:
function abc(){ krajeeDialog.confirm('123',function(result){ if(result){ alert('456'); }else{ //do something } }); }
以上的不一樣,再加上是在vendor中修改有違原則啊(拿出來很費勁,又是繼承什麼的,而導出csv的js沒找到相似yii.js那樣覆蓋的方法,只能從新寫引入什麼的),也是我不想改源碼的緣由。坑爹。好吧,下面繼續說怎麼改:
一、{toggleData}顯示所有記錄,它的調用confirm是在vendor/kartik-v/yii2-grid/GridView.php中的getToggleDataScript方法,咱們修改return就能夠:
$url=Url::current([$this->_toggleDataKey => $tag]);//先定義須要跳轉的url return "\$('#{$this->_toggleButtonId}').on('{$event}',function(e){ e.preventDefault();//先阻止點擊事件 krajeeDialog.confirm('{$msg}',function(data){ if (data) { window.location.href='{$url}';//點擊是則跳轉 } }); //下面這條是原來的方法 // if(!window.confirm('{$msg}')){e.preventDefault();} });";
二、{export}中的導出提示,是在vendor/kartik-v/yii2-grid/assets/js/kv-grid-export.js中:這個就麻煩了,感受須要重寫關聯的notify方法和listenClick方法。誰寫完了,麻煩告訴一聲吧。
kvConfirm: function (msg) { try { return window.confirm(msg);//調的這個 } catch (err) { return true; } }
上面就這樣吧。
下面說下session中的flash,咱們通常建立完成等操做時,須要給點提示是完成了仍是怎麼着。在Yii中有自帶flash方法來實現,可點擊這裏查看,其實在adminLTE這個後臺框架中已集成了Alert小部件,咱們能夠在backend/views/layout/content.php中發現此小部件的調用<?= Alert::widget() ?>,這是咱們只須要在controller中添加setFlash方法,那麼就能在view中接收到:
public function actionCreate() { $model = new User(); if ($model->load(Yii::$app->request->post()) && $model->save()) { $session = Yii::$app->session;//session $session->setFlash('success', '建立成功');//添加flash return $this->redirect(['index']); } else { return $this->render('create', [ 'model' => $model, ]); } }
捕捉到的:(adminLTE的alert樣式顏色就是這麼深,而Yii框架自帶的顏色雖然淺,可是與此後臺框架的顏色也不搭配)
進一步擴展就是,若是是成功的提示,那我5s後能夠隱藏,那能夠這樣設置,在backend/views/layout/content.php中添加下面漸隱的js代碼
<?php //這是一段,在顯示後定裏消失的JQ代碼 $this->registerJs(" $('.alert-success').animate({opacity: 1.0}, 5000).fadeOut('slow'); "); ?>
唉?爲何忽然說到flash,明顯先後文不統一嗎,差評!主要是,既然有alert形式的flash,那固然也能夠用彈窗的方式來展現啊。kartik-v/yii2-dialog雖然有alert、dialog功能,可是在這裏都和我想要的不太同樣,因此咱們直接調用原生的方法來寫,主要的方法是這樣:(下面有詳細封裝)
var dialogShow=BootstrapDialog.show({ type:BootstrapDialog.TYPE_SUCCESS, title:'提示消息', message:'建立成功,3s後自動關閉', size:BootstrapDialog.SIZE_SMALL, buttons:[ { label: '關閉', action: function(dialogItself){ dialogItself.close(); } } ] });
咱們固然能夠直接在index.php中寫,可是東西有點多,最好封裝一下,好吧,那就參照Alert來寫一個Popup的widget來用吧:(一些介紹點這裏),在common/widgets中新建Popup.php,直接貼代碼吧。因爲只是註冊js,沒有返回值什麼的,因此沒有用到run()方法。
1 <?php 2 3 namespace common\widgets; 4 5 class Popup extends \yii\bootstrap\Widget 6 { 7 /** 8 * 樣式數組 9 * @var [type] 10 */ 11 public $popupTypes = [ 12 'default' => 'BootstrapDialog.TYPE_DEFAULT', 13 'info' => 'BootstrapDialog.TYPE_INFO', 14 'primary' => 'BootstrapDialog.TYPE_PRIMARY', 15 'success' => 'BootstrapDialog.TYPE_SUCCESS', 16 'warning' => 'BootstrapDialog.TYPE_WARNING', 17 'danger' => 'BootstrapDialog.TYPE_WARNING' 18 ]; 19 /** 20 * 尺寸數組 21 * @var [type] 22 */ 23 public $sizeTypes=[ 24 'nomal'=>'BootstrapDialog.SIZE_NORMAL', 25 'small'=>'BootstrapDialog.SIZE_SMALL', 26 'wide'=>'BootstrapDialog.SIZE_WIDE', 27 'large'=>'BootstrapDialog.SIZE_LARGE' 28 29 ]; 30 /** 31 * 標題 32 * @var [type] 33 */ 34 public $title; 35 /** 36 * 尺寸 37 * @var [type] 38 */ 39 public $size; 40 41 public function init() 42 { 43 parent::init(); 44 //默認標題 45 if ($this->title === null) { 46 $this->title = '消息提示'; 47 } 48 //默認樣式 49 if ($this->size===null || !isset($this->sizeTypes[$this->size])){ 50 $this->size='small'; 51 } 52 53 $session = \Yii::$app->session; 54 $flashes = $session->getAllFlashes(); 55 56 $view = $this->getView(); 57 58 foreach ($flashes as $type => $data) { 59 if (isset($this->popupTypes[$type])) { 60 $data = (array) $data; 61 foreach ($data as $i => $message) { 62 $view->registerJs(" 63 var dialogShow=BootstrapDialog.show({ 64 type:".$this->popupTypes[$type].", 65 title:'".$this->title."', 66 message:'".$message."', 67 size:".$this->sizeTypes[$this->size].", 68 buttons:[ 69 { 70 label: '關閉', 71 action: function(dialogItself){ 72 dialogItself.close(); 73 } 74 } 75 ] 76 }); 77 "); 78 // 若是是成功,須要增長3s後自動關閉,其他警告等則不須要 79 if($type=='success'){ 80 $view->registerJs(" 81 setTimeout(function(){ dialogShow.close() }, 3000); 82 "); 83 } 84 } 85 86 $session->removeFlash($type); 87 } 88 } 89 } 90 }
而後在backend/views/layout/content.php引用小部件:
use common\widgets\Popup; <?= Popup::widget([ 'title'=>'消息', 'size'=>'small'//參數不寫會有默認值 ]) ?>
看下效果:若是是success,則會自動消失。
那彈出框Popup和提示Alert最大區別是,當存在addFlash方法時,Alert能夠依次排列顯示多個,而彈出框Popup則會重複覆蓋顯示,不太友好。固然了在不用addFlash方法時彈出框Popup的顯示更漂亮醒目。
好了,就這樣,睡覺先!