
<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">

<h4>A PHP Error was encountered</h4>

<p>Severity: Notice</p>
<p>Message:  Trying to get property 'slug' of non-object</p>
<p>Filename: helpers/link_helper.php</p>
<p>Line Number: 17</p>


	<p>Backtrace:</p>
	
		
	
		
	
		
			<p style="margin-left:10px">
			File: /www/wwwroot/ths.visiter.in/application/helpers/link_helper.php<br />
			Line: 17<br />
			Function: _error_handler			</p>

		
	
		
			<p style="margin-left:10px">
			File: /www/wwwroot/ths.visiter.in/application/controllers/Seo.php<br />
			Line: 35<br />
			Function: getUrlCateNews			</p>

		
	
		
	
		
			<p style="margin-left:10px">
			File: /www/wwwroot/ths.visiter.in/index.php<br />
			Line: 318<br />
			Function: require_once			</p>

		
	

</div><?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>http://ths.visiter.in/</loc><lastmod/><changefreq>always</changefreq><priority>1.0</priority></url><url><loc>http://ths.visiter.in/ve-apeckids-c1</loc><lastmod>2020-11-12</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/cam-nang-c2</loc><lastmod>2020-11-12</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/huong-dan-su-dung-app-danh-cho-giao-vien-c3</loc><lastmod>2020-12-10</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/huong-dan-su-dung-app-danh-cho-phu-huynh-c4</loc><lastmod>2020-12-10</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/huong-dan-quan-tri-website-admin-c5</loc><lastmod>2020-12-10</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/field-1-c6</loc><lastmod>2020-12-15</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/tai-lieu-1-c7</loc><lastmod>2020-12-16</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/category-event-1-c8</loc><lastmod>2020-12-23</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/he-thong-truong-hoc-c9</loc><lastmod>2021-07-23</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url><url><loc>http://ths.visiter.in/-c10</loc><lastmod>2021-07-24</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url></urlset> <style type="text/css">
/* Hide debugbar when printing a page */
@media print {
  div.phpdebugbar {
    display: none;
  }
}

div.phpdebugbar {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  border-top: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
  background: #fff;
  z-index: 10000;
  font-size: 14px;
  color: #000;
  text-align: left;
  line-height: 1;
  letter-spacing: normal;
  direction: ltr;
}

div.phpdebugbar a,
div.phpdebugbar-openhandler {
  cursor: pointer;
}

div.phpdebugbar-drag-capture {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10001;
  background: none;
  display: none;
  cursor: ns-resize;
}

div.phpdebugbar-closed {
    width: auto;
}

div.phpdebugbar * {
  margin: 0;
  padding: 0;
  border: 0;
  font-weight: normal;
  text-decoration: none;
  clear: initial;
  width: auto;
  -moz-box-sizing: content-box;
       box-sizing: content-box;
}

div.phpdebugbar ol, div.phpdebugbar ul {
  list-style: none;
}

div.phpdebugbar ul li, div.phpdebugbar ol li, div.phpdebugbar dl li {
  line-height: normal;
}

div.phpdebugbar table, .phpdebugbar-openhandler table {
  border-collapse: collapse;
  border-spacing: 0;
  color: inherit;
}

div.phpdebugbar input[type='text'], div.phpdebugbar input[type='password'] {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
  background: #fff;
  font-size: 14px;
  color: #000;
  border: 0;
  padding: 0;
  margin: 0;
}

div.phpdebugbar code, div.phpdebugbar pre, div.phpdebugbar samp {
  background: none;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  font-size: 1em;
  border: 0;
  padding: 0;
  margin: 0;
}

div.phpdebugbar code, div.phpdebugbar pre {
  color: #000;
}

div.phpdebugbar pre.sf-dump {
  color: #a0a000;
  outline: 0;
}

a.phpdebugbar-restore-btn {
  float: left;
  padding: 5px 8px;
  font-size: 14px;
  color: #555;
  text-decoration: none;
  border-right: 1px solid #ddd;
}

div.phpdebugbar-resize-handle {
  display: none;
  height: 4px;
  margin-top: -4px;
  width: 100%;
  background: none;
  border-bottom: 1px solid #ccc;
  cursor: ns-resize;
}

div.phpdebugbar-closed, div.phpdebugbar-minimized{
  border-top: 1px solid #ccc;
}
/* -------------------------------------- */

a.phpdebugbar-restore-btn {
    background: #efefef url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2020%2020%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle%20fill%3D%22%23000%22%20cx%3D%2210%22%20cy%3D%2210%22%20r%3D%229%22%2F%3E%3Cpath%20d%3D%22M6.039%208.342c.463%200%20.772.084.927.251.154.168.191.455.11.862-.084.424-.247.727-.487.908-.241.182-.608.272-1.1.272h-.743l.456-2.293h.837zm-2.975%204.615h1.22l.29-1.457H5.62c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.13-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H4.153l-1.089%205.479zM9.235%206.02h1.21l-.289%201.458h1.079c.679%200%201.147.115%201.405.347.258.231.335.607.232%201.125l-.507%202.55h-1.23l.481-2.424c.055-.276.035-.464-.06-.565-.095-.1-.298-.15-.608-.15H9.98L9.356%2011.5h-1.21l1.089-5.48M15.566%208.342c.464%200%20.773.084.928.251.154.168.19.455.11.862-.084.424-.247.727-.488.908-.24.182-.607.272-1.1.272h-.742l.456-2.293h.836zm-2.974%204.615h1.22l.29-1.457h1.046c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.129-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H13.68l-1.089%205.479z%22%20fill%3D%22%23FFF%22%2F%3E%3C%2Fsvg%3E)  no-repeat center / 20px 20px;
}
div.phpdebugbar-header {
  min-height: 26px;
  line-height: 16px;
}
div.phpdebugbar-header:before, div.phpdebugbar-header:after {
  display: table;
  line-height: 0;
  content: "";
}
div.phpdebugbar-header:after {
  clear: both;
}
div.phpdebugbar-header-left {
  float: left;
}
div.phpdebugbar-header-right {
  float: right;
}
div.phpdebugbar-header > div > * {
  padding: 5px;
  font-size: 14px;
  height: 16px;
  color: #555;
  text-decoration: none;
}
div.phpdebugbar-header-left > *,
div.phpdebugbar-header-right > * {
  line-height: 0;
  display: flex;
  align-items: center;
}
div.phpdebugbar-header-left > * {
  float: left;
}
div.phpdebugbar-header-right > * {
  float: right;
}
div.phpdebugbar-header-right > select {
  padding: 0;
  line-height: 1em;
}

/* -------------------------------------- */

span.phpdebugbar-indicator,
a.phpdebugbar-indicator
{
  border-right: 1px solid #ddd;
}

a.phpdebugbar-tab.phpdebugbar-active {
  background: #ccc;
  color: #444;
  background-image: linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
  background-image: -o-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
  background-image: -moz-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
  background-image: -webkit-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
  background-image: -ms-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
  background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.41, rgb(173,173,173)), color-stop(0.71, rgb(209,209,209)));
}
  a.phpdebugbar-tab span.phpdebugbar-badge {
    display: none;
    margin-left: 5px;
    font-size: 11px;
    line-height: 14px;
    padding: 0 6px;
    background: #ccc;
    border-radius: 4px;
    color: #555;
    font-weight: normal;
    text-shadow: none;
  }
  a.phpdebugbar-tab.phpdebugbar-active  span.phpdebugbar-badge {
    background: #555;
    color: #fff;
  }
  a.phpdebugbar-tab i {
    display: none;
    vertical-align: middle;
  }
  a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-visible {
    display: inline;
  }
  a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-important {
    background: #ed6868;
    color: white;
  }

a.phpdebugbar-close-btn, a.phpdebugbar-open-btn, a.phpdebugbar-restore-btn, a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
  width: 16px;
  height: 16px;
}

a.phpdebugbar-maximize-btn { display: none}

a.phpdebugbar-minimize-btn { display: block}

div.phpdebugbar-minimized a.phpdebugbar-maximize-btn { display: block}

div.phpdebugbar-minimized a.phpdebugbar-minimize-btn { display: none}

a.phpdebugbar-minimize-btn {
  background:url(data:image/svg+xml,%3Csvg%20viewBox=%220%200%201792%201792%22%20fill=%22none%22%20xmlns=%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d=%22m1683%20653.5-742%20741c-12.667%2012.67-27.667%2019-45%2019s-32.333-6.33-45-19l-742-741c-12.667-12.667-19-27.833-19-45.5s6.333-32.833%2019-45.5l166-165c12.667-12.667%2027.667-19%2045-19s32.333%206.333%2045%2019l531%20531%20531-531c12.67-12.667%2027.67-19%2045-19s32.33%206.333%2045%2019l166%20165c12.67%2012.667%2019%2027.833%2019%2045.5s-6.33%2032.833-19%2045.5Z%22%20fill=%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat center / 14px 14px;
}

a.phpdebugbar-maximize-btn {
  background: url(data:image/svg+xml,%3Csvg%20viewBox=%220%200%201792%201792%22%20fill=%22none%22%20xmlns=%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d=%22m1683%201229.5-166%20165c-12.67%2012.67-27.67%2019-45%2019s-32.33-6.33-45-19l-531-531-531%20531c-12.667%2012.67-27.667%2019-45%2019s-32.333-6.33-45-19l-166-165c-12.667-12.67-19-27.83-19-45.5s6.333-32.83%2019-45.5l742-741c12.667-12.667%2027.667-19%2045-19s32.333%206.333%2045%2019l742%20741c12.67%2012.67%2019%2027.83%2019%2045.5s-6.33%2032.83-19%2045.5Z%22%20fill=%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat center / 14px 14px;
}

a.phpdebugbar-close-btn {
  background: url(data:image/svg+xml,%3Csvg%20viewBox=%220%200%201792%201792%22%20fill=%22none%22%20xmlns=%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d=%22M1490%201258c0%2026.67-9.33%2049.33-28%2068l-136%20136c-18.67%2018.67-41.33%2028-68%2028s-49.33-9.33-68-28l-294-294-294%20294c-18.667%2018.67-41.333%2028-68%2028s-49.333-9.33-68-28l-136-136c-18.667-18.67-28-41.33-28-68s9.333-49.33%2028-68l294-294-294-294c-18.667-18.667-28-41.333-28-68s9.333-49.333%2028-68l136-136c18.667-18.667%2041.333-28%2068-28s49.333%209.333%2068%2028l294%20294%20294-294c18.67-18.667%2041.33-28%2068-28s49.33%209.333%2068%2028l136%20136c18.67%2018.667%2028%2041.333%2028%2068s-9.33%2049.333-28%2068l-294%20294%20294%20294c18.67%2018.67%2028%2041.33%2028%2068Z%22%20fill=%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat center / 14px 14px;
}

a.phpdebugbar-open-btn {
  background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 1792 1792'%3e%3cpath fill='%23555' d='M1646 991.796c0 16.494-8.25 34.064-24.75 52.684l-268.22 316.13c-22.89 27.14-54.95 50.16-96.2 69.05S1177.4 1458 1142.27 1458H273.728c-18.095 0-34.194-3.46-48.297-10.38-14.104-6.92-21.155-18.36-21.155-34.32 0-16.5 8.249-34.06 24.747-52.69l268.228-316.13c22.884-27.14 54.949-50.156 96.194-69.049 41.246-18.893 79.431-28.34 114.556-28.34h868.549c18.09 0 34.19 3.459 48.3 10.378 14.1 6.918 21.15 18.361 21.15 34.327Zm-273.82-274.615v127.728H708.001c-50.027 0-102.448 12.64-157.264 37.919-54.817 25.28-98.457 57.078-130.921 95.397L150.79 1294.35l-3.992 4.79c0-2.13-.133-5.46-.399-9.98-.266-4.52-.399-7.85-.399-9.98V512.817c0-48.962 17.563-91.005 52.688-126.13 35.125-35.126 77.168-52.688 126.131-52.688h255.455c48.962 0 91.005 17.562 126.13 52.688 35.126 35.125 52.688 77.168 52.688 126.13v25.546h434.278c48.96 0 91 17.563 126.13 52.688 35.12 35.125 52.68 77.168 52.68 126.13Z'/%3e%3c/svg%3e") no-repeat center / 14px 14px;
}

.phpdebugbar-indicator {
  position: relative;
  cursor: pointer;
}
  .phpdebugbar-indicator span.phpdebugbar-text {
    margin-left: 5px;
  }
  .phpdebugbar-indicator span.phpdebugbar-tooltip {
    display: none;
    position: absolute;
    top: -30px;
    background: #efefef70;
    border: 1px solid #ccc;
    color: #555;
    font-size: 11px;
    padding: 2px 6px;
    z-index: 1000;
    text-align: center;
    white-space: nowrap;
    right: 0;
    line-height: 1.5;
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
  }
  .phpdebugbar-indicator:hover span.phpdebugbar-tooltip:not(.phpdebugbar-disabled) {
    display: block;
  }

select.phpdebugbar-datasets-switcher {
  float: right;
  display: none;
  margin: 2px 0 0 7px;
  max-width: 200px;
  max-height: 23px;
  padding: 0;
}

/* -------------------------------------- */

div.phpdebugbar-body {
  border-top: 1px solid #ccc;
  display: none;
  position: relative;
  height: 300px;
}

/* -------------------------------------- */

div.phpdebugbar-panel {
  display: none;
  height: 100%;
  overflow: auto;
  width: 100%;
}
div.phpdebugbar-panel.phpdebugbar-active {
  display: block;
}

/* -------------------------------------- */

div.phpdebugbar-mini-design a.phpdebugbar-tab {
  position: relative;
  border-right: 1px solid #ddd;
}
  div.phpdebugbar-mini-design a.phpdebugbar-tab span.phpdebugbar-text {
    display: none;
  }
  div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
    display: block;
    position: absolute;
    top: -30px;
    background: #efefef70;
    opacity: 1;
    border: 1px solid #ccc;
    color: #555;
    font-size: 11px;
    padding: 2px 6px;
    z-index: 1000;
    text-align: center;
    right: 0;
    line-height: 1.5;
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
  }
  div.phpdebugbar-mini-design a.phpdebugbar-tab i {
    display:inline-block;
  }

/* -------------------------------------- */

  a.phpdebugbar-tab.phpdebugbar-tab-history {
    min-width: 16px;
    height: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  a.phpdebugbar-tab.phpdebugbar-tab-history .phpdebugbar-text {
      display: none;
      white-space: nowrap;
  }
  a.phpdebugbar-tab.phpdebugbar-tab-history i {
    display:inline-block;
  }
  .phpdebugbar-widgets-dataset-history table {
      width: 100%;
      table-layout: fixed;
  }
    .phpdebugbar-widgets-dataset-history table th {
        font-weight: bold;
    }
    .phpdebugbar-widgets-dataset-history table td, .phpdebugbar-widgets-dataset-history table th {
        padding: 6px 3px;
        border-bottom: 1px solid #ddd;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .phpdebugbar-widgets-dataset-history table td a{
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .phpdebugbar-widgets-dataset-history table tr.phpdebugbar-widgets-active {
        background: #ccc;
        color: #444;
    }
    .phpdebugbar-widgets-dataset-history span.phpdebugbar-badge {
        margin: 0 5px 0 2px;
        font-size: 11px;
        line-height: 14px;
        padding: 0 6px;
        background: #ccc;
        border-radius: 4px;
        color: #555;
        font-weight: normal;
        text-shadow: none;
        vertical-align: middle;
    }
    .phpdebugbar-widgets-dataset-history .phpdebugbar-widgets-dataset-actions {
        text-align: center;
        padding: 7px 0;
        position: sticky;
        top: 0;
        background: #fff;
    }
    .phpdebugbar-widgets-dataset-history .phpdebugbar-widgets-dataset-actions a {
        margin: 0 10px;
    }
    .phpdebugbar-widgets-dataset-history .phpdebugbar-widgets-dataset-actions input {
        appearance: checkbox !important;
        margin: 5px;
    }

pre.phpdebugbar-widgets-code-block {
    white-space: pre;
    word-wrap: normal;
    overflow: hidden;
}
  pre.phpdebugbar-widgets-code-block code {
    display: block;
    overflow-x: auto;
    overflow-y: hidden;
  }
  pre.phpdebugbar-widgets-code-block code.phpdebugbar-widgets-numbered-code {
    padding: 5px;
  }
  pre.phpdebugbar-widgets-code-block ul li.phpdebugbar-widgets-highlighted-line {
    font-weight: bolder;
    text-decoration: underline;
  }
  pre.phpdebugbar-widgets-code-block ul li.phpdebugbar-widgets-highlighted-line span {
    position: absolute;
    background: #800000;
    min-width: calc(100% - 85px);
    margin-left: 10px;
    opacity: 0.15;
  }
  pre.phpdebugbar-widgets-code-block ul {
    position: static;
    float: left;
    padding: 5px;
    background: #cacaca;
    border-right: 1px solid #aaa;
    text-align: right;
  }

  .phpdebugbar-widgets-kvlist span.phpdebugbar-widgets-filename,
  li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
    display: block;
    font-style: italic;
    float: right;
    margin-left: 8px;
    color: #888;
  }

  a.phpdebugbar-widgets-editor-link:hover {
    color: #aaaaaa;
  }

  a.phpdebugbar-widgets-editor-link:before {
    font-family: FontAwesome;
    margin-right: 4px;
    font-size: 12px;
    font-style: normal;
  }

  a.phpdebugbar-widgets-editor-link:before {
    content: "\f08e";
    margin-left: 4px;
  }

/* -------------------------------------- */

ul.phpdebugbar-widgets-list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
  ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
    padding: 3px;
    border-bottom: 1px solid #eee;
    position: relative;
    overflow: hidden;
  }
  ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:hover {
    background: #fafafa;
  }

/* -------------------------------------- */

div.phpdebugbar-widgets-messages {
  position: relative;
  height: 100%;
}
  div.phpdebugbar-widgets-messages ul.phpdebugbar-widgets-list {
    padding-bottom: 45px;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value:before {
    font-family: FontAwesome;
    margin-right: 8px;
    font-size: 11px;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-alert:before {
    content: "\f0f3";
    color: #cbcf38;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-debug:before {
    content: "\f188";
    color: #78d79a;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-warning:before,
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-emergency:before,
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-notice:before {
    content: "\f071";
    color: #ecb03d;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error,
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-critical:before {
    color: red;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error:before,
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-critical:before {
    content: "\f057";
  }
  dl.phpdebugbar-widgets-kvlist dd.phpdebugbar-widgets-value pre.sf-dump,
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item pre.sf-dump {
    display: inline-block !important;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector,
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-label {
    float: right;
    font-size: 12px;
    padding: 2px 4px;
    color: #888;
    margin: 0 2px;
    text-decoration: none;
    text-shadow: none;
    background: none;
    font-weight: normal;
  }
  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector {
    color: #555;
    font-style: italic;
  }
  div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar {
    position: fixed;
    bottom: 0;
    width: 100%;
    background: #fff;
  }
  div.phpdebugbar-widgets-messages li .phpdebugbar-widgets-label-called-from {
    float: right;
    color: #666;
    padding-left: 5px;
    border-bottom: 1px dotted #666;
  }
  div.phpdebugbar-widgets-messages li .phpdebugbar-widgets-label-called-from:before {
    content: "\f08d";
    font-family: FontAwesome;
    margin-right: 4px;
    font-size: 12px;
  }
    div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input {
      border: 0;
      margin: 0;
      margin-left: 7px;
      width: 50%;
      box-shadow: none;
    }
    div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input:focus {
      outline: none;
    }
      div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter {
        float: right;
        font-size: 12px;
        padding: 2px 4px;
        background: #7cacd5;
        margin: 0 2px;
        border-radius: 4px;
        color: #fff;
        text-decoration: none;
      }
      div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
        background: #eee;
        color: #888;
      }

/* -------------------------------------- */

dl.phpdebugbar-widgets-kvlist {
  margin: 0;
}
  dl.phpdebugbar-widgets-kvlist dt {
    float: left;
    width: 150px;
    padding: 5px;
    border-top: 1px solid #eee;
    font-weight: bold;
    clear: both;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  dl.phpdebugbar-widgets-kvlist dd {
    margin-left: 160px;
    padding: 5px;
    border-top: 1px solid #eee;
    cursor: pointer;
    min-height: 17px;
  }

/* -------------------------------------- */

dl.phpdebugbar-widgets-varlist,
dl.phpdebugbar-widgets-htmlvarlist {
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
  dl.phpdebugbar-widgets-htmlvarlist dd {
    cursor: initial;
  }

/* -------------------------------------- */

ul.phpdebugbar-widgets-timeline {
  margin: 0;
  padding: 0;
  list-style: none;
}
  ul.phpdebugbar-widgets-timeline .phpdebugbar-widgets-measure {
    height: 20px;
    position: relative;
    border-bottom: 1px solid #eee;
    display: block;
  }
  ul.phpdebugbar-widgets-timeline li:hover {
    background: #fafafa;
  }
    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
      position: absolute;
      font-size: 12px;
      font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
      color: #555;
      top: 4px;
      left: 5px;
      background: none;
      text-shadow: none;
      font-weight: normal;
      white-space: pre;
    }
    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
      left: initial;
      right: 5px;
    }
    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-value {
      display: block;
      position: absolute;
      height: 10px;
      background: #3db9ec;
      top: 5px;
      border-radius: 2px;
      min-width: 1px;
    }
    ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params {
      display: none;
      width: 70%;
      margin: 10px;
      border: 1px solid #ddd;
      font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
      border-collapse: collapse;
    }
      ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params td {
        border: 1px solid #ddd;
        padding: 0 5px;
      }
      ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params .phpdebugbar-widgets-name {
        width: 20%;
        font-weight: bold;
      }

/* -------------------------------------- */

div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item {
  cursor: pointer;
}
  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message {
    display: block;
    color: red;
  }

  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-type {
    display: block;
    position: absolute;
    right: 4px;
    top: 4px;
    font-weight: bold;
  }

  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file {
    display: none;
    margin: 10px;
    padding: 5px;
    border: 1px solid #ddd;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  }

  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
    float: none;
  }

ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params {
    display: table;
    border: 0;
    width: 99%;
}

div.phpdebugbar-openhandler-overlay {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: #000;
    opacity: .3;
    z-index: 20000;
}

div.phpdebugbar-openhandler {
    position: fixed;
    margin: auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 70%;
    height: 70%;
    background: #fff;
    color: #000;
    border: 2px solid #888;
    overflow: auto;
    z-index: 20001;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 14px;
    padding-bottom: 10px;
}
    div.phpdebugbar-openhandler a {
        color: #555;
    }
    div.phpdebugbar-openhandler .phpdebugbar-openhandler-header {
        background: #efefef url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfdBgcKHQH1H7EUAAADV0lEQVQ4y7WUy28bVRSHvzvjJPbYY48dj80rTe28gCbCivPsAhBthJCoBIEQQGr/BMRjh1gA20plEYSQumFFQbBBEWVV0bLoQ1BC1YfcBDt1UicFZZzYje06M57LokVNaZJ2w7e7597zOzpX53fgfhSgzYzGDmk+7YQe0DMD/UNSD+gZzaedMKOxQ0DbnXf3IP5z1hLtyc8k8q1IuFX/N+i6LopyN7dYtNYR4ti1fO5doLqVmD+oBy90JLs6pJQ8CCEE2dxctnyz/AxQ2SwWjYRbzycTHbscx+Fh8Xg85OazC8VVKw2sqIDS3dlzJBo1X3Bdd8skKSVCiPvirusSChmhoB40rKJ1XFFVT/uGvXFwu+pBQ6erp5OdWq9v1A8KIdo9Ab9/MhJu9TUaDdbWVlEUFYlEureTP/n0IwpLNzh75gwetRlN06jdqoF7+5Mcx8br9fk0nzaJ1+s7nU4NysTupLRtW5ZKJVmpVOWpkz/LjkRCFgoFaduOrFarcnb2quzb0ytnZmZktVaT5fJNWSqV5P59+2RTU9Npxa/5e10p0XU/lmUxOryX7q5OIpEw4xPjxOMxnn/uWdqeaCNmxhgeHSSVSvHi2BidyS6OHv2S9z94D1e6exQzauqObZMeSGOtWNiOQ9iI4iIZGhplfb1CNpulNWyiqAr2xi0A5nN5QiEDze+n0QAkmic7/+diZ6K7bXLyTTxNKr19T/Hq+Css5Be4vpinWCwS8BsEQi3UajVMM45t24zsHaKv72leG59gcuINFKEsC6/X+13cfOT1S1cu8u03x8jl8ti2zfT0NCMjo9RqFS5fyhAMBejp6WZsbD9mLM6pk7+gqio/Hf+Ret1hLpv5Xhgh4+WwEZmey84ykO5HuuqWMwXgOA6ffzHF1NQR5jJ5FPWuxZaWCwcEEHzs0cfPeVtangwGjQdOfbVSpcXrRd0ktFZazVzLzw8rQHlpuXA4FAo/lIU0v3aPkBCCxesLh4Gyeic2c+Ov5d0xM57arsWtcF2XCxdnvpJSfgygbrr7wbJWioYRfqm5uXlH+6iqSr1eJ3P1yjuudD/cbp8BJIUQX/enBoYbjcaWQr//8ds5KeXbQG6n5biZXcABIDaYHkn+ev5sDvgbmAYW+L/5B5NrVZNHcIujAAAAAElFTkSuQmCC)  no-repeat 5px 4px;
        padding-left: 29px;
        min-height: 26px;
        line-height: 25px;
        color: #555;
        margin-bottom: 10px;
    }
        div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a {
            font-size: 14px;
            color: #555;
            text-decoration: none;
            float: right;
            padding: 5px 8px;
        }
    div.phpdebugbar-openhandler table {
        width: 100%;
        table-layout: fixed;
        font-size: 14px;
    }
        div.phpdebugbar-openhandler table td {
            padding: 6px 3px;
            border-bottom: 1px solid #ddd;
        }
            div.phpdebugbar-openhandler table td a{
                display: block;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            }
    div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions {
        text-align: center;
        padding: 7px 0;
    }
        div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions a {
            margin: 0 10px;
            color: #555;
        }

div.phpdebugbar-widgets-sqlqueries .phpdebugbar-widgets-status {
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  padding: 6px 6px;
  border-bottom: 1px solid #ddd;
  font-weight: bold;
  color: #555;
  background: #fafafa;
}

div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-error {
  color: red;
}

div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id {
  float: right;
  margin-left: 8px;
  color: #888;
}
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-database,
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-duration,
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-memory,
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-row-count,
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-copy-clipboard,
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-stmt-id {
  color: #555;
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before,
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link:before {
  font-family: FontAwesome;
  margin-right: 4px;
  font-size: 12px;
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database:before {
  content: "\f1c0";
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before {
  content: "\f017";
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before {
  content: "\f085";
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before {
  content: "\f0ce";
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before {
  content: "\f08d";
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before {
  content: "\f0c5";
}
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard-check:before {
  content: "\f46c";
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link:before {
  content: "\f08e";
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link {
  color: #888;
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link:hover {
  color: #aaaaaa;
}
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params {
  display: none;
  width: 70%;
  margin: 10px;
  border: 1px solid #ddd;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  border-collapse: collapse;
}
  div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td {
    border: 1px solid #ddd;
    text-align: center;
  }
  div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params .phpdebugbar-widgets-name {
    width: 20%;
    font-weight: bold;
  }

div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-error {
  display: block;
  font-weight: bold;
}

code.phpdebugbar-widgets-sql {
  white-space: pre-wrap;
  overflow-wrap: break-word;
  word-wrap: break-word;
}

div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate {
  background-color: #edeff0;
}

div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate:hover {
  background-color: #ffc;
}

div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar {
  display:none;
  position: fixed;
  bottom: 0;
  width: calc(100% - 30px);
  margin-bottom: 5px;
  z-index: 1;
}

div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter {
  float: right;
  font-size: 12px;
  padding: 2px 4px;
  background: #7cacd5;
  margin: 0 2px;
  border-radius: 4px;
  color: #fff;
  text-decoration: none;
}
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
  background: #eee;
  color: #888;
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-duplicates {
  font-weight: bold;
  text-decoration: underline;
}
div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item div.phpdebugbar-widgets-bg-measure {
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
}
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-bg-measure div.phpdebugbar-widgets-value {
  position: absolute;
  height: 100%;
  opacity: 0.2;
  background: red;
}
div.phpdebugbar-widgets-sqlqueries td.phpdebugbar-widgets-value li.phpdebugbar-widgets-table-list-item {
  text-align: left;
  padding-left: 6px;
}
div.phpdebugbar-widgets-sqlqueries .phpdebugbar-text-muted {
  color: #888;
}

div.phpdebugbar-header, a.phpdebugbar-restore-btn, div.phpdebugbar-openhandler .phpdebugbar-openhandler-header {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAATCAYAAACZZ43PAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIRSURBVHjapJQ9TFRBEMdn7zj5iF8JhpwhxkQxxILgRxAKEkNvuAY7C2oTGxpjtLA1hEISKOwMlHZqLLDRyoSKBo0Up4QQcgXBEAGB2/U3b+cd7+DOxs39d+ftm/nvf2bnnatclOYjJ+erHbKPtdPodfF7kBbXIv8aNwt7csuLTDU/wzFnEFiqBsYNMJ4L0gPkOBKCuvgQYQ632RtjuwAGmilomACB/c7JC8x2cBic+OSEUOdjKZyMHiJ4GqsTHIBtsCSmrjZCY4I7LhbsLPgD8uB33sl6rl7AURE9EV4tL9eYVXaHBRcspt17Kfoo+yHL3foauFotnoILeqLShSBvSGU0IXQyidsa66Dl/hy8SxSoNCpe4uWABSvZL4Jfcvy8PV8Fw3a7yvEMXI81OJRe5I9awWIyIqdRUIRgBnsC/LB6aEramWe4mfGEAKMXzssZAj3xHHsTkBSIWIDyAaHv7VpVwR5TX9pI3VY4PbkVfAar7JdIb8RKv8XymPVDxvdUqqBiVdfgMrfyBOe32IucVU7bGzWKWcxN892KNfCyzPozyTtWdhfSV0Tdx15JestFqfxWefxmfbKQKvhK4Gtrqm37HgLe1eP9DbQ+mvIXn5e5WieGyDZJ4D3WtrTPXaZ9Q0ylxLRBmo+C/Ue4yqWjnoZ1OFeVNsyP2X43gh44rrD1SWuGr3SVERpCkP8ZfwUYAL2WpEUbzbyiAAAAAElFTkSuQmCC") no-repeat scroll 5px 4px #efefef;}.phpdebugbar-widgets-value.phpdebugbar-widgets-warning { color: #f39c12; }</style>
<script type="text/javascript">
if (typeof(PhpDebugBar) == 'undefined') {
    // namespace
    var PhpDebugBar = {};
    PhpDebugBar.$ = jQuery;
}

(function($) {

    if (typeof(localStorage) == 'undefined') {
        // provide mock localStorage object for dumb browsers
        localStorage = {
            setItem: function(key, value) {},
            getItem: function(key) { return null; }
        };
    }

    if (typeof(PhpDebugBar.utils) == 'undefined') {
        PhpDebugBar.utils = {};
    }

    /**
     * Returns the value from an object property.
     * Using dots in the key, it is possible to retrieve nested property values
     *
     * @param {Object} dict
     * @param {String} key
     * @param {Object} default_value
     * @return {Object}
     */
    var getDictValue = PhpDebugBar.utils.getDictValue = function(dict, key, default_value) {
        var d = dict, parts = key.split('.');
        for (var i = 0; i < parts.length; i++) {
            if (!d[parts[i]]) {
                return default_value;
            }
            d = d[parts[i]];
        }
        return d;
    }

    /**
     * Counts the number of properties in an object
     *
     * @param {Object} obj
     * @return {Integer}
     */
    var getObjectSize = PhpDebugBar.utils.getObjectSize = function(obj) {
        if (Object.keys) {
            return Object.keys(obj).length;
        }
        var count = 0;
        for (var k in obj) {
            if (obj.hasOwnProperty(k)) {
                count++;
            }
        }
        return count;
    }

    /**
     * Returns a prefixed css class name
     *
     * @param {String} cls
     * @return {String}
     */
    PhpDebugBar.utils.csscls = function(cls, prefix) {
        if (cls.indexOf(' ') > -1) {
            var clss = cls.split(' '), out = [];
            for (var i = 0, c = clss.length; i < c; i++) {
                out.push(PhpDebugBar.utils.csscls(clss[i], prefix));
            }
            return out.join(' ');
        }
        if (cls.indexOf('.') === 0) {
            return '.' + prefix + cls.substr(1);
        }
        return prefix + cls;
    };

    /**
     * Creates a partial function of csscls where the second
     * argument is already defined
     *
     * @param  {string} prefix
     * @return {Function}
     */
    PhpDebugBar.utils.makecsscls = function(prefix) {
        var f = function(cls) {
            return PhpDebugBar.utils.csscls(cls, prefix);
        };
        return f;
    }

    var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-');


    // ------------------------------------------------------------------

    /**
     * Base class for all elements with a visual component
     *
     * @param {Object} options
     * @constructor
     */
    var Widget = PhpDebugBar.Widget = function(options) {
        this._attributes = $.extend({}, this.defaults);
        this._boundAttributes = {};
        this.$el = $('<' + this.tagName + ' />');
        if (this.className) {
            this.$el.addClass(this.className);
        }
        this.initialize.apply(this, [options || {}]);
        this.render.apply(this);
    };

    $.extend(Widget.prototype, {

        tagName: 'div',

        className: null,

        defaults: {},

        /**
         * Called after the constructor
         *
         * @param {Object} options
         */
        initialize: function(options) {
            this.set(options);
        },

        /**
         * Called after the constructor to render the element
         */
        render: function() {},

        /**
         * Sets the value of an attribute
         *
         * @param {String} attr Can also be an object to set multiple attributes at once
         * @param {Object} value
         */
        set: function(attr, value) {
            if (typeof(attr) != 'string') {
                for (var k in attr) {
                    this.set(k, attr[k]);
                }
                return;
            }

            this._attributes[attr] = value;
            if (typeof(this._boundAttributes[attr]) !== 'undefined') {
                for (var i = 0, c = this._boundAttributes[attr].length; i < c; i++) {
                    this._boundAttributes[attr][i].apply(this, [value]);
                }
            }
        },

        /**
         * Checks if an attribute exists and is not null
         *
         * @param {String} attr
         * @return {[type]} [description]
         */
        has: function(attr) {
            return typeof(this._attributes[attr]) !== 'undefined' && this._attributes[attr] !== null;
        },

        /**
         * Returns the value of an attribute
         *
         * @param {String} attr
         * @return {Object}
         */
        get: function(attr) {
            return this._attributes[attr];
        },

        /**
         * Registers a callback function that will be called whenever the value of the attribute changes
         *
         * If cb is a jQuery element, text() will be used to fill the element
         *
         * @param {String} attr
         * @param {Function} cb
         */
        bindAttr: function(attr, cb) {
            if (Array.isArray(attr)) {
                for (var i = 0, c = attr.length; i < c; i++) {
                    this.bindAttr(attr[i], cb);
                }
                return;
            }

            if (typeof(this._boundAttributes[attr]) == 'undefined') {
                this._boundAttributes[attr] = [];
            }
            if (typeof(cb) == 'object') {
                var el = cb;
                cb = function(value) { el.text(value || ''); };
            }
            this._boundAttributes[attr].push(cb);
            if (this.has(attr)) {
                cb.apply(this, [this._attributes[attr]]);
            }
        }

    });


    /**
     * Creates a subclass
     *
     * Code from Backbone.js
     *
     * @param {Array} props Prototype properties
     * @return {Function}
     */
    Widget.extend = function(props) {
        var parent = this;

        var child = function() { return parent.apply(this, arguments); };
        $.extend(child, parent);

        var Surrogate = function() { this.constructor = child; };
        Surrogate.prototype = parent.prototype;
        child.prototype = new Surrogate;
        $.extend(child.prototype, props);

        child.__super__ = parent.prototype;

        return child;
    };

    // ------------------------------------------------------------------

    /**
     * Tab
     *
     * A tab is composed of a tab label which is always visible and
     * a tab panel which is visible only when the tab is active.
     *
     * The panel must contain a widget. A widget is an object which has
     * an element property containing something appendable to a jQuery object.
     *
     * Options:
     *  - title
     *  - badge
     *  - widget
     *  - data: forward data to widget data
     */
    var Tab = Widget.extend({

        className: csscls('panel'),

        render: function() {
            this.$tab = $('<a />').addClass(csscls('tab'));
            this.$icon = $('<i />').appendTo(this.$tab);
            this.bindAttr('icon', function(icon) {
                if (icon) {
                    this.$icon.attr('class', 'fa fa-' + icon);
                } else {
                    this.$icon.attr('class', '');
                }
            });

            this.bindAttr('title', $('<span />').addClass(csscls('text')).appendTo(this.$tab));

            this.$badge = $('<span />').addClass(csscls('badge')).appendTo(this.$tab);
            this.bindAttr('badge', function(value) {
                if (value !== null) {
                    this.$badge.text(value);
                    this.$badge.addClass(csscls('visible'));
                } else {
                    this.$badge.removeClass(csscls('visible'));
                }
            });

            this.bindAttr('widget', function(widget) {
                this.$el.empty().append(widget.$el);
            });

            this.bindAttr('data', function(data) {
                if (this.has('widget')) {
                    this.get('widget').set('data', data);
                    if (!$.isEmptyObject(data)) {
                        this.$tab.show();
                    }
                }
            })
        }

    });

    // ------------------------------------------------------------------

    /**
     * Indicator
     *
     * An indicator is a text and an icon to display single value information
     * right inside the always visible part of the debug bar
     *
     * Options:
     *  - icon
     *  - title
     *  - tooltip
     *  - data: alias of title
     */
    var Indicator = Widget.extend({

        tagName: 'span',

        className: csscls('indicator'),

        render: function() {
            this.$icon = $('<i />').appendTo(this.$el);
            this.bindAttr('icon', function(icon) {
                if (icon) {
                    this.$icon.attr('class', 'fa fa-' + icon);
                } else {
                    this.$icon.attr('class', '');
                }
            });

            this.bindAttr(['title', 'data'], $('<span />').addClass(csscls('text')).appendTo(this.$el));

            this.$tooltip = $('<span />').addClass(csscls('tooltip disabled')).appendTo(this.$el);
            this.bindAttr('tooltip', function(tooltip) {
                if (tooltip) {
                    this.$tooltip.text(tooltip).removeClass(csscls('disabled'));
                } else {
                    this.$tooltip.addClass(csscls('disabled'));
                }
            });
        }

    });

    // ------------------------------------------------------------------

    /**
     * Dataset title formater
     *
     * Formats the title of a dataset for the select box
     */
    var DatasetTitleFormater = PhpDebugBar.DatasetTitleFormater = function(debugbar) {
        this.debugbar = debugbar;
    };

    $.extend(DatasetTitleFormater.prototype, {

        /**
         * Formats the title of a dataset
         *
         * @this {DatasetTitleFormater}
         * @param {String} id
         * @param {Object} data
         * @param {String} suffix
         * @return {String}
         */
        format: function(id, data, suffix, nb) {
            if (suffix) {
                suffix = ' ' + suffix;
            } else {
                suffix = '';
            }

            var nb = nb || getObjectSize(this.debugbar.datasets) ;

            if (typeof(data['__meta']) === 'undefined') {
                return "#" + nb + suffix;
            }

            var uri = data['__meta']['uri'].split('/'), filename = uri.pop();

            // URI ends in a trailing /, avoid returning an empty string
            if (!filename) {
                filename = (uri.pop() || '') + '/'; // add the trailing '/' back
            }

            // filename is a number, path could be like /action/{id}
            if (uri.length && !isNaN(filename)) {
                filename = uri.pop() + '/' + filename;
            }

            // truncate the filename in the label, if it's too long
            var maxLength = 150;
            if (filename.length > maxLength) {
                filename = filename.substr(0, maxLength) + '...';
            }

            var label = "#" + nb + " " + filename + suffix + ' (' + data['__meta']['datetime'].split(' ')[1] + ')';
            return label;
        }

    });

    // ------------------------------------------------------------------


    /**
     * DebugBar
     *
     * Creates a bar that appends itself to the body of your page
     * and sticks to the bottom.
     *
     * The bar can be customized by adding tabs and indicators.
     * A data map is used to fill those controls with data provided
     * from datasets.
     */
    var DebugBar = PhpDebugBar.DebugBar = Widget.extend({

        className: "phpdebugbar " + csscls('minimized'),

        options: {
            bodyMarginBottom: true,
            bodyMarginBottomHeight: 0
        },

        initialize: function() {
            this.controls = {};
            this.dataMap = {};
            this.datasets = {};
            this.firstTabName = null;
            this.activePanelName = null;
            this.activeDatasetId = null;
            this.hideEmptyTabs = false;
            this.datesetTitleFormater = new DatasetTitleFormater(this);
            this.options.bodyMarginBottomHeight = parseInt($('body').css('margin-bottom'));
            try {
                this.isIframe = window.self !== window.top && window.top.phpdebugbar;
            } catch (error) {
                this.isIframe = false;
            }
            this.registerResizeHandler();
        },

        /**
         * Register resize event, for resize debugbar with reponsive css.
         *
         * @this {DebugBar}
         */
        registerResizeHandler: function() {
            if (typeof this.resize.bind == 'undefined' || this.isIframe) return;

            var f = this.resize.bind(this);
            this.respCSSSize = 0;
            $(window).resize(f);
            setTimeout(f, 20);
        },

        /**
         * Resizes the debugbar to fit the current browser window
         */
        resize: function() {
            var contentSize = this.respCSSSize;
            if (this.respCSSSize == 0) {
                this.$header.find("> *:visible").each(function () {
                    contentSize += $(this).outerWidth(true);
                });
            }

            var currentSize = this.$header.width();
            var cssClass = csscls("mini-design");
            var bool = this.$header.hasClass(cssClass);

            if (currentSize <= contentSize && !bool) {
                this.respCSSSize = contentSize;
                this.$header.addClass(cssClass);
            } else if (contentSize < currentSize && bool) {
                this.respCSSSize = 0;
                this.$header.removeClass(cssClass);
            }

            // Reset height to ensure bar is still visible
            this.setHeight(this.$body.height());
        },

        /**
         * Initialiazes the UI
         *
         * @this {DebugBar}
         */
        render: function() {
            if (this.isIframe) {
                this.$el.hide();
            }

            var self = this;
            this.$el.appendTo('body');
            this.$dragCapture = $('<div />').addClass(csscls('drag-capture')).appendTo(this.$el);
            this.$resizehdle = $('<div />').addClass(csscls('resize-handle')).appendTo(this.$el);
            this.$header = $('<div />').addClass(csscls('header')).appendTo(this.$el);
            this.$headerBtn = $('<a />').addClass(csscls('restore-btn')).appendTo(this.$header);
            this.$headerBtn.click(function() {
                self.close();
            });
            this.$headerLeft = $('<div />').addClass(csscls('header-left')).appendTo(this.$header);
            this.$headerRight = $('<div />').addClass(csscls('header-right')).appendTo(this.$header);
            var $body = this.$body = $('<div />').addClass(csscls('body')).appendTo(this.$el);
            this.recomputeBottomOffset();

            // dragging of resize handle
            var pos_y, orig_h;
            this.$resizehdle.on('mousedown', function(e) {
                orig_h = $body.height(), pos_y = e.pageY;
                $body.parents().on('mousemove', mousemove).on('mouseup', mouseup);
                self.$dragCapture.show();
                e.preventDefault();
            });
            var mousemove = function(e) {
                var h = orig_h + (pos_y - e.pageY);
                self.setHeight(h);
            };
            var mouseup = function() {
                $body.parents().off('mousemove', mousemove).off('mouseup', mouseup);
                self.$dragCapture.hide();
            };

            // close button
            this.$closebtn = $('<a />').addClass(csscls('close-btn')).appendTo(this.$headerRight);
            this.$closebtn.click(function() {
                self.close();
            });

            // minimize button
            this.$minimizebtn = $('<a />').addClass(csscls('minimize-btn') ).appendTo(this.$headerRight);
            this.$minimizebtn.click(function() {
                self.minimize();
            });

            // maximize button
            this.$maximizebtn = $('<a />').addClass(csscls('maximize-btn') ).appendTo(this.$headerRight);
            this.$maximizebtn.click(function() {
                self.restore();
            });

            // restore button
            this.$restorebtn = $('<a />').addClass(csscls('restore-btn')).hide().appendTo(this.$el);
            this.$restorebtn.click(function() {
                self.restore();
            });

            // open button
            this.$openbtn = $('<a />').addClass(csscls('open-btn')).appendTo(this.$headerRight).hide();
            this.$openbtn.click(function() {
                self.openHandler.show(function(id, dataset) {
                    self.addDataSet(dataset, id, "(opened)");
                    self.showTab();
                });
            });

            // select box for data sets
            this.$datasets = $('<select />').addClass(csscls('datasets-switcher')).attr('name', 'datasets-switcher')
                .appendTo(this.$headerRight);
            this.$datasets.change(function() {
                self.showDataSet(this.value);
            });
        },

        /**
         * Sets the height of the debugbar body section
         * Forces the height to lie within a reasonable range
         * Stores the height in local storage so it can be restored
         * Resets the document body bottom offset
         *
         * @this {DebugBar}
         */
        setHeight: function(height) {
          var min_h = 40;
          var max_h = $(window).innerHeight() - this.$header.height() - 10;
          height = Math.min(height, max_h);
          height = Math.max(height, min_h);
          this.$body.css('height', height);
          localStorage.setItem('phpdebugbar-height', height);
          this.recomputeBottomOffset();
        },

        /**
         * Restores the state of the DebugBar using localStorage
         * This is not called by default in the constructor and
         * needs to be called by subclasses in their init() method
         *
         * @this {DebugBar}
         */
        restoreState: function() {
            if (this.isIframe) return;
            // bar height
            var height = localStorage.getItem('phpdebugbar-height');
            this.setHeight(height || this.$body.height());

            // bar visibility
            var open = localStorage.getItem('phpdebugbar-open');
            if (open && open == '0') {
                this.close();
            } else {
                var visible = localStorage.getItem('phpdebugbar-visible');
                if (visible && visible == '1') {
                    var tab = localStorage.getItem('phpdebugbar-tab');
                    if (this.isTab(tab)) {
                        this.showTab(tab);
                    } else {
                        this.showTab();
                    }
                }
            }
        },

        /**
         * Creates and adds a new tab
         *
         * @this {DebugBar}
         * @param {String} name Internal name
         * @param {Object} widget A widget object with an element property
         * @param {String} title The text in the tab, if not specified, name will be used
         * @return {Tab}
         */
        createTab: function(name, widget, title) {
            var tab = new Tab({
                title: title || (name.replace(/[_\-]/g, ' ').charAt(0).toUpperCase() + name.slice(1)),
                widget: widget
            });
            return this.addTab(name, tab);
        },

        /**
         * Adds a new tab
         *
         * @this {DebugBar}
         * @param {String} name Internal name
         * @param {Tab} tab Tab object
         * @return {Tab}
         */
        addTab: function(name, tab) {
            if (this.isControl(name)) {
                throw new Error(name + ' already exists');
            }

            var self = this;
            tab.$tab.appendTo(this.$headerLeft).click(function() {
                if (!self.isMinimized() && self.activePanelName == name) {
                    self.minimize();
                } else {
                    self.showTab(name);
                }
            })
            if (this.hideEmptyTabs) {
                tab.$tab.hide();
            }
            tab.$tab.attr('data-collector', name);
            tab.$el.attr('data-collector', name);
            tab.$el.appendTo(this.$body);

            this.controls[name] = tab;
            if (this.firstTabName == null) {
                this.firstTabName = name;
            }
            return tab;
        },

        /**
         * Creates and adds an indicator
         *
         * @this {DebugBar}
         * @param {String} name Internal name
         * @param {String} icon
         * @param {String} tooltip
         * @param {String} position "right" or "left", default is "right"
         * @return {Indicator}
         */
        createIndicator: function(name, icon, tooltip, position) {
            var indicator = new Indicator({
                icon: icon,
                tooltip: tooltip
            });
            return this.addIndicator(name, indicator, position);
        },

        /**
         * Adds an indicator
         *
         * @this {DebugBar}
         * @param {String} name Internal name
         * @param {Indicator} indicator Indicator object
         * @return {Indicator}
         */
        addIndicator: function(name, indicator, position) {
            if (this.isControl(name)) {
                throw new Error(name + ' already exists');
            }

            if (position == 'left') {
                indicator.$el.insertBefore(this.$headerLeft.children().first());
            } else {
                indicator.$el.appendTo(this.$headerRight);
            }

            this.controls[name] = indicator;
            return indicator;
        },

        /**
         * Returns a control
         *
         * @param {String} name
         * @return {Object}
         */
        getControl: function(name) {
            if (this.isControl(name)) {
                return this.controls[name];
            }
        },

        /**
         * Checks if there's a control under the specified name
         *
         * @this {DebugBar}
         * @param {String} name
         * @return {Boolean}
         */
        isControl: function(name) {
            return typeof(this.controls[name]) != 'undefined';
        },

        /**
         * Checks if a tab with the specified name exists
         *
         * @this {DebugBar}
         * @param {String} name
         * @return {Boolean}
         */
        isTab: function(name) {
            return this.isControl(name) && this.controls[name] instanceof Tab;
        },

        /**
         * Checks if an indicator with the specified name exists
         *
         * @this {DebugBar}
         * @param {String} name
         * @return {Boolean}
         */
        isIndicator: function(name) {
            return this.isControl(name) && this.controls[name] instanceof Indicator;
        },

        /**
         * Removes all tabs and indicators from the debug bar and hides it
         *
         * @this {DebugBar}
         */
        reset: function() {
            this.minimize();
            var self = this;
            $.each(this.controls, function(name, control) {
                if (self.isTab(name)) {
                    control.$tab.remove();
                }
                control.$el.remove();
            });
            this.controls = {};
        },

        /**
         * Open the debug bar and display the specified tab
         *
         * @this {DebugBar}
         * @param {String} name If not specified, display the first tab
         */
        showTab: function(name) {
            if (!name) {
                if (this.activePanelName) {
                    name = this.activePanelName;
                } else {
                    name = this.firstTabName;
                }
            }

            if (!this.isTab(name)) {
                throw new Error("Unknown tab '" + name + "'");
            }

            this.$resizehdle.show();
            this.$body.show();
            this.recomputeBottomOffset();

            $(this.$header).find('> div > .' + csscls('active')).removeClass(csscls('active'));
            $(this.$body).find('> .' + csscls('active')).removeClass(csscls('active'));

            this.controls[name].$tab.addClass(csscls('active'));
            this.controls[name].$el.addClass(csscls('active'));
            this.activePanelName = name;

            this.$el.removeClass(csscls('minimized'));
            localStorage.setItem('phpdebugbar-visible', '1');
            localStorage.setItem('phpdebugbar-tab', name);

            this.resize();
        },

        /**
         * Hide panels and minimize the debug bar
         *
         * @this {DebugBar}
         */
        minimize: function() {
            this.$header.find('> div > .' + csscls('active')).removeClass(csscls('active'));
            this.$body.hide();
            this.$resizehdle.hide();
            this.recomputeBottomOffset();
            localStorage.setItem('phpdebugbar-visible', '0');
            this.$el.addClass(csscls('minimized'));
            this.resize();
        },

        /**
         * Checks if the panel is minimized
         *
         * @return {Boolean}
         */
        isMinimized: function() {
            return this.$el.hasClass(csscls('minimized'));
        },

        /**
         * Close the debug bar
         *
         * @this {DebugBar}
         */
        close: function() {
            this.$resizehdle.hide();
            this.$header.hide();
            this.$body.hide();
            this.$restorebtn.show();
            localStorage.setItem('phpdebugbar-open', '0');
            this.$el.addClass(csscls('closed'));
            this.recomputeBottomOffset();
        },

        /**
         * Checks if the panel is closed
         *
         * @return {Boolean}
         */
        isClosed: function() {
            return this.$el.hasClass(csscls('closed'));
        },

        /**
         * Restore the debug bar
         *
         * @this {DebugBar}
         */
        restore: function() {
            this.$resizehdle.show();
            this.$header.show();
            this.$restorebtn.hide();
            localStorage.setItem('phpdebugbar-open', '1');
            var tab = localStorage.getItem('phpdebugbar-tab');
            if (this.isTab(tab)) {
                this.showTab(tab);
            } else {
                this.showTab();
            }
            this.$el.removeClass(csscls('closed'));
            this.resize();
        },

        /**
         * Recomputes the margin-bottom css property of the body so
         * that the debug bar never hides any content
         */
        recomputeBottomOffset: function() {
            if (this.options.bodyMarginBottom) {
                if (this.isClosed()) {
                    return $('body').css('margin-bottom', this.options.bodyMarginBottomHeight || '');
                }

                var offset = parseInt(this.$el.height()) + (this.options.bodyMarginBottomHeight || 0);
                $('body').css('margin-bottom', offset);
            }
        },

        /**
         * Sets the data map used by dataChangeHandler to populate
         * indicators and widgets
         *
         * A data map is an object where properties are control names.
         * The value of each property should be an array where the first
         * item is the name of a property from the data object (nested properties
         * can be specified) and the second item the default value.
         *
         * Example:
         *     {"memory": ["memory.peak_usage_str", "0B"]}
         *
         * @this {DebugBar}
         * @param {Object} map
         */
        setDataMap: function(map) {
            this.dataMap = map;
        },

        /**
         * Same as setDataMap() but appends to the existing map
         * rather than replacing it
         *
         * @this {DebugBar}
         * @param {Object} map
         */
        addDataMap: function(map) {
            $.extend(this.dataMap, map);
        },

        /**
         * Resets datasets and add one set of data
         *
         * For this method to be usefull, you need to specify
         * a dataMap using setDataMap()
         *
         * @this {DebugBar}
         * @param {Object} data
         * @return {String} Dataset's id
         */
        setData: function(data) {
            this.datasets = {};
            return this.addDataSet(data);
        },

        /**
         * Adds a dataset
         *
         * If more than one dataset are added, the dataset selector
         * will be displayed.
         *
         * For this method to be usefull, you need to specify
         * a dataMap using setDataMap()
         *
         * @this {DebugBar}
         * @param {Object} data
         * @param {String} id The name of this set, optional
         * @param {String} suffix
         * @param {Bool} show Whether to show the new dataset, optional (default: true)
         * @return {String} Dataset's id
         */
        addDataSet: function(data, id, suffix, show) {
            if (!data || !data.__meta) return;
            if (this.isIframe) {
                window.top.phpdebugbar.addDataSet(data, id, '(iframe)' + (suffix || ''), show);
                return;
            }

            var nb = getObjectSize(this.datasets) + 1;
            id = id || nb;
            data.__meta['nb'] = nb;
            data.__meta['suffix'] = suffix;
            this.datasets[id] = data;

            var label = this.datesetTitleFormater.format(id, this.datasets[id], suffix, nb);

            if (this.datasetTab) {
                this.datasetTab.set('data', this.datasets);
                var datasetSize = getObjectSize(this.datasets);
                this.datasetTab.set('badge', datasetSize > 1 ? datasetSize : null);
                this.datasetTab.$tab.show();
            }

            this.$datasets.append($('<option value="' + id + '">' + label + '</option>'));
            if (this.$datasets.children().length > 1) {
                this.$datasets.show();
            }

            if (typeof(show) == 'undefined' || show) {
                this.showDataSet(id);
            }

            this.resize();

            return id;
        },

        /**
         * Loads a dataset using the open handler
         *
         * @param {String} id
         * @param {Bool} show Whether to show the new dataset, optional (default: true)
         */
        loadDataSet: function(id, suffix, callback, show) {
            if (!this.openHandler) {
                throw new Error('loadDataSet() needs an open handler');
            }
            var self = this;
            this.openHandler.load(id, function(data) {
                self.addDataSet(data, id, suffix, show);
                self.resize();
                callback && callback(data);
            });
        },

        /**
         * Returns the data from a dataset
         *
         * @this {DebugBar}
         * @param {String} id
         * @return {Object}
         */
        getDataSet: function(id) {
            return this.datasets[id];
        },

        /**
         * Switch the currently displayed dataset
         *
         * @this {DebugBar}
         * @param {String} id
         */
        showDataSet: function(id) {
            this.activeDatasetId = id;
            this.dataChangeHandler(this.datasets[id]);

            if (this.$datasets.val() !== id) {
                this.$datasets.val(id);
            }

            if (this.datasetTab) {
                this.datasetTab.get('widget').set('id', id);
            }
        },

        /**
         * Called when the current dataset is modified.
         *
         * @this {DebugBar}
         * @param {Object} data
         */
        dataChangeHandler: function(data) {
            var self = this;
            $.each(this.dataMap, function(key, def) {
                var d = getDictValue(data, def[0], def[1]);
                if (key.indexOf(':') != -1) {
                    key = key.split(':');
                    self.getControl(key[0]).set(key[1], d);
                } else {
                    self.getControl(key).set('data', d);
                }
            });
            self.resize();
        },

        /**
         * Sets the handler to open past dataset
         *
         * @this {DebugBar}
         * @param {object} handler
         */
        setOpenHandler: function(handler) {
            this.openHandler = handler;
            if (handler !== null) {
                this.$openbtn.show();
            } else {
                this.$openbtn.hide();
            }
        },

        setHideEmptyTabs: function(hideEmpty) {
            this.hideEmptyTabs = hideEmpty;
        },

        /**
         * Returns the handler to open past dataset
         *
         * @this {DebugBar}
         * @return {object}
         */
        getOpenHandler: function() {
            return this.openHandler;
        },

        enableAjaxHandlerTab: function() {
            this.datasetTab = new PhpDebugBar.DebugBar.Tab({"icon":"history", "title":"Request history", "widget": new PhpDebugBar.Widgets.DatasetWidget({
                    'debugbar': this
                })});
            this.datasetTab.$tab.addClass(csscls('tab-history'));
            this.datasetTab.$tab.attr('data-collector', '__datasets');
            this.datasetTab.$el.attr('data-collector', '__datasets');
            this.datasetTab.$tab.insertAfter(this.$openbtn).hide();
            this.datasetTab.$tab.click(() => {
                if (!this.isMinimized() && self.activePanelName == '__datasets') {
                    this.minimize();
                } else {
                    this.showTab('__datasets');
                }
            });
            this.datasetTab.$el.appendTo(this.$body);
            this.controls['__datasets'] = this.datasetTab;
        },

    });

    DebugBar.Tab = Tab;
    DebugBar.Indicator = Indicator;

    // ------------------------------------------------------------------

    /**
     * AjaxHandler
     *
     * Extract data from headers of an XMLHttpRequest and adds a new dataset
     *
     * @param {Bool} autoShow Whether to immediately show new datasets, optional (default: true)
     */
    var AjaxHandler = PhpDebugBar.AjaxHandler = function(debugbar, headerName, autoShow) {
        this.debugbar = debugbar;
        this.headerName = headerName || 'phpdebugbar';
        this.autoShow = typeof(autoShow) == 'undefined' ? true : autoShow;
        if (localStorage.getItem('phpdebugbar-ajaxhandler-autoshow') !== null) {
            this.autoShow = localStorage.getItem('phpdebugbar-ajaxhandler-autoshow') == '1';
        }
    };

    $.extend(AjaxHandler.prototype, {

        /**
         * Handles a Fetch API Response or an XMLHttpRequest
         *
         * @this {AjaxHandler}
         * @param {Response|XMLHttpRequest} response
         * @return {Bool}
         */
        handle: function(response) {
            // Check if the debugbar header is available
            if (this.isFetch(response) && !response.headers.has(this.headerName + '-id')) {
                return true;
            } else if (this.isXHR(response) && response.getAllResponseHeaders().indexOf(this.headerName) === -1) {
                return true;
            }
            if (!this.loadFromId(response)) {
                return this.loadFromData(response);
            }
            return true;
        },

        getHeader: function(response, header) {
            if (this.isFetch(response)) {
                return response.headers.get(header)
            }

            return response.getResponseHeader(header)
        },

        isFetch: function(response) {
            return Object.prototype.toString.call(response) == '[object Response]'
        },

        isXHR: function(response) {
            return Object.prototype.toString.call(response) == '[object XMLHttpRequest]'
        },

        setAutoShow: function(autoshow) {
            this.autoShow = autoshow;
            localStorage.setItem('phpdebugbar-ajaxhandler-autoshow', autoshow ? '1' : '0');
        },

        /**
         * Checks if the HEADER-id exists and loads the dataset using the open handler
         *
         * @param {Response|XMLHttpRequest} response
         * @return {Bool}
         */
        loadFromId: function(response) {
            var id = this.extractIdFromHeaders(response);
            if (id && this.debugbar.openHandler) {
                this.debugbar.loadDataSet(id, "(ajax)", undefined, this.autoShow);
                return true;
            }
            return false;
        },

        /**
         * Extracts the id from the HEADER-id
         *
         * @param {Response|XMLHttpRequest} response
         * @return {String}
         */
        extractIdFromHeaders: function(response) {
            return this.getHeader(response, this.headerName + '-id');
        },

        /**
         * Checks if the HEADER exists and loads the dataset
         *
         * @param {Response|XMLHttpRequest} response
         * @return {Bool}
         */
        loadFromData: function(response) {
            var raw = this.extractDataFromHeaders(response);
            if (!raw) {
                return false;
            }

            var data = this.parseHeaders(raw);
            if (data.error) {
                throw new Error('Error loading debugbar data: ' + data.error);
            } else if(data.data) {
                this.debugbar.addDataSet(data.data, data.id, "(ajax)", this.autoShow);
            }
            return true;
        },

        /**
         * Extract the data as a string from headers of an XMLHttpRequest
         *
         * @this {AjaxHandler}
         * @param {Response|XMLHttpRequest} response
         * @return {string}
         */
        extractDataFromHeaders: function(response) {
            var data = this.getHeader(response, this.headerName);
            if (!data) {
                return;
            }
            for (var i = 1;; i++) {
                var header = this.getHeader(response, this.headerName + '-' + i);
                if (!header) {
                    break;
                }
                data += header;
            }
            return decodeURIComponent(data);
        },

        /**
         * Parses the string data into an object
         *
         * @this {AjaxHandler}
         * @param {string} data
         * @return {string}
         */
        parseHeaders: function(data) {
            return JSON.parse(data);
        },

        /**
         * Attaches an event listener to fetch
         *
         * @this {AjaxHandler}
         */
        bindToFetch: function() {
            var self = this;
            var proxied = window.fetch;

            if (proxied !== undefined && proxied.polyfill !== undefined) {
                return;
            }

            window.fetch = function () {
                var promise = proxied.apply(this, arguments);

                promise.then(function (response) {
                    self.handle(response);
                }).catch(function(reason) {
                    // Fetch request failed or aborted via AbortController.abort().
                    // Catch is required to not trigger React's error handler.
                });

                return promise;
            };
        },

        /**
         * @deprecated use bindToXHR instead
         */
        bindToJquery: function(jq) {
            var self = this;
            jq(document).ajaxComplete(function(e, xhr, settings) {
                if (!settings.ignoreDebugBarAjaxHandler) {
                    self.handle(xhr);
                }
            });
        },

        /**
         * Attaches an event listener to XMLHttpRequest
         *
         * @this {AjaxHandler}
         */
        bindToXHR: function() {
            var self = this;
            var proxied = XMLHttpRequest.prototype.open;
            XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
                var xhr = this;
                this.addEventListener("readystatechange", function() {
                    var skipUrl = self.debugbar.openHandler ? self.debugbar.openHandler.get('url') : null;
                    var href = (typeof url === 'string') ? url : url.href;

                    if (xhr.readyState == 4 && href.indexOf(skipUrl) !== 0) {
                        self.handle(xhr);
                    }
                }, false);
                proxied.apply(this, Array.prototype.slice.call(arguments));
            };
        }

    });

})(PhpDebugBar.$);

if (typeof(PhpDebugBar) == 'undefined') {
    // namespace
    var PhpDebugBar = {};
    PhpDebugBar.$ = jQuery;
}

(function($) {

    /**
     * @namespace
     */
    PhpDebugBar.Widgets = {};

    var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');

    /**
     * Replaces spaces with &nbsp; and line breaks with <br>
     *
     * @param {String} text
     * @return {String}
     */
    var htmlize = PhpDebugBar.Widgets.htmlize = function(text) {
        return text.replace(/\n/g, '<br>').replace(/\s/g, "&nbsp;")
    };

    /**
     * Returns a string representation of value, using JSON.stringify
     * if it's an object.
     *
     * @param {Object} value
     * @param {Boolean} prettify Uses htmlize() if true
     * @return {String}
     */
    var renderValue = PhpDebugBar.Widgets.renderValue = function(value, prettify) {
        if (typeof(value) !== 'string') {
            if (prettify) {
                return htmlize(JSON.stringify(value, undefined, 2));
            }
            return JSON.stringify(value);
        }
        return value;
    };

    /**
     * Highlights a block of code
     *
     * @param  {String} code
     * @param  {String} lang
     * @return {String}
     */
    var highlight = PhpDebugBar.Widgets.highlight = function(code, lang) {
        if (typeof(code) === 'string') {
            if (typeof(hljs) === 'undefined') {
                return htmlize(code);
            }
            if (lang && hljs.getLanguage(lang)) {
                return hljs.highlight(code, {language: lang}).value;
            }
            return hljs.highlightAuto(code).value;
        }

        if (typeof(hljs) === 'object') {
            code.each(function(i, e) { hljs.highlightElement(e); });
        }
        return code;
    };

    /**
     * Creates a <pre> element with a block of code
     *
     * @param  {String} code
     * @param  {String} lang
     * @param  {Number} [firstLineNumber] If provided, shows line numbers beginning with the given value.
     * @param  {Number} [highlightedLine] If provided, the given line number will be highlighted.
     * @return {String}
     */
    var createCodeBlock = PhpDebugBar.Widgets.createCodeBlock = function(code, lang, firstLineNumber, highlightedLine) {
        var pre = $('<pre />').addClass(csscls('code-block'));
        // Add a newline to prevent <code> element from vertically collapsing too far if the last
        // code line was empty: that creates problems with the horizontal scrollbar being
        // incorrectly positioned - most noticeable when line numbers are shown.
        var codeElement = $('<code />').text(code + '\n').appendTo(pre);

        // Format the code
        if (lang) {
            codeElement.addClass("language-" + lang);
        }
        highlight(codeElement).removeClass('hljs');

        // Show line numbers in a list
        if (!isNaN(parseFloat(firstLineNumber))) {
            var lineCount = code.split('\n').length;
            var $lineNumbers = $('<ul />').prependTo(pre);
            pre.children().addClass(csscls('numbered-code'));
            for (var i = firstLineNumber; i < firstLineNumber + lineCount; i++) {
                var li = $('<li />').text(i).appendTo($lineNumbers);

                // Add a span with a special class if we are supposed to highlight a line.
                if (highlightedLine === i) {
                    li.addClass(csscls('highlighted-line')).append('<span>&nbsp;</span>');
                }
            }
        }

        return pre;
    };

    var getDictValue = PhpDebugBar.utils.getDictValue = function(dict, key, default_value) {
        var d = dict, parts = key.split('.');
        for (var i = 0; i < parts.length; i++) {
            if (!d[parts[i]]) {
                return default_value;
            }
            d = d[parts[i]];
        }
        return d;
    }

    // ------------------------------------------------------------------
    // Generic widgets
    // ------------------------------------------------------------------

    /**
     * Displays array element in a <ul> list
     *
     * Options:
     *  - data
     *  - itemRenderer: a function used to render list items (optional)
     */
    var ListWidget = PhpDebugBar.Widgets.ListWidget = PhpDebugBar.Widget.extend({

        tagName: 'ul',

        className: csscls('list'),

        initialize: function(options) {
            if (!options['itemRenderer']) {
                options['itemRenderer'] = this.itemRenderer;
            }
            this.set(options);
        },

        render: function() {
            this.bindAttr(['itemRenderer', 'data'], function() {
                this.$el.empty();
                if (!this.has('data')) {
                    return;
                }

                var data = this.get('data');
                for (var i = 0; i < data.length; i++) {
                    var li = $('<li />').addClass(csscls('list-item')).appendTo(this.$el);
                    this.get('itemRenderer')(li, data[i]);
                }
            });
        },

        /**
         * Renders the content of a <li> element
         *
         * @param {jQuery} li The <li> element as a jQuery Object
         * @param {Object} value An item from the data array
         */
        itemRenderer: function(li, value) {
            li.html(renderValue(value));
        }

    });

    // ------------------------------------------------------------------

    /**
     * Displays object property/value paris in a <dl> list
     *
     * Options:
     *  - data
     *  - itemRenderer: a function used to render list items (optional)
     */
    var KVListWidget = PhpDebugBar.Widgets.KVListWidget = ListWidget.extend({

        tagName: 'dl',

        className: csscls('kvlist'),

        render: function() {
            this.bindAttr(['itemRenderer', 'data'], function() {
                this.$el.empty();
                if (!this.has('data')) {
                    return;
                }

                var self = this;
                $.each(this.get('data'), function(key, value) {
                    var dt = $('<dt />').addClass(csscls('key')).appendTo(self.$el);
                    var dd = $('<dd />').addClass(csscls('value')).appendTo(self.$el);
                    self.get('itemRenderer')(dt, dd, key, value);
                });
            });
        },

        /**
         * Renders the content of the <dt> and <dd> elements
         *
         * @param {jQuery} dt The <dt> element as a jQuery Object
         * @param {jQuery} dd The <dd> element as a jQuery Object
         * @param {String} key Property name
         * @param {Object} value Property value
         */
        itemRenderer: function(dt, dd, key, value) {
            dt.text(key);
            dd.html(htmlize(value));
        }

    });

    // ------------------------------------------------------------------

    /**
     * An extension of KVListWidget where the data represents a list
     * of variables
     *
     * Options:
     *  - data
     */
    var VariableListWidget = PhpDebugBar.Widgets.VariableListWidget = KVListWidget.extend({

        className: csscls('kvlist varlist'),

        itemRenderer: function(dt, dd, key, value) {
            $('<span />').attr('title', key).text(key).appendTo(dt);

            var v = value && value.value || value;
            if (v && v.length > 100) {
                v = v.substr(0, 100) + "...";
            }
            var prettyVal = null;
            dd.text(v).click(function() {
                if (dd.hasClass(csscls('pretty'))) {
                    dd.text(v).removeClass(csscls('pretty'));
                } else {
                    prettyVal = prettyVal || createCodeBlock(value);
                    dd.addClass(csscls('pretty')).empty().append(prettyVal);
                }
            });
        }

    });

    // ------------------------------------------------------------------

    /**
     * An extension of KVListWidget where the data represents a list
     * of variables whose contents are HTML; this is useful for showing
     * variable output from VarDumper's HtmlDumper.
     *
     * Options:
     *  - data
     */
    var HtmlVariableListWidget = PhpDebugBar.Widgets.HtmlVariableListWidget = KVListWidget.extend({

        className: csscls('kvlist htmlvarlist'),

        itemRenderer: function(dt, dd, key, value) {
            $('<span />').attr('title', $('<i />').html(key || '').text()).html(key || '').appendTo(dt);
            dd.html(value && value.value || value);

            if (value && value.xdebug_link) {
                var header = $('<span />').addClass(csscls('filename')).text(value.xdebug_link.filename + ( value.xdebug_link.line ? "#" + value.xdebug_link.line : ''));
                if (value.xdebug_link) {
                    if (value.xdebug_link.ajax) {
                        $('<a title="' + value.xdebug_link.url + '"></a>').on('click', function () {
                            $.ajax(value.xdebug_link.url);
                        }).addClass(csscls('editor-link')).appendTo(header);
                    } else {
                        $('<a href="' + value.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(header);
                    }
                }
                header.appendTo(dd);
            }
        }

    });

    // ------------------------------------------------------------------

    /**
     * Iframe widget
     *
     * Options:
     *  - data
     */
    var IFrameWidget = PhpDebugBar.Widgets.IFrameWidget = PhpDebugBar.Widget.extend({

        tagName: 'iframe',

        className: csscls('iframe'),

        render: function() {
            this.$el.attr({
                seamless: "seamless",
                border: "0",
                width: "100%",
                height: "100%"
            });
            this.bindAttr('data', function(url) { this.$el.attr('src', url); });
        }

    });


    // ------------------------------------------------------------------
    // Collector specific widgets
    // ------------------------------------------------------------------

    /**
     * Widget for the MessagesCollector
     *
     * Uses ListWidget under the hood
     *
     * Options:
     *  - data
     */
    var MessagesWidget = PhpDebugBar.Widgets.MessagesWidget = PhpDebugBar.Widget.extend({

        className: csscls('messages'),

        render: function() {
            var self = this;

            this.$list = new ListWidget({ itemRenderer: function(li, value) {
                if (value.message_html) {
                    var val = $('<span />').addClass(csscls('value')).html(value.message_html).appendTo(li);
                } else {
                    var m = value.message;
                    if (m.length > 100) {
                        m = m.substr(0, 100) + "...";
                    }

                    var val = $('<span />').addClass(csscls('value')).text(m).appendTo(li);
                    if (!value.is_string || value.message.length > 100) {
                        var prettyVal = value.message;
                        if (!value.is_string) {
                            prettyVal = null;
                        }
                        li.css('cursor', 'pointer').click(function () {
                            if (window.getSelection().type == "Range") {
                                return''
                            }
                            if (val.hasClass(csscls('pretty'))) {
                                val.text(m).removeClass(csscls('pretty'));
                            } else {
                                prettyVal = prettyVal || createCodeBlock(value.message, 'php');
                                val.addClass(csscls('pretty')).empty().append(prettyVal);
                            }
                        });
                    }
                }
                if (value.xdebug_link) {
                    var header = $('<span />').addClass(csscls('filename')).text(value.xdebug_link.filename + ( value.xdebug_link.line ? "#" + value.xdebug_link.line : ''));
                    if (value.xdebug_link) {
                        if (value.xdebug_link.ajax) {
                            $('<a title="' + value.xdebug_link.url + '"></a>').on('click', function () {
                                $.ajax(value.xdebug_link.url);
                            }).addClass(csscls('editor-link')).appendTo(header);
                        } else {
                            $('<a href="' + value.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(header);
                        }
                    }
                    header.appendTo(li);
                }
                if (value.collector) {
                    $('<span />').addClass(csscls('collector')).text(value.collector).prependTo(li);
                }
                if (value.label) {
                    val.addClass(csscls(value.label));
                    $('<span />').addClass(csscls('label')).text(value.label).prependTo(li);
                }
            }});

            this.$list.$el.appendTo(this.$el);
            this.$toolbar = $('<div><i class="fa fa-search"></i></div>').addClass(csscls('toolbar')).appendTo(this.$el);

            $('<input type="text" name="search" aria-label="Search" placeholder="Search" />')
                .on('change', function() { self.set('search', this.value); })
                .appendTo(this.$toolbar);

            this.bindAttr('data', function(data) {
                this.set({excludelabel: [], excludecollector: [], search: ''});
                this.$toolbar.find(csscls('.filter')).remove();

                var labels = [], collectors = [], self = this,
                    createFilterItem = function (type, value) {
                        $('<a />')
                            .addClass(csscls('filter')).addClass(csscls(type))
                            .text(value).attr('rel', value)
                            .on('click', function() { self.onFilterClick(this, type); })
                            .appendTo(self.$toolbar)
                    };

                data.forEach(function (item) {
                    if (!labels.includes(item.label || 'none')) {
                        labels.push(item.label || 'none');
                    }

                    if (!collectors.includes(item.collector || 'none')) {
                        collectors.push(item.collector || 'none');
                    }
                });

                if (labels.length > 1) {
                    labels.forEach(label => createFilterItem('label', label));
                }

                if (collectors.length === 1) {
                    return;
                }

                $('<a />').addClass(csscls('filter')).css('visibility', 'hidden').appendTo(self.$toolbar);
                collectors.forEach(collector => createFilterItem('collector', collector));
            });

            this.bindAttr(['excludelabel', 'excludecollector', 'search'], function() {
                var excludelabel = this.get('excludelabel') || [],
                    excludecollector = this.get('excludecollector') || [],
                    search = this.get('search'),
                    caseless = false,
                    fdata = [];

                if (search && search === search.toLowerCase()) {
                    caseless = true;
                }

                this.get('data').forEach(function (item) {
                    var message = caseless ? item.message.toLowerCase() : item.message;

                    if (
                        !excludelabel.includes(item.label || undefined) &&
                        !excludecollector.includes(item.collector || undefined) &&
                        (!search || message.indexOf(search) > -1)
                    ) {
                        fdata.push(item);
                    }
                });

                this.$list.set('data', fdata);
            });
        },

        onFilterClick: function(el, type) {
            $(el).toggleClass(csscls('excluded'));

            var excluded = [];
            this.$toolbar.find(csscls('.filter') + csscls('.excluded') + csscls('.' + type)).each(function() {
                excluded.push(this.rel === 'none' || !this.rel ? undefined : this.rel);
            });

            this.set('exclude' + type, excluded);
        }

    });

    // ------------------------------------------------------------------

    /**
     * Widget for the TimeDataCollector
     *
     * Options:
     *  - data
     */
    var TimelineWidget = PhpDebugBar.Widgets.TimelineWidget = PhpDebugBar.Widget.extend({

        tagName: 'ul',

        className: csscls('timeline'),

        render: function() {
            this.bindAttr('data', function(data) {

                // ported from php DataFormatter
                var formatDuration = function(seconds) {
                    if (seconds < 0.001)
                        return (seconds * 1000000).toFixed() + 'μs';
                    else if (seconds < 0.1)
                        return (seconds * 1000).toFixed(2) + 'ms';
                    else if (seconds < 1)
                        return (seconds * 1000).toFixed() + 'ms';
                    return (seconds).toFixed(2) +  's';
                };

                // ported from php DataFormatter
                var formatBytes = function formatBytes(size) {
                    if (size === 0 || size === null) {
                        return '0B';
                    }

                    var sign = size < 0 ? '-' : '',
                        size = Math.abs(size),
                        base = Math.log(size) / Math.log(1024),
                        suffixes = ['B', 'KB', 'MB', 'GB', 'TB'];
                    return sign + (Math.round(Math.pow(1024, base - Math.floor(base)) * 100) / 100) + suffixes[Math.floor(base)];
                }

                this.$el.empty();
                if (data.measures) {
                    var aggregate = {};

                    for (var i = 0; i < data.measures.length; i++) {
                        var measure = data.measures[i];

                        if(!aggregate[measure.label])
                            aggregate[measure.label] = { count: 0, duration: 0, memory : 0 };

                        aggregate[measure.label]['count'] += 1;
                        aggregate[measure.label]['duration'] += measure.duration;
                        aggregate[measure.label]['memory'] += (measure.memory || 0);

                        var m = $('<div />').addClass(csscls('measure')),
                            li = $('<li />'),
                            left = (measure.relative_start * 100 / data.duration).toFixed(2),
                            width = Math.min((measure.duration * 100 / data.duration).toFixed(2), 100 - left);

                        m.append($('<span />').addClass(csscls('value')).css({
                            left: left + "%",
                            width: width + "%"
                        }));
                        m.append($('<span />').addClass(csscls('label'))
                            .text(measure.label + " (" + measure.duration_str +(measure.memory ? '/' + measure.memory_str: '') + ")"));

                        if (measure.collector) {
                            $('<span />').addClass(csscls('collector')).text(measure.collector).appendTo(m);
                        }

                        m.appendTo(li);
                        this.$el.append(li);

                        if (measure.params && !$.isEmptyObject(measure.params)) {
                            var table = $('<table><tr><th colspan="2">Params</th></tr></table>').hide().addClass(csscls('params')).appendTo(li);
                            for (var key in measure.params) {
                                if (typeof measure.params[key] !== 'function') {
                                    table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') +
                                    '"><pre><code>' + measure.params[key] + '</code></pre></td></tr>');
                                }
                            }
                            li.css('cursor', 'pointer').click(function() {
                                if (window.getSelection().type == "Range") {
                                    return''
                                }
                                var table = $(this).find('table');
                                if (table.is(':visible')) {
                                    table.hide();
                                } else {
                                    table.show();
                                }
                            });
                        }
                    }

                    // convert to array and sort by duration
                    aggregate = $.map(aggregate, function(data, label) {
                       return {
                           label: label,
                           data: data
                       }
                    }).sort(function(a, b) {
                        return b.data.duration - a.data.duration
                    });

                    // build table and add
                    var aggregateTable = $('<table></table>').addClass(csscls('params'));
                    $.each(aggregate, function(i, aggregate) {
                        width = Math.min((aggregate.data.duration * 100 / data.duration).toFixed(2), 100);

                        aggregateTable.append('<tr><td class="' + csscls('name') + '">' +
                            aggregate.data.count + ' x ' + $('<i />').text(aggregate.label).html() + ' (' + width + '%)</td><td class="' + csscls('value') + '">' +
                            '<div class="' + csscls('measure') +'">' +
                                '<span class="' + csscls('value') + '"></span>' +
                                '<span class="' + csscls('label') + '">' + formatDuration(aggregate.data.duration) + (aggregate.data.memory ? '/' + formatBytes(aggregate.data.memory) : '') + '</span>' +
                            '</div></td></tr>');
                        aggregateTable.find('span.' + csscls('value') + ':last').css({width: width + "%" });
                    });

                    this.$el.append('<li/>').find('li:last').append(aggregateTable);
                }
            });
        }

    });

    // ------------------------------------------------------------------

    /**
     * Widget for the displaying exceptions
     *
     * Options:
     *  - data
     */
    var ExceptionsWidget = PhpDebugBar.Widgets.ExceptionsWidget = PhpDebugBar.Widget.extend({

        className: csscls('exceptions'),

        render: function() {
            this.$list = new ListWidget({ itemRenderer: function(li, e) {
                $('<span />').addClass(csscls('message')).text(e.message).appendTo(li);
                if (e.file) {
                    var header = $('<span />').addClass(csscls('filename')).text(e.file + "#" + e.line);
                    if (e.xdebug_link) {
                        if (e.xdebug_link.ajax) {
                            $('<a title="' + e.xdebug_link.url + '"></a>').on('click', function () {
                                fetch(e.xdebug_link.url);
                            }).addClass(csscls('editor-link')).appendTo(header);
                        } else {
                            $('<a href="' + e.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(header);
                        }
                    }
                    header.appendTo(li);
                }
                if (e.type) {
                    $('<span />').addClass(csscls('type')).text(e.type).appendTo(li);
                }
                if (e.surrounding_lines) {
                    var startLine = (e.line - 3) <= 0 ? 1 : e.line - 3;
                    var pre = createCodeBlock(e.surrounding_lines.join(""), 'php', startLine, e.line).addClass(csscls('file')).appendTo(li);
                    if (!e.stack_trace_html) {
                        // This click event makes the var-dumper hard to use.
                        li.click(function () {
                            if (pre.is(':visible')) {
                                pre.hide();
                            } else {
                                pre.show();
                            }
                        });
                    }
                }
                if (e.stack_trace_html) {
                    var $trace = $('<span />').addClass(csscls('filename')).html(e.stack_trace_html);
                    $trace.appendTo(li);
                } else if (e.stack_trace) {
                    e.stack_trace.split("\n").forEach(function (trace) {
                        var $traceLine = $('<div />');
                        $('<span />').addClass(csscls('filename')).text(trace).appendTo($traceLine);
                        $traceLine.appendTo(li);
                    });
                }
            }});
            this.$list.$el.appendTo(this.$el);

            this.bindAttr('data', function(data) {
                this.$list.set('data', data);
                if (data.length == 1) {
                    this.$list.$el.children().first().find(csscls('.file')).show();
                }
            });

        }

    });

    /**
     * Displays datasets in a table
     *
     */
    var DatasetWidget = PhpDebugBar.Widgets.DatasetWidget = PhpDebugBar.Widget.extend({

        initialize: function(options) {
            if (!options['itemRenderer']) {
                options['itemRenderer'] = this.itemRenderer;
            }
            this.set(options);
            this.set('autoshow', null);
            this.set('id', null);
            this.set('sort', localStorage.getItem('debugbar-history-sort') || 'asc');
            this.$el.addClass(csscls('dataset-history'))

            this.renderHead();
        },

        renderHead: function() {
            this.$el.empty();
            this.$actions = $('<div />').addClass(csscls('dataset-actions')).appendTo(this.$el);

            var self = this;

            this.$autoshow = $('<input type=checkbox>')
                .on('click', function() {
                    if (self.get('debugbar').ajaxHandler) {
                        self.get('debugbar').ajaxHandler.setAutoShow($(this).is(':checked'));
                    }
                });

            $('<label>Autoshow</label>')
                .append(this.$autoshow)
                .appendTo(this.$actions)


            this.$clearbtn = $('<a>Clear</a>')
                .appendTo(this.$actions)
                .on('click', function() {
                    self.$table.empty();
                });

            this.$showBtn = $('<a>Show all</a>')
                .appendTo(this.$actions)
                .on('click', function() {
                    self.searchInput.val(null);
                    self.methodInput.val(null);
                    self.set('search', null);
                    self.set('method', null);
                });

            this.methodInput = $('<select name="method" style="width:100px"><option>(method)</option><option>GET</option><option>POST</option><option>PUT</option><option>DELETE</option></select>')
                .on('change', function() { self.set('method', this.value)})
                .appendTo(this.$actions)

            this.searchInput = $('<input type="text" name="search" aria-label="Search" placeholder="Search" />')
                .on('input', function() { self.set('search', this.value); })
                .appendTo(this.$actions);


            this.$table = $('<tbody />');

            $('<table/>')
                .append($('<thead/>')
                    .append($('<tr/>')
                        .append($('<th></th>').css('width', '30px'))
                        .append($('<th>Date ↕</th>').css('width', '175px').click(function() {
                            self.set('sort', self.get('sort') === 'asc' ? 'desc' : 'asc')
                            localStorage.setItem('debugbar-history-sort', self.get('sort'))
                        }))
                        .append($('<th>Method</th>').css('width', '80px'))
                        .append($('<th>URL</th>'))
                        .append($('<th width="40%">Data</th>')))
                )
                .append(this.$table)
                .appendTo(this.$el);


        },

        renderDatasets: function() {
            this.$table.empty();
            var self = this;
            $.each(this.get('data'), function(key, data) {
                if (!data.__meta) {
                    return;
                }

                self.get('itemRenderer')(self, data);
            });
        },

        render: function() {
            this.bindAttr('data', function() {
                if (this.get('autoshow') === null && this.get('debugbar').ajaxHandler) {
                    this.set('autoshow', this.get('debugbar').ajaxHandler.autoShow);
                }

                if (!this.has('data')) {
                    return;
                }

                // Render the latest item
                var datasets = this.get('data');
                var data = datasets[Object.keys(datasets)[Object.keys(datasets).length - 1]]
                if (!data.__meta) {
                    return;
                }

                this.get('itemRenderer')(this, data);
           });
            this.bindAttr(['itemRenderer', 'search', 'method', 'sort'], function() {
                this.renderDatasets();
            })
            this.bindAttr('autoshow', function() {
                var autoshow = this.get('autoshow');
                this.$autoshow.prop('checked', autoshow);
            })
            this.bindAttr('id', function() {
                var id = this.get('id');
                this.$table.find('.' + csscls('active')).removeClass(csscls('active'));
                this.$table.find('tr[data-id=' + id+']').addClass(csscls('active'));
            })
        },

        /**
         * Renders the content of a dataset item
         *
         * @param {Object} value An item from the data array
         */
        itemRenderer: function(widget, data) {
            var meta = data.__meta;

            var $badges = $('<td />');
            var tr = $('<tr />');
            if (widget.get('sort') === 'asc') {
                tr.appendTo(widget.$table);
            } else {
                tr.prependTo(widget.$table);
            }

            var clickHandler = function() {
                var debugbar = widget.get('debugbar');
                debugbar.showDataSet(meta.id, debugbar.datesetTitleFormater.format('', data, meta.suffix, meta.nb));
                widget.$table.find('.' + csscls('active')).removeClass(csscls('active'));
                tr.addClass(csscls('active'));

                if ($(this).data('tab')) {
                    debugbar.showTab($(this).data('tab'));
                }
            }

            tr.attr('data-id', meta['id'])
                .append($('<td>#' + meta['nb'] + '</td>').click(clickHandler))
                .append($('<td>' + meta['datetime'] + '</td>').click(clickHandler))
                .append($('<td>' + meta['method'] + '</td>').click(clickHandler))
                .append($('<td />').append(meta['uri'] + (meta['suffix'] ? ' ' + meta['suffix'] : '')).click(clickHandler))
                .css('cursor', 'pointer')
                .addClass(csscls('table-row'))

            var debugbar = widget.get('debugbar');
            $.each(debugbar.dataMap, function(key, def) {
                var d = getDictValue(data, def[0], def[1]);
                if (key.indexOf(':') != -1) {
                    key = key.split(':');
                    if (key[1] === 'badge' && d > 0) {
                        var control = debugbar.getControl(key[0]);
                        var $a = $('<a>').attr('title', control.get('title')).data('tab', key[0]);
                        if (control.$icon) {
                            $a.append(debugbar.getControl(key[0]).$icon.clone());
                        }
                        if (control.$badge) {
                            $a.append(debugbar.getControl(key[0]).$badge.clone().css('display', 'inline-block').text(d));
                        }
                        $a.appendTo($badges).click(clickHandler);
                    }
                }
            });
            tr.append($badges);

            if (debugbar.activeDatasetId === meta['id']) {
                tr.addClass(csscls('active'));
            }

            var search = widget.get('search');
            var method = widget.get('method');
            if ((search && meta['uri'].indexOf(search) == -1) || (method && meta['method'] !== method)) {
                tr.hide();
            }
        }

    });


})(PhpDebugBar.$);

if (typeof(PhpDebugBar) == 'undefined') {
    // namespace
    var PhpDebugBar = {};
    PhpDebugBar.$ = jQuery;
}

(function($) {

    var csscls = function(cls) {
        return PhpDebugBar.utils.csscls(cls, 'phpdebugbar-openhandler-');
    };

    PhpDebugBar.OpenHandler = PhpDebugBar.Widget.extend({

        className: 'phpdebugbar-openhandler',

        defaults: {
            items_per_page: 20
        },

        render: function() {
            var self = this;

            this.$el.appendTo('body').hide();
            this.$closebtn = $('<a><i class="fa fa-times"></i></a>');
            this.$table = $('<tbody />');
            $('<div>PHP DebugBar | Open</div>').addClass(csscls('header')).append(this.$closebtn).appendTo(this.$el);
            $('<table><thead><tr><th width="150">Date</th><th width="55">Method</th><th>URL</th><th width="125">IP</th><th width="100">Filter data</th></tr></thead></table>').append(this.$table).appendTo(this.$el);
            this.$actions = $('<div />').addClass(csscls('actions')).appendTo(this.$el);

            this.$closebtn.on('click', function() {
                self.hide();
            });

            this.$loadmorebtn = $('<a>Load more</a>')
                .appendTo(this.$actions)
                .on('click', function() {
                    self.find(self.last_find_request, self.last_find_request.offset + self.get('items_per_page'), self.handleFind.bind(self));
                });

            this.$showonlycurrentbtn = $('<a>Show only current URL</a>')
                .appendTo(this.$actions)
                .on('click', function() {
                    self.$table.empty();
                    self.find({uri: window.location.pathname}, 0, self.handleFind.bind(self));
                });

            this.$showallbtn = $('<a>Show all</a>')
                .appendTo(this.$actions)
                .on('click', function() {
                    self.refresh();
                });

            this.$clearbtn = $('<a>Delete all</a>')
                .appendTo(this.$actions)
                .on('click', function() {
                    self.clear(function() {
                        self.hide();
                    });
                });

            this.addSearch();

            this.$overlay = $('<div />').addClass(csscls('overlay')).hide().appendTo('body');
            this.$overlay.on('click', function() {
                self.hide();
            });
        },

        refresh: function() {
            this.$table.empty();
            this.$loadmorebtn.show();
            this.find({}, 0, this.handleFind.bind(this));
        },

        addSearch: function(){
            var self = this;
            var searchBtn = $('<button />')
                .text('Search')
                .attr('type', 'submit')
                .on('click', function(e) {
                    self.$table.empty();
                    var search = {};
                    var a = $(this).parent().serializeArray();
                    $.each(a, function() {
                        if(this.value){
                            search[this.name] = this.value;
                        }
                    });

                    self.find(search, 0, self.handleFind.bind(self));
                    e.preventDefault();
                });

            $('<form />')
                .append('<br/><b>Filter results</b><br/>')
                .append('Method: <select name="method"><option></option><option>GET</option><option>POST</option><option>PUT</option><option>DELETE</option></select><br/>')
                .append('Uri: <input type="text" name="uri"><br/>')
                .append('IP: <input type="text" name="ip"><br/>')
                .append(searchBtn)
                .appendTo(this.$actions);
        },

        handleFind: function(data) {
            var self = this;
            $.each(data, function(i, meta) {
               var a = $('<a />')
                    .text('Load dataset')
                    .on('click', function(e) {
                       self.hide();
                       self.load(meta['id'], function(data) {
                           self.callback(meta['id'], data);
                       });
                       e.preventDefault();
                    });

                var method = $('<a />')
                    .text(meta['method'])
                    .on('click', function(e) {
                        self.$table.empty();
                        self.find({method: meta['method']}, 0, self.handleFind.bind(self));
                        e.preventDefault();
                    });

                var uri = $('<a />')
                    .text(meta['uri'])
                    .on('click', function(e) {
                        self.hide();
                        self.load(meta['id'], function(data) {
                            self.callback(meta['id'], data);
                        });
                        e.preventDefault();
                    });

                var ip = $('<a />')
                    .text(meta['ip'])
                    .on('click', function(e) {
                        self.$table.empty();
                        self.find({ip: meta['ip']}, 0, self.handleFind.bind(self));
                        e.preventDefault();
                    });

                var search = $('<a />')
                    .text('Show URL')
                    .on('click', function(e) {
                        self.$table.empty();
                        self.find({uri: meta['uri']}, 0, self.handleFind.bind(self));
                        e.preventDefault();
                    });

                $('<tr />')
                    .append('<td>' + meta['datetime'] + '</td>')
                    .append('<td>' + meta['method'] + '</td>')
                    .append($('<td />').append(uri))
                    .append($('<td />').append(ip))
                    .append($('<td />').append(search))
                    .appendTo(self.$table);
            });
            if (data.length < this.get('items_per_page')) {
                this.$loadmorebtn.hide();
            }
        },

        show: function(callback) {
            this.callback = callback;
            this.$el.show();
            this.$overlay.show();
            this.refresh();
        },

        hide: function() {
            this.$el.hide();
            this.$overlay.hide();
        },

        find: function(filters, offset, callback) {
            var data = $.extend({}, filters, {max: this.get('items_per_page'), offset: offset || 0});
            this.last_find_request = data;
            this.ajax(data, callback);
        },

        load: function(id, callback) {
            this.ajax({op: "get", id: id}, callback);
        },

        clear: function(callback) {
            this.ajax({op: "clear"}, callback);
        },

        ajax: function(data, callback) {
            var url = this.get('url');
            if (data) {
                url = url + '?' + new URLSearchParams(data);
            }

            fetch(url, {
                method: "GET",
                headers: {
                    "Accept": "application/json",
                },
            })
                .then((data) => data.json())
                .then(callback);
        }

    });

})(PhpDebugBar.$);

(function($) {

    var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');

    /**
     * Widget for the displaying sql queries
     *
     * Options:
     *  - data
     */
    var SQLQueriesWidget = PhpDebugBar.Widgets.SQLQueriesWidget = PhpDebugBar.Widget.extend({

        className: csscls('sqlqueries'),

        onFilterClick: function(el) {
            $(el).toggleClass(csscls('excluded'));
            this.$list.$el.find("li[connection=" + $(el).attr("rel") + "]").toggle();
        },
        onCopyToClipboard: function (el) {
            var code = $(el).parent('li').find('code').get(0);
            var copy = function () {
                try {
                    if (document.execCommand('copy')) {
                        $(el).addClass(csscls('copy-clipboard-check'));
                        setTimeout(function(){
                            $(el).removeClass(csscls('copy-clipboard-check'));
                        }, 2000)
                    }
                } catch (err) {
                    console.log('Oops, unable to copy');
                }
            };
            var select = function (node) {
                if (document.selection) {
                    var range = document.body.createTextRange();
                    range.moveToElementText(node);
                    range.select();
                } else if (window.getSelection) {
                    var range = document.createRange();
                    range.selectNodeContents(node);
                    window.getSelection().removeAllRanges();
                    window.getSelection().addRange(range);
                }
                copy();
                window.getSelection().removeAllRanges();
            };
            select(code);
        },
        renderList: function (caption, icon, data) {
            var $ul = $('<ul />').addClass(csscls('table-list')), $parts;
            var $li = $('<li />').addClass(csscls('table-list-item'));
            var $span = $('<span />').addClass('phpdebugbar-text-muted');
            for (var key in data) {
                var value = typeof data[key] === 'function' ? data[key].name + ' {}' : data[key];
                $li.clone().append(typeof value === 'object' && value !== null
                    ? [$span.clone().text(value.index || key).append('.'), '&nbsp;']
                        .concat(value.namespace ? [value.namespace + '::'] : [])
                        .concat([value.name || value.file])
                        .concat(value.line ? [$span.clone().text(':' + value.line)] : [])
                    : [$span.clone().text(key + ':'), '&nbsp;', value]
                ).appendTo($ul);
            }
            caption += icon ? ' <i class="fa fa-' + icon + ' phpdebugbar-text-muted"></i>' : '';
            return $('<tr />').append(
                $('<td />').addClass(csscls('name')).html(caption),
                $('<td />').addClass(csscls('value')).append($ul)
            );
        },
        render: function() {
            this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el);

            this.$toolbar = $('<div />').addClass(csscls('toolbar')).appendTo(this.$el);

            var filters = [], self = this;

            this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, stmt) {
                if (stmt.type === 'transaction') {
                    $('<strong />').addClass(csscls('sql')).addClass(csscls('name')).text(stmt.sql).appendTo(li);
                } else {
                    $('<code />').addClass(csscls('sql')).html(PhpDebugBar.Widgets.highlight(stmt.sql, 'sql')).appendTo(li);
                }
                if (stmt.width_percent) {
                    $('<div />').addClass(csscls('bg-measure')).append(
                        $('<div />').addClass(csscls('value')).css({
                            left: stmt.start_percent + '%',
                            width: Math.max(stmt.width_percent, 0.01) + '%',
                        })
                    ).appendTo(li);
                }
                if (stmt.duration_str) {
                    $('<span title="Duration" />').addClass(csscls('duration')).text(stmt.duration_str).appendTo(li);
                }
                if (stmt.memory_str) {
                    $('<span title="Memory usage" />').addClass(csscls('memory')).text(stmt.memory_str).appendTo(li);
                }
                if (typeof(stmt.row_count) != 'undefined') {
                    $('<span title="Row count" />').addClass(csscls('row-count')).text(stmt.row_count).appendTo(li);
                }
                if (typeof(stmt.stmt_id) != 'undefined' && stmt.stmt_id) {
                    $('<span title="Prepared statement ID" />').addClass(csscls('stmt-id')).text(stmt.stmt_id).appendTo(li);
                }
                if (stmt.connection) {
                    $('<span title="Connection" />').addClass(csscls('database')).text(stmt.connection).appendTo(li);
                    li.attr("connection",stmt.connection);
                    if ( $.inArray(stmt.connection, filters) == -1 ) {
                        filters.push(stmt.connection);
                        $('<a />')
                            .addClass(csscls('filter'))
                            .text(stmt.connection)
                            .attr('rel', stmt.connection)
                            .on('click', function() { self.onFilterClick(this); })
                            .appendTo(self.$toolbar);
                        if (filters.length>1) {
                            self.$toolbar.show();
                            self.$list.$el.css("margin-bottom","20px");
                        }
                    }
                }
                if (typeof(stmt.is_success) != 'undefined' && !stmt.is_success) {
                    li.addClass(csscls('error'));
                    li.append($('<span />').addClass(csscls('error')).text("[" + stmt.error_code + "] " + stmt.error_message));
                }
                if ((!stmt.type || stmt.type === 'query')) {
                    $('<span title="Copy to clipboard" />')
                        .addClass(csscls('copy-clipboard'))
                        .css('cursor', 'pointer')
                        .html("&#8203;")
                        .on('click', function (event) {
                            self.onCopyToClipboard(this);
                            event.stopPropagation();
                        })
                        .appendTo(li);
                }
                if (typeof(stmt.xdebug_link) !== 'undefined' && stmt.xdebug_link) {
                    var header = $('<span title="Filename" />').addClass(csscls('filename')).text(stmt.xdebug_link.filename + ( stmt.xdebug_link.line ? "#" + stmt.xdebug_link.line : ''));
                    $('<a href="' + stmt.xdebug_link.url + '"></a>').on('click', function () {
                        event.stopPropagation();
                        if (stmt.xdebug_link.ajax) {                            
                            fetch(stmt.xdebug_link.url);
                            event.preventDefault();
                        }
                    }).addClass(csscls('editor-link')).appendTo(header);
                    header.appendTo(li);
                }
                var table = $('<table></table>').addClass(csscls('params'));
                if (stmt.params && !$.isEmptyObject(stmt.params)) {
                    self.renderList('Params', 'thumb-tack', stmt.params).appendTo(table);
                }
                if (stmt.bindings && !$.isEmptyObject(stmt.bindings)) {
                    self.renderList('Bindings', 'thumb-tack', stmt.bindings).appendTo(table);
                }
                if (stmt.hints && !$.isEmptyObject(stmt.hints)) {
                    self.renderList('Hints', 'question-circle', stmt.hints).appendTo(table);
                }
                if (stmt.backtrace && !$.isEmptyObject(stmt.backtrace)) {
                    self.renderList('Backtrace', 'list-ul', stmt.backtrace).appendTo(table);
                }
                if (table.find('tr').length) {
                    table.appendTo(li);
                    li.css('cursor', 'pointer').click(function() {
                        if (window.getSelection().type == "Range") {
                            return''
                        }
                        if (table.is(':visible')) {
                            table.hide();
                        } else {
                            table.show();
                        }
                    });
                }
            }});
            this.$list.$el.appendTo(this.$el);

            this.bindAttr('data', function(data) {
                // the PDO collector maybe is empty
                if (data.length <= 0 || !data.statements) {
                    return false;
                }
                filters = [];
                this.$toolbar.hide().find(csscls('.filter')).remove();
                this.$list.set('data', data.statements);
                this.$status.empty();

                // Search for duplicate statements.
                for (var sql = {}, duplicate = 0, i = 0; i < data.statements.length; i++) {
                    if (data.statements[i].type && data.statements[i].type !== 'query') {
                        continue;
                    }
                    var stmt = data.statements[i].sql;
                    if (data.statements[i].params && !$.isEmptyObject(data.statements[i].params)) {
                        stmt += JSON.stringify(data.statements[i].params);
                    }
                    if (data.statements[i].bindings && !$.isEmptyObject(data.statements[i].bindings)) {
                        stmt += JSON.stringify(data.statements[i].bindings);
                    }
                    if (data.statements[i].connection) {
                        stmt += '@' + data.statements[i].connection;
                    }
                    sql[stmt] = sql[stmt] || { keys: [] };
                    sql[stmt].keys.push(i);
                }
                // Add classes to all duplicate SQL statements.
                for (var stmt in sql) {
                    if (sql[stmt].keys.length > 1) {
                        duplicate += sql[stmt].keys.length;
                        for (var i = 0; i < sql[stmt].keys.length; i++) {
                            this.$list.$el.find('.' + csscls('list-item')).eq(sql[stmt].keys[i])
                                .addClass(csscls('sql-duplicate'));
                        }
                    }
                }

                var t = $('<span />').text(data.nb_statements + " statements were executed").appendTo(this.$status);
                if (data.nb_failed_statements) {
                    t.append(", " + data.nb_failed_statements + " of which failed");
                }
                if (duplicate) {
                    t.append(", " + duplicate + " of which were duplicates");
                    t.append(", " + (data.nb_statements - duplicate) + " unique. ");

                    // add toggler for displaying only duplicated queries
                    var duplicatedText = 'Show only duplicated';
                    $('<a />').addClass(csscls('duplicates')).click(function () {
                        $(this).toggleClass('shown-duplicated')
                            .text($(this).hasClass('shown-duplicated') ? 'Show All' : duplicatedText);
                        $('.' + self.className + ' .' + csscls('list-item'))
                            .not('.' + csscls('sql-duplicate')).toggle();
                    }).text(duplicatedText).appendTo(t);
                }
                if (data.accumulated_duration_str) {
                    this.$status.append($('<span title="Accumulated duration" />').addClass(csscls('duration')).text(data.accumulated_duration_str));
                }
                if (data.memory_usage_str) {
                    this.$status.append($('<span title="Memory usage" />').addClass(csscls('memory')).text(data.memory_usage_str));
                }
            });
        }

    });

})(PhpDebugBar.$);

</script>
<script type="text/javascript">
var phpdebugbar = new PhpDebugBar.DebugBar();
phpdebugbar.addIndicator("php_version", new PhpDebugBar.DebugBar.Indicator({"icon":"code","tooltip":"PHP Version"}), "right");
phpdebugbar.addIndicator("version", new PhpDebugBar.DebugBar.Indicator({"icon":"github","tooltip":"Version"}), "right");
phpdebugbar.addIndicator("environment", new PhpDebugBar.DebugBar.Indicator({"icon":"desktop","tooltip":"Environment"}), "right");
phpdebugbar.addIndicator("locale", new PhpDebugBar.DebugBar.Indicator({"icon":"flag","tooltip":"Current locale"}), "right");
phpdebugbar.addIndicator("time", new PhpDebugBar.DebugBar.Indicator({"icon":"clock-o","tooltip":"Request Duration"}), "right");
phpdebugbar.addTab("timeline", new PhpDebugBar.DebugBar.Tab({"icon":"tasks","title":"Timeline", "widget": new PhpDebugBar.Widgets.TimelineWidget()}));
phpdebugbar.addIndicator("memory", new PhpDebugBar.DebugBar.Indicator({"icon":"cogs","tooltip":"Memory Usage"}), "right");
phpdebugbar.addTab("database", new PhpDebugBar.DebugBar.Tab({"icon":"arrow-right","title":"Database", "widget": new PhpDebugBar.Widgets.SQLQueriesWidget()}));
phpdebugbar.addTab("session", new PhpDebugBar.DebugBar.Tab({"icon":"archive","title":"Session", "widget": new PhpDebugBar.Widgets.VariableListWidget()}));
phpdebugbar.addTab("config", new PhpDebugBar.DebugBar.Tab({"icon":"gear","title":"Config", "widget": new PhpDebugBar.Widgets.VariableListWidget()}));
phpdebugbar.addTab("file", new PhpDebugBar.DebugBar.Tab({"icon":"files-o","title":"File", "widget": new PhpDebugBar.Widgets.MessagesWidget()}));
phpdebugbar.addTab("request", new PhpDebugBar.DebugBar.Tab({"icon":"tags","title":"Request", "widget": new PhpDebugBar.Widgets.VariableListWidget()}));
phpdebugbar.setDataMap({
"php_version": ["php.version", ],
"version": ["codeigniter.version", ],
"environment": ["codeigniter.environment", ],
"locale": ["codeigniter.locale", ],
"time": ["time.duration_str", '0ms'],
"timeline": ["time", {}],
"memory": ["memory.peak_usage_str", '0B'],
"database": ["ciquerybuilder", []],
"database:badge": ["ciquerybuilder.nb_statements", 0],
"session": ["session", {}],
"config": ["config", {}],
"file": ["file.messages", {}],
"file:badge": ["file.count", null],
"request": ["request", {}]
});
phpdebugbar.restoreState();
phpdebugbar.ajaxHandler = new PhpDebugBar.AjaxHandler(phpdebugbar, undefined, true);
phpdebugbar.ajaxHandler.bindToXHR();
phpdebugbar.addDataSet({"__meta":{"id":"X5e70b3a4c2ba2951b7e9febc3cb1fd24","datetime":"2026-05-21 02:04:29","utime":1779303869.571091,"method":"GET","uri":"\/sitemap.xml","ip":"104.23.243.42"},"php":{"version":"7.2.33","interface":"fpm-fcgi"},"codeigniter":{"version":"3.1.6","environment":"development","locale":"vietnamese"},"time":{"start":1779303869.458059,"end":1779303869.571107,"duration":0.11304783821105957,"duration_str":"113ms","measures":[{"label":"loading_time:_base_classes","start":1779303869.458061,"relative_start":1.9073486328125e-6,"end":1779303869.469859,"relative_end":1779303869.469859,"duration":0.011797904968261719,"duration_str":"11.8ms","memory":0,"memory_str":"0B","params":[],"collector":null},{"label":"controller_execution_time_( Seo \/ sitemap )","start":1779303869.471533,"relative_start":0.013473987579345703,"end":1779303869.540724,"relative_end":1779303869.540724,"duration":0.06919097900390625,"duration_str":"69.19ms","memory":0,"memory_str":"0B","params":[],"collector":null}]},"memory":{"peak_usage":5356256,"peak_usage_str":"5MB"},"ciquerybuilder":{"nb_statements":3,"accumulated_duration":0.0009021759033203125,"accumulated_duration_str":"902\u03bcs","statements":[{"sql":"SELECT *\nFROM `ap_category`\nJOIN `ap_category_translations` ON `ap_category`.`id` = `ap_category_translations`.`id`\nWHERE `ap_category_translations`.`language_code` = \u0027vi\u0027\nAND `ap_category`.`is_status` = 1\nORDER BY `ap_category`.`order` DESC\n LIMIT 100","connection":"ths_visiter_in","duration":0.00040793418884277344,"duration_str":"408\u03bcs"},{"sql":"SELECT *\nFROM `ap_post`\nJOIN `ap_post_translations` ON `ap_post`.`id` = `ap_post_translations`.`id`\nWHERE `ap_post_translations`.`language_code` = \u0027vi\u0027\nAND `ap_post`.`is_status` = 1\nORDER BY `ap_post`.`created_time` DESC\n LIMIT 100","connection":"ths_visiter_in","duration":0.00020003318786621094,"duration_str":"200\u03bcs"},{"sql":"SELECT *\nFROM `ap_category` as `A`\nJOIN `ap_category_translations` as `B` ON `A`.`id` = `B`.`id`\nWHERE `A`.`id` = \u002710\u0027","connection":"ths_visiter_in","duration":0.0002942085266113281,"duration_str":"294\u03bcs"}]},"session":{"__ci_last_regenerate":"1779303869","public_lang_code":"vi","public_lang_full":"vietnamese","PHPDEBUGBAR_STACK_DATA":"[]"},"config":{"base_url":"http:\/\/ths.visiter.in\/","index_page":"","uri_protocol":"REQUEST_URI","url_suffix":"","language":"vietnamese","charset":"utf-8","enable_hooks":"true","subclass_prefix":"APS_","composer_autoload":"\/www\/wwwroot\/ths.visiter.in\/vendor\/autoload.php","permitted_uri_chars":"a-z 0-9~%.:_\\-","enable_query_strings":"false","controller_trigger":"c","function_trigger":"m","directory_trigger":"d","allow_get_array":"true","log_threshold":"1","log_path":"","log_file_extension":"log","log_file_permissions":"420","log_date_format":"Y-m-d H:i:s","error_views_path":"","cache_path":"","cache_query_string":"false","encryption_key":"aps","sess_driver":"files","sess_cookie_name":"aps_cms_core","sess_expiration":"7200","sess_save_path":"\/tmp","sess_match_ip":"false","sess_time_to_update":"300","sess_regenerate_destroy":"false","cookie_prefix":"","cookie_domain":"","cookie_path":"\/","cookie_secure":"false","cookie_httponly":"false","standardize_newlines":"false","global_xss_filtering":"false","csrf_protection":"true","csrf_token_name":"APS_csrf_token","csrf_cookie_name":"APS_csrf_cookie","csrf_expire":"7200","csrf_regenerate":"false","compress_output":"false","time_reference":"local","rewrite_short_tags":"false","proxy_ips":"","crumb_divider":"","tag_open":"\u003Cul class=\u0022breadcrumb\u0022\u003E","tag_close":"\u003C\/ul\u003E","crumb_open":"\u003Cli typeof=\u0022v:breadcrumb\u0022\u003E","crumb_last_open":"\u003Cli \u003E","crumb_close":"\u003C\/li\u003E","frontend_crumb_divider":"","frontend_tag_open":"\u003Cnav class=\u0022breadcrumb\u0022\u003E","frontend_tag_close":"\u003C\/nav\u003E","frontend_crumb_open":"\u003Cli class=\u0022breadcrumb-item \u0022 typeof=\u0022v:breadcrumbs\u0022\u003E","frontend_crumb_last_open":"\u003Cli class=\u0022breadcrumb-item active\u0022\u003E","frontend_crumb_close":"\u003C\/li\u003E","cms_language":"array:1 [\n  \u0022vi\u0022 =\u003E \u0022VN\u0022\n]","cms_lang_cnf":"array:1 [\n  \u0022vi\u0022 =\u003E \u0022vietnamese\u0022\n]","cms_language_flg":"array:2 [\n  \u0022vi\u0022 =\u003E \u0022flag-vn.jpg\u0022\n  \u0022en\u0022 =\u003E \u0022flag-en.jpg\u0022\n]","default_language":"vi","default_currency":"EUR","thumbnail":"array:4 [\n  \u0022width\u0022 =\u003E 300\n  \u0022height\u0022 =\u003E 300\n  \u0022crop\u0022 =\u003E true\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","1920x367":"array:4 [\n  \u0022width\u0022 =\u003E 1920\n  \u0022height\u0022 =\u003E 367\n  \u0022crop\u0022 =\u003E true\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","710x580":"array:4 [\n  \u0022width\u0022 =\u003E 710\n  \u0022height\u0022 =\u003E 580\n  \u0022crop\u0022 =\u003E true\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","700x365":"array:4 [\n  \u0022width\u0022 =\u003E 700\n  \u0022height\u0022 =\u003E 365\n  \u0022crop\u0022 =\u003E true\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","1920x1220":"array:4 [\n  \u0022width\u0022 =\u003E 1920\n  \u0022height\u0022 =\u003E 1220\n  \u0022crop\u0022 =\u003E true\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","312x228":"array:4 [\n  \u0022width\u0022 =\u003E 312\n  \u0022height\u0022 =\u003E 228\n  \u0022crop\u0022 =\u003E false\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","460x260":"array:4 [\n  \u0022width\u0022 =\u003E 460\n  \u0022height\u0022 =\u003E 260\n  \u0022crop\u0022 =\u003E true\n  \u0022qlty\u0022 =\u003E \u002280%\u0022\n]","257x315":"array:4 [\n  \u0022width\u0022 =\u003E 255\n  \u0022height\u0022 =\u003E 315\n  \u0022crop\u0022 =\u003E false\n  \u0022qlty\u0022 =\u003E \u002280%\u0022\n]","50x50":"array:4 [\n  \u0022width\u0022 =\u003E 100\n  \u0022height\u0022 =\u003E 100\n  \u0022crop\u0022 =\u003E false\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","565x510":"array:4 [\n  \u0022width\u0022 =\u003E 565\n  \u0022height\u0022 =\u003E 510\n  \u0022crop\u0022 =\u003E false\n  \u0022qlty\u0022 =\u003E \u0022100%\u0022\n]","protocol":"smtp","smtp_host":"ssl:\/\/smtp.googlemail.com","smtp_user":"noreplyapecsoft2@gmail.com","smtp_pass":"gmgalshdeivbuuhs","smtp_port":"465","mailtype":"html","newline":"\r\n","crlf":"\r\n"},"file":{"messages":[{"message":"\u0027config\/constants.php\u0027,","is_string":true},{"message":"\u0027config\/config.php\u0027,","is_string":true},{"message":"\u0027config\/hooks.php\u0027,","is_string":true},{"message":"\u0027config\/routes.php\u0027,","is_string":true},{"message":"\u0027config\/mimes.php\u0027,","is_string":true},{"message":"\u0027core\/APS_Lang.php\u0027,","is_string":true},{"message":"\u0027core\/APS_Controller.php\u0027,","is_string":true},{"message":"\u0027core\/APS_Trait.php\u0027,","is_string":true},{"message":"\u0027core\/Admin_Controller.php\u0027,","is_string":true},{"message":"\u0027core\/Public_Controller.php\u0027,","is_string":true},{"message":"\u0027core\/API_Controller.php\u0027,","is_string":true},{"message":"\u0027controllers\/Seo.php\u0027,","is_string":true},{"message":"\u0027config\/autoload.php\u0027,","is_string":true},{"message":"\u0027libraries\/APS_Form_validation.php\u0027,","is_string":true},{"message":"\u0027config\/form_validation.php\u0027,","is_string":true},{"message":"\u0027config\/user_agents.php\u0027,","is_string":true},{"message":"\u0027libraries\/Breadcrumbs.php\u0027,","is_string":true},{"message":"\u0027config\/breadcrumbs.php\u0027,","is_string":true},{"message":"\u0027helpers\/data_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/email_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/youtube_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/cms_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/general_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/number_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/link_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/datetime_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/debug_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/curl_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/string_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/response_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/builder_query_helper.php\u0027,","is_string":true},{"message":"\u0027config\/cms.php\u0027,","is_string":true},{"message":"\u0027config\/languages.php\u0027,","is_string":true},{"message":"\u0027config\/images.php\u0027,","is_string":true},{"message":"\u0027language\/vietnamese\/general_lang.php\u0027,","is_string":true},{"message":"\u0027config\/database.php\u0027,","is_string":true},{"message":"\u0027helpers\/navmenus_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/notify_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/title_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/format_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/image_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/status_order_helper.php\u0027,","is_string":true},{"message":"\u0027helpers\/status_helper.php\u0027,","is_string":true},{"message":"\u0027config\/email.php\u0027,","is_string":true},{"message":"\u0027language\/vietnamese\/frontend_lang.php\u0027,","is_string":true},{"message":"\u0027core\/APS_Model.php\u0027,","is_string":true},{"message":"\u0027models\/Category_model.php\u0027,","is_string":true},{"message":"\u0027models\/Post_model.php\u0027,","is_string":true},{"message":"\u0027views\/errors\/html\/error_php.php\u0027,","is_string":true},{"message":"\u0027hooks\/compress.php\u0027,","is_string":true},{"message":"\u0027libraries\/Profiler.php\u0027,","is_string":true},{"message":"\u0027config\/profiler.php\u0027,","is_string":true},{"message":"\u0027language\/vietnamese\/profiler_lang.php\u0027,","is_string":true},{"message":"\u0027libraries\/collectors\/CodeIgniterCollector.php\u0027,","is_string":true},{"message":"\u0027libraries\/collectors\/BenchmarkCollector.php\u0027,","is_string":true},{"message":"\u0027libraries\/collectors\/CodeIgniterRequestCollector.php\u0027,","is_string":true},{"message":"\u0027libraries\/collectors\/QueryCollector.php\u0027,","is_string":true},{"message":"\u0027libraries\/collectors\/SessionCollector.php\u0027,","is_string":true},{"message":"\u0027libraries\/collectors\/IncludedFileCollector.php\u0027,","is_string":true}],"count":59},"request":{"$_GET":"[]","$_POST":"[]","0":"\u0022seo\/sitemap\u0022","$_SERVER":"array:18 [\n  \u0022HTTP_ACCEPT\u0022 =\u003E \u0022*\/*\u0022\n  \u0022HTTP_USER_AGENT\u0022 =\u003E \u0022Mozilla\/5.0 AppleWebKit\/537.36 (KHTML, like Gecko; compatible; ClaudeBot\/1.0; +claudebot@anthropic.com)\u0022\n  \u0022HTTP_CONNECTION\u0022 =\u003E \u0022Keep-Alive\u0022\n  \u0022SERVER_PORT\u0022 =\u003E \u002280\u0022\n  \u0022SERVER_NAME\u0022 =\u003E \u0022ths.visiter.in\u0022\n  \u0022REMOTE_ADDR\u0022 =\u003E \u0022104.23.243.42\u0022\n  \u0022SERVER_SOFTWARE\u0022 =\u003E \u0022nginx\/1.24.0\u0022\n  \u0022HTTP_ACCEPT_LANGUAGE\u0022 =\u003E null\n  \u0022SCRIPT_NAME\u0022 =\u003E \u0022\/index.php\u0022\n  \u0022REQUEST_METHOD\u0022 =\u003E \u0022GET\u0022\n  \u0022HTTP_HOST\u0022 =\u003E \u0022ths.visiter.in\u0022\n  \u0022REMOTE_HOST\u0022 =\u003E null\n  \u0022CONTENT_TYPE\u0022 =\u003E \u0022\u0022\n  \u0022SERVER_PROTOCOL\u0022 =\u003E \u0022HTTP\/1.1\u0022\n  \u0022QUERY_STRING\u0022 =\u003E \u0022\u0022\n  \u0022HTTP_ACCEPT_ENCODING\u0022 =\u003E \u0022gzip\u0022\n  \u0022HTTP_X_FORWARDED_FOR\u0022 =\u003E \u002210.8.35.199,216.73.216.89\u0022\n  \u0022HTTP_DNT\u0022 =\u003E null\n]"}}, "X5e70b3a4c2ba2951b7e9febc3cb1fd24");

</script>
