实现一个联系客服对话框的前端部分

您所在的位置:网站首页 意想不到的字谜怎么写 实现一个联系客服对话框的前端部分

实现一个联系客服对话框的前端部分

2024-07-07 13:54| 来源: 网络整理| 查看: 265

  一直都想写一个对话框,正好公司买了一个,就照着外观自己也写一个,每次写都会碰到意想不到的情况,通过解决这些情况,就很好的了解和学习了js知识。  先给出效果图:

      

    这一次主要是碰到了一个问题:极短时间内多次按Enter键触发”发送内容不能为空“的提示,提示也会多次触发渐隐效果,但实际上应该是出发一次,后来发现setTimeout()方法是有一个类似id的返回值(setInterval()方法也类似),可以用clearTimeout(id),将其停止。    同时,也测试了一下键盘事件的发生顺序和可以获得的内容。输入框触发事件的顺序是focus-keydown-input-keyup-change-blur,在keydown发生的时候,能获得keycode,但是不能获得value;在input发生的时候,能获得value;在keyup发生的时候,能获得keycode,同时也能获得value,就是利用这个,实现了Enter键发送消息,shift+Enter换行。

    getElementByXX与querySelector(),querySelectorAll()还是有区别的,但是本文中getElementById()完全可以用后者替代。据我所知getElementById()性能上要比querySelector()快一些,而且getElementByXX是动态的查询,querySelectorAll()只能查询出HTML代码中的节点,不会考虑动态添加的。

    另外,操作DOM生成提问和回复的js代码写的不好,容我在搜索学习下=。=至少目前看来,createElement()之后应该马上appendChild()到父节点;可能一次性用innerHTML加入内容会更好。(2017年5月26日更新:今天在搜索关于回流与重绘的问题时候,突然想到了以前DOM笔记里的有关DocumentFragment类型的内容,毫无疑问,利用DocumentFragment类型来处理这种动态节点的添加再好不过了)

    下面给出代码:

    HTML & JS  

1 doctype html> 2 3 4 5 客服聊天 6 7 8 9 10 11 12 13 14 15 16 17 18 联系客服 19 20 21 22 > 23 24 头像 25 26 XX客服 27 XX客服支持平台 28 29 30 31 32 您好,请提问 33 34 35 36 !发送内容不能为空 37 38 39 小工具预留位置 40 41 42 43 44 45 var doc = document; 46 // 模拟一些后端传输数据 47 var serviceData = { 48 'robot': { 49 'name': 'robot001', 50 'dialogue': ['模拟回复1', '模拟回复2', '模拟回复3'], 51 'welcome': '您好,robot001为您服务' 52 } 53 }; 54 55 var dialogueInput = doc.getElementById('dialogue_input'), 56 dialogueContain = doc.getElementById('dialogue_contain'), 57 dialogueHint = doc.getElementById('dialogue_hint'), 58 btnOpen = doc.getElementById('btn_open'), 59 btnClose = doc.getElementById('btn_close'), 60 timer, 61 timerId, 62 shiftKeyOn = false; // 辅助判断shift键是否按住 63 64 btnOpen.addEventListener('click', function(e) { 65 $('.dialogue-support-btn').css({'display': 'none'}); 66 $('.dialogue-main').css({'display': 'inline-block', 'height': '0'}); 67 $('.dialogue-main').animate({'height': '600px'}) 68 }) 69 70 btnClose.addEventListener('click', function(e) { 71 $('.dialogue-main').animate({'height': '0'}, function() { 72 $('.dialogue-main').css({'display': 'none'}); 73 $('.dialogue-support-btn').css({'display': 'inline-block'}); 74 }); 75 }) 76 77 dialogueInput.addEventListener('keydown', function(e) { 78 var e = e || window.event; 79 if (e.keyCode == 16) { 80 shiftKeyOn = true; 81 } 82 if (shiftKeyOn) { 83 return true; 84 } else if (e.keyCode == 13 && dialogueInput.value == '') { 85 // console.log('发送内容不能为空'); 86 // 多次触发只执行最后一次渐隐 87 setTimeout(function() { 88 fadeIn(dialogueHint); 89 clearTimeout(timerId) 90 timer = setTimeout(function() { 91 fadeOut(dialogueHint) 92 }, 2000); 93 }, 10); 94 timerId = timer; 95 return true; 96 } else if (e.keyCode == 13) { 97 var nodeP = doc.createElement('p'), 98 nodeSpan = doc.createElement('span'); 99 nodeP.classList.add('dialogue-customer-contain'); 100 nodeSpan.classList.add('dialogue-text', 'dialogue-customer-text'); 101 nodeSpan.innerHTML = dialogueInput.value; 102 nodeP.appendChild(nodeSpan); 103 dialogueContain.appendChild(nodeP); 104 dialogueContain.scrollTop = dialogueContain.scrollHeight; 105 submitCustomerText(dialogueInput.value); 106 } 107 }); 108 109 dialogueInput.addEventListener('keyup', function(e) { 110 var e = e || window.event; 111 if (e.keyCode == 16) { 112 shiftKeyOn = false; 113 return true; 114 } 115 if (!shiftKeyOn && e.keyCode == 13) { 116 dialogueInput.value = null; 117 } 118 }); 119 120 function submitCustomerText(text) { 121 console.log(text) 122 // code here 向后端发送text内容 123 124 // 模拟后端回复 125 var num = Math.random() * 10; 126 if (num 0) { 149 n -= 10; 150 obj.style.opacity = '0.' + n; 151 } else if (n = 80) { 167 168 obj.style.opacity = '1'; 169 clearInterval(time); 170 } 171 }, 100); 172 return true; 173 } 174 175 176

    CSS

  

1 @charset "utf-8"; 2 /*公共样式*/ 3 html{font-family:"Helvetica Neue",Helvetica,STHeiTi,sans-serif;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;} 4 body{-webkit-overflow-scrolling:touch;margin:0;} 5 ul{margin:0;padding:0;list-style:none;outline:none;} 6 dl,dd{margin:0;} 7 a{display:inline-block;margin:0;padding:0;text-decoration:none;background:transparent;outline:none;color:#000;} 8 a:link,a:visited,a:hover,a:active{text-decoration:none;color:currentColor;} 9 a,dt,dd{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;} 10 img{border:0;} 11 p{margin:0;} 12 input,button,select,textarea{margin:0;padding:0;border:0;outline:0;background-color:transparent;} 13 /*css reset*/ 14 body { 15 position: relative; 16 } 17 18 .dialogue-wrapper { 19 font-size: 14px; 20 color: #fff; 21 } 22 /*右侧点击按钮*/ 23 .dialogue-wrapper .dialogue-support-btn { 24 position: fixed; 25 display: inline-block; 26 top: 50%; 27 right: 0; 28 margin-top: -70px; 29 padding: 10px 0; 30 width: 40px; 31 height: 120px; 32 font-size: 16px; 33 font-weight: 500; 34 text-align: center; 35 cursor: pointer; 36 border-top-left-radius: 5px; 37 border-bottom-left-radius: 5px; 38 box-shadow: -1px 1px 5px rgba(0, 0, 0, .4); 39 background-color: #5d94f3; 40 } 41 42 .dialogue-wrapper .dialogue-support-btn .dialogue-support-icon { 43 position: relative; 44 display: inline-block; 45 margin-bottom: -2px; 46 width: 20px; 47 height: 16px; 48 border-radius: 4px; 49 background-color: #fff; 50 } 51 52 .dialogue-wrapper .dialogue-support-btn .dialogue-support-icon:before { 53 content: ''; 54 position: absolute; 55 left: 50%; 56 bottom: -6px; 57 margin-left: -3px; 58 width: 0; 59 height: 0; 60 border-left: 4px solid transparent; 61 border-right: 4px solid transparent; 62 border-top: 6px solid #fff; 63 } 64 65 .dialogue-wrapper .dialogue-support-btn .dialogue-support-line { 66 display: inline-block; 67 width: 100%; 68 height: 1px; 69 background-color: #ddd; 70 } 71 72 .dialogue-wrapper .dialogue-support-btn .dialogue-support-text { 73 padding: 5px 0; 74 letter-spacing: 4px; 75 writing-mode: vertical-rl; 76 -webkit-user-select: none; 77 } 78 79 /*底部客服对话框*/ 80 .dialogue-wrapper .dialogue-main { 81 position: fixed; 82 display: none; 83 right: 100px; 84 bottom: 10px; 85 width: 400px; 86 height: 600px; 87 border-radius: 4px; 88 box-shadow: 0 0 5px rgba(0, 0, 0, .4); 89 } 90 91 /*客服对话框头部*/ 92 .dialogue-wrapper .dialogue-main .dialogue-header { 93 position: relative; 94 padding: 10px; 95 height: 80px; 96 border-top-left-radius: 4px; 97 border-top-right-radius: 4px; 98 box-shadow: 0 0 5px rgba(0, 0, 0, .2); 99 background-color: #5d94f3; 100 } 101 102 .dialogue-wrapper .dialogue-main .dialogue-close { 103 position: absolute; 104 top: 10px; 105 right: 20px; 106 padding: 2px; 107 font-size: 22px; 108 transform: rotate(90deg); 109 cursor: pointer; 110 } 111 112 .dialogue-wrapper .dialogue-main .dialogue-service-info { 113 position: relative; 114 top: 50%; 115 margin-top: -20px; 116 height: 40px; 117 } 118 119 .dialogue-wrapper .dialogue-main .dialogue-service-img { 120 display: inline-block; 121 margin: 0 10px 0 20px; 122 width: 40px; 123 height: 40px; 124 text-align: center; 125 line-height: 40px; 126 vertical-align: middle; 127 color: #000; 128 border-radius: 50%; 129 box-shadow: 1px 1px 4px rgba(0, 0, 0, .2); 130 background-color: #fff; 131 } 132 133 .dialogue-wrapper .dialogue-main .dialogue-service-title { 134 display: inline-block; 135 vertical-align: middle; 136 } 137 138 .dialogue-wrapper .dialogue-main .dialogue-service-detail { 139 font-size: 12px; 140 } 141 142 /*客服对话框内容*/ 143 .dialogue-wrapper .dialogue-main .dialogue-contain { 144 overflow-y: auto; 145 padding: 10px; 146 height: 380px; 147 word-wrap: break-word; 148 background-color: #f9f9f9; 149 } 150 151 .dialogue-wrapper .dialogue-main .dialogue-text { 152 display: inline-block; 153 position: relative; 154 padding: 10px; 155 max-width: 120px; 156 white-space: pre-wrap; 157 border: 1px solid #09d07d; 158 border-radius: 4px; 159 background-color: #09d07d; 160 box-sizing: border-box; 161 } 162 163 .dialogue-wrapper .dialogue-main .dialogue-service-contain { 164 margin-bottom: 10px; 165 text-align: left; 166 } 167 168 .dialogue-wrapper .dialogue-main .dialogue-service-text { 169 margin-left: 20px; 170 } 171 172 .dialogue-wrapper .dialogue-main .dialogue-service-text:before { 173 content: ''; 174 position: absolute; 175 top: 50%; 176 left: -10px; 177 width: 0; 178 height: 0; 179 border-top: 6px solid transparent; 180 border-bottom: 6px solid transparent; 181 border-right: 10px solid #09d07d; 182 -webkit-transform: translate(0, -50%); 183 transform: translate(0, -50%); 184 } 185 186 .dialogue-wrapper .dialogue-main .dialogue-customer-contain { 187 margin-bottom: 10px; 188 text-align: right; 189 } 190 191 .dialogue-wrapper .dialogue-main .dialogue-customer-text { 192 margin-right: 20px; 193 } 194 195 .dialogue-wrapper .dialogue-main .dialogue-customer-text:after { 196 content: ''; 197 position: absolute; 198 top: 50%; 199 right: -10px; 200 width: 0; 201 height: 0; 202 border-top: 6px solid transparent; 203 border-bottom: 6px solid transparent; 204 border-left: 10px solid #09d07d; 205 -webkit-transform: translate(0, -50%); 206 transform: translate(0, -50%); 207 } 208 209 /*客服对话框底部与输入*/ 210 .dialogue-wrapper .dialogue-main .dialogue-submit { 211 position: relative; 212 padding: 10px; 213 height: 100px; 214 color: #000; 215 word-wrap: break-word; 216 border-top: 1px solid #ddd; 217 box-sizing: border-box; 218 } 219 220 /*空输入提示*/ 221 .dialogue-wrapper .dialogue-main .dialogue-hint { 222 position: absolute; 223 top: -15px; 224 left: 20px; 225 padding: 2px; 226 width: 140px; 227 height: 18px; 228 opacity: 0; 229 font-size: 12px; 230 text-align: center; 231 line-height: 18px; 232 border: 1px solid #ddd; 233 box-shadow: 1px 1px 4px rgba(0, 0, 0, .4); 234 background-color: #fff; 235 } 236 237 .dialogue-wrapper .dialogue-main .dialogue-hint-icon { 238 display: inline-block; 239 width: 18px; 240 height: 18px; 241 margin-right: 5px; 242 font-size: 14px; 243 font-style: italic; 244 font-weight: 700; 245 vertical-align: middle; 246 line-height: 18px; 247 color: #fff; 248 border-radius: 50%; 249 background-color: #5d94f3 250 } 251 252 .dialogue-wrapper .dialogue-main .dialogue-hint-text { 253 display: inline-block; 254 vertical-align: middle; 255 } 256 257 /*输入框*/ 258 .dialogue-wrapper .dialogue-submit .dialogue-input-text { 259 overflow-y: auto; 260 display: inline-block; 261 padding: 5px 10px; 262 width: 295px; 263 height: 70px; 264 vertical-align: middle; 265 white-space: pre-wrap; 266 word-wrap: break-word; 267 resize: none; 268 border-right: 1px solid #ddd; 269 box-sizing: border-box; 270 } 271 272 .dialogue-wrapper .dialogue-submit .dialogue-input-tools { 273 display: inline-block; 274 width: 80px; 275 height: 80px; 276 vertical-align: middle; 277 }

   2017年6月1日补充:

  利用端午好好夯实了一下js的对象、原型链、继承等知识。

  代码中的渐隐、渐显完全可以扩展到Object的原型对象上:

  

1 // 渐隐 2 Object.prototype.iFadeOut = function() { 3 var n = 100, 4 that = this; 5 var time = setInterval(function() { 6 if (n > 0) { 7 n -= 10; 8 that.style.opacity = '0.' + n; 9 } else if (n


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3