├── .gitignore ├── LICENSE ├── README.md ├── css ├── animate.css ├── bootstrap-datetimepicker.min.css ├── dataTables.bootstrap.css ├── img │ ├── details_close.png │ └── details_open.png ├── jquery.dataTables.min.css ├── prettify.min.css └── styles.css ├── favicon.ico ├── index.html └── js ├── app.js ├── app └── main.js ├── lib ├── bootstrap-datetimepicker.min.js ├── bootstrap-notify.min.js ├── bootstrap.min.js ├── collapse.js ├── cryptojs_v3.1.2.min.js ├── dataTables.bootstrap.js ├── jquery.cookie.js ├── jquery.dataTables.min.js ├── jquery.js ├── moment.min.js ├── prettify.min.js ├── store+json2.min.js ├── transition.js └── xapiwrapper.min.js └── require.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | node_modules 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tyler Mulligan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xapi-statement-viewer 2 | A datatables and bootstrap based Experience API (xAPI) Statement viewer. 3 | 4 | Pulls xAPI Statements from a Learning Record Store (LRS) using [XAPIWrapper](https://github.com/adlnet/XAPIWrapper) and displays them nicely in a sortable and filterable table. 5 | 6 | ##Installation 7 | 8 | Run `git clone https://github.com/adlnet/xapi-statement-viewer` 9 | 10 | ##Use 11 | Host the github project files on your server. Launch index.html. 12 | 13 | ## Contributing to the project 14 | We welcome contributions to this project. Fork this repository, make changes, and submit pull requests. If you're not comfortable with editing the code, please [submit an issue](https://github.com/adlnet/xapi-statement-viewer/issues) and we'll be happy to address it. 15 | 16 | ## License 17 | Copyright ©2016 Advanced Distributed Learning 18 | 19 | Licensed under the Apache License, Version 2.0 (the "License"); 20 | you may not use this file except in compliance with the License. 21 | You may obtain a copy of the License at 22 | 23 | http://www.apache.org/licenses/LICENSE-2.0 24 | 25 | Unless required by applicable law or agreed to in writing, software 26 | distributed under the License is distributed on an "AS IS" BASIS, 27 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | See the License for the specific language governing permissions and 29 | limitations under the License. 30 | 31 | [Live Demo](http://adlnet.github.io/xapi-statement-viewer) 32 | -------------------------------------------------------------------------------- /css/bootstrap-datetimepicker.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Datetimepicker for Bootstrap 3 3 | //! version : 4.0.0-beta 4 | * https://github.com/Eonasdan/bootstrap-datetimepicker/ 5 | */.bootstrap-datetimepicker-widget.dropdown-menu{margin:2px 0;padding:4px;width:19em}@media (min-width:768px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:992px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:1200px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}.bootstrap-datetimepicker-widget.dropdown-menu:before,.bootstrap-datetimepicker-widget.dropdown-menu:after{content:'';display:inline-block;position:absolute}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);top:-7px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;top:-6px;left:8px}.bootstrap-datetimepicker-widget.dropdown-menu.top:before{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,.2);bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.dropdown-menu.top:after{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget .list-unstyled{margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:700;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootstrap-datetimepicker-widget .btn[data-action=incrementHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Increment Hours"}.bootstrap-datetimepicker-widget .btn[data-action=incrementMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Increment Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=decrementHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Decrement Hours"}.bootstrap-datetimepicker-widget .btn[data-action=decrementMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Decrement Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=showHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Show Hours"}.bootstrap-datetimepicker-widget .btn[data-action=showMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Show Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=togglePeriod]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Toggle AM/PM"}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget .picker-switch::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Toggle Date and Time Screens"}.bootstrap-datetimepicker-widget .picker-switch td{padding:0;margin:0;height:auto;width:auto;line-height:inherit}.bootstrap-datetimepicker-widget .picker-switch td span{line-height:2.5;height:2.5em;width:100%}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget td,.bootstrap-datetimepicker-widget th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget th.picker-switch{width:145px}.bootstrap-datetimepicker-widget th.disabled,.bootstrap-datetimepicker-widget th.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget th.prev::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Previous Month"}.bootstrap-datetimepicker-widget th.next::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Next Month"}.bootstrap-datetimepicker-widget thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget thead tr:first-child th:hover{background:#eee}.bootstrap-datetimepicker-widget td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget td.cw{font-size:.8em;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget td.day:hover,.bootstrap-datetimepicker-widget td.hour:hover,.bootstrap-datetimepicker-widget td.minute:hover,.bootstrap-datetimepicker-widget td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget td.old,.bootstrap-datetimepicker-widget td.new{color:#777}.bootstrap-datetimepicker-widget td.today{position:relative}.bootstrap-datetimepicker-widget td.today:before{content:'';display:inline-block;border-left:7px solid transparent;border-bottom:7px solid #428bca;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget td.active,.bootstrap-datetimepicker-widget td.active:hover{background-color:#428bca;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget td.disabled,.bootstrap-datetimepicker-widget td.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget td span:hover{background:#eee}.bootstrap-datetimepicker-widget td span.active{background-color:#428bca;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget td span.old{color:#777}.bootstrap-datetimepicker-widget td span.disabled,.bootstrap-datetimepicker-widget td span.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget.usetwentyfour td.hour{height:27px;line-height:27px}.input-group.date .input-group-addon{cursor:pointer}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0} -------------------------------------------------------------------------------- /css/dataTables.bootstrap.css: -------------------------------------------------------------------------------- 1 | div.dataTables_length label { 2 | font-weight: normal; 3 | text-align: left; 4 | white-space: nowrap; 5 | } 6 | 7 | div.dataTables_length select { 8 | width: 75px; 9 | display: inline-block; 10 | } 11 | 12 | div.dataTables_filter { 13 | text-align: right; 14 | } 15 | 16 | div.dataTables_filter label { 17 | font-weight: normal; 18 | white-space: nowrap; 19 | text-align: left; 20 | } 21 | 22 | div.dataTables_filter input { 23 | margin-left: 0.5em; 24 | display: inline-block; 25 | } 26 | 27 | div.dataTables_info { 28 | padding-top: 8px; 29 | white-space: nowrap; 30 | } 31 | 32 | div.dataTables_paginate { 33 | margin: 0; 34 | white-space: nowrap; 35 | text-align: right; 36 | } 37 | 38 | div.dataTables_paginate ul.pagination { 39 | margin: 2px 0; 40 | white-space: nowrap; 41 | } 42 | 43 | @media screen and (max-width: 767px) { 44 | div.dataTables_length, 45 | div.dataTables_filter, 46 | div.dataTables_info, 47 | div.dataTables_paginate { 48 | text-align: center; 49 | } 50 | } 51 | 52 | 53 | table.dataTable td, 54 | table.dataTable th { 55 | -webkit-box-sizing: content-box; 56 | -moz-box-sizing: content-box; 57 | box-sizing: content-box; 58 | } 59 | 60 | 61 | table.dataTable { 62 | clear: both; 63 | margin-top: 6px !important; 64 | margin-bottom: 6px !important; 65 | max-width: none !important; 66 | } 67 | 68 | table.dataTable thead .sorting, 69 | table.dataTable thead .sorting_asc, 70 | table.dataTable thead .sorting_desc, 71 | table.dataTable thead .sorting_asc_disabled, 72 | table.dataTable thead .sorting_desc_disabled { 73 | cursor: pointer; 74 | position: relative; 75 | } 76 | 77 | table.dataTable thead .sorting:after, 78 | table.dataTable thead .sorting_asc:after, 79 | table.dataTable thead .sorting_desc:after { 80 | position: absolute; 81 | top: 8px; 82 | right: 8px; 83 | display: block; 84 | font-family: 'Glyphicons Halflings'; 85 | opacity: 0.5; 86 | } 87 | table.dataTable thead .sorting:after { 88 | opacity: 0.2; 89 | content: "\e150"; /* sort */ 90 | } 91 | table.dataTable thead .sorting_asc:after { 92 | content: "\e155"; /* sort-by-attributes */ 93 | } 94 | table.dataTable thead .sorting_desc:after { 95 | content: "\e156"; /* sort-by-attributes-alt */ 96 | } 97 | 98 | table.dataTable thead .sorting_asc_disabled:after, 99 | table.dataTable thead .sorting_desc_disabled:after { 100 | color: #eee; 101 | } 102 | 103 | table.dataTable thead > tr > th { 104 | padding-left: 8px; 105 | padding-right: 30px; 106 | } 107 | 108 | table.dataTable th:active { 109 | outline: none; 110 | } 111 | 112 | /* Scrolling */ 113 | div.dataTables_scrollHead table { 114 | margin-bottom: 0 !important; 115 | border-bottom-left-radius: 0; 116 | border-bottom-right-radius: 0; 117 | } 118 | 119 | div.dataTables_scrollHead table thead tr:last-child th:first-child, 120 | div.dataTables_scrollHead table thead tr:last-child td:first-child { 121 | border-bottom-left-radius: 0 !important; 122 | border-bottom-right-radius: 0 !important; 123 | } 124 | 125 | div.dataTables_scrollBody table { 126 | border-top: none; 127 | margin-top: 0 !important; 128 | margin-bottom: 0 !important; 129 | } 130 | 131 | div.dataTables_scrollBody tbody tr:first-child th, 132 | div.dataTables_scrollBody tbody tr:first-child td { 133 | border-top: none; 134 | } 135 | 136 | div.dataTables_scrollFoot table { 137 | margin-top: 0 !important; 138 | border-top: none; 139 | } 140 | 141 | /* Frustratingly the border-collapse:collapse used by Bootstrap makes the column 142 | width calculations when using scrolling impossible to align columns. We have 143 | to use separate 144 | */ 145 | table.table-bordered.dataTable { 146 | border-collapse: separate !important; 147 | } 148 | table.table-bordered thead th, 149 | table.table-bordered thead td { 150 | border-left-width: 0; 151 | border-top-width: 0; 152 | } 153 | table.table-bordered tbody th, 154 | table.table-bordered tbody td { 155 | border-left-width: 0; 156 | border-bottom-width: 0; 157 | } 158 | table.table-bordered th:last-child, 159 | table.table-bordered td:last-child { 160 | border-right-width: 0; 161 | } 162 | div.dataTables_scrollHead table.table-bordered { 163 | border-bottom-width: 0; 164 | } 165 | 166 | 167 | 168 | 169 | /* 170 | * TableTools styles 171 | */ 172 | .table.dataTable tbody tr.active td, 173 | .table.dataTable tbody tr.active th { 174 | background-color: #08C; 175 | color: white; 176 | } 177 | 178 | .table.dataTable tbody tr.active:hover td, 179 | .table.dataTable tbody tr.active:hover th { 180 | background-color: #0075b0 !important; 181 | } 182 | 183 | .table.dataTable tbody tr.active th > a, 184 | .table.dataTable tbody tr.active td > a { 185 | color: white; 186 | } 187 | 188 | .table-striped.dataTable tbody tr.active:nth-child(odd) td, 189 | .table-striped.dataTable tbody tr.active:nth-child(odd) th { 190 | background-color: #017ebc; 191 | } 192 | 193 | table.DTTT_selectable tbody tr { 194 | cursor: pointer; 195 | } 196 | 197 | div.DTTT .btn:hover { 198 | text-decoration: none !important; 199 | } 200 | 201 | ul.DTTT_dropdown.dropdown-menu { 202 | z-index: 2003; 203 | } 204 | 205 | ul.DTTT_dropdown.dropdown-menu a { 206 | color: #333 !important; /* needed only when demo_page.css is included */ 207 | } 208 | 209 | ul.DTTT_dropdown.dropdown-menu li { 210 | position: relative; 211 | } 212 | 213 | ul.DTTT_dropdown.dropdown-menu li:hover a { 214 | background-color: #0088cc; 215 | color: white !important; 216 | } 217 | 218 | div.DTTT_collection_background { 219 | z-index: 2002; 220 | } 221 | 222 | /* TableTools information display */ 223 | div.DTTT_print_info { 224 | position: fixed; 225 | top: 50%; 226 | left: 50%; 227 | width: 400px; 228 | height: 150px; 229 | margin-left: -200px; 230 | margin-top: -75px; 231 | text-align: center; 232 | color: #333; 233 | padding: 10px 30px; 234 | opacity: 0.95; 235 | 236 | background-color: white; 237 | border: 1px solid rgba(0, 0, 0, 0.2); 238 | border-radius: 6px; 239 | 240 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); 241 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); 242 | } 243 | 244 | div.DTTT_print_info h6 { 245 | font-weight: normal; 246 | font-size: 28px; 247 | line-height: 28px; 248 | margin: 1em; 249 | } 250 | 251 | div.DTTT_print_info p { 252 | font-size: 14px; 253 | line-height: 20px; 254 | } 255 | 256 | div.dataTables_processing { 257 | position: absolute; 258 | top: 50%; 259 | left: 50%; 260 | width: 100%; 261 | height: 60px; 262 | margin-left: -50%; 263 | margin-top: -25px; 264 | padding-top: 20px; 265 | padding-bottom: 20px; 266 | text-align: center; 267 | font-size: 1.2em; 268 | background-color: white; 269 | background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0))); 270 | background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); 271 | background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); 272 | background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); 273 | background: -o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); 274 | background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); 275 | } 276 | 277 | 278 | 279 | /* 280 | * FixedColumns styles 281 | */ 282 | div.DTFC_LeftHeadWrapper table, 283 | div.DTFC_LeftFootWrapper table, 284 | div.DTFC_RightHeadWrapper table, 285 | div.DTFC_RightFootWrapper table, 286 | table.DTFC_Cloned tr.even { 287 | background-color: white; 288 | margin-bottom: 0; 289 | } 290 | 291 | div.DTFC_RightHeadWrapper table , 292 | div.DTFC_LeftHeadWrapper table { 293 | border-bottom: none !important; 294 | margin-bottom: 0 !important; 295 | border-top-right-radius: 0 !important; 296 | border-bottom-left-radius: 0 !important; 297 | border-bottom-right-radius: 0 !important; 298 | } 299 | 300 | div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child, 301 | div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child, 302 | div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child, 303 | div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child { 304 | border-bottom-left-radius: 0 !important; 305 | border-bottom-right-radius: 0 !important; 306 | } 307 | 308 | div.DTFC_RightBodyWrapper table, 309 | div.DTFC_LeftBodyWrapper table { 310 | border-top: none; 311 | margin: 0 !important; 312 | } 313 | 314 | div.DTFC_RightBodyWrapper tbody tr:first-child th, 315 | div.DTFC_RightBodyWrapper tbody tr:first-child td, 316 | div.DTFC_LeftBodyWrapper tbody tr:first-child th, 317 | div.DTFC_LeftBodyWrapper tbody tr:first-child td { 318 | border-top: none; 319 | } 320 | 321 | div.DTFC_RightFootWrapper table, 322 | div.DTFC_LeftFootWrapper table { 323 | border-top: none; 324 | margin-top: 0 !important; 325 | } 326 | 327 | 328 | /* 329 | * FixedHeader styles 330 | */ 331 | div.FixedHeader_Cloned table { 332 | margin: 0 !important 333 | } 334 | 335 | -------------------------------------------------------------------------------- /css/img/details_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlnet/xapi-statement-viewer/3d18472feec00445257bab0c22480c06fd1c2367/css/img/details_close.png -------------------------------------------------------------------------------- /css/img/details_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlnet/xapi-statement-viewer/3d18472feec00445257bab0c22480c06fd1c2367/css/img/details_open.png -------------------------------------------------------------------------------- /css/jquery.dataTables.min.css: -------------------------------------------------------------------------------- 1 | table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead th,table.dataTable thead td{padding:10px 18px;border-bottom:1px solid #111}table.dataTable thead th:active,table.dataTable thead td:active{outline:none}table.dataTable tfoot th,table.dataTable tfoot td{padding:10px 18px 6px 18px;border-top:1px solid #111}table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting{cursor:pointer;*cursor:hand}table.dataTable thead .sorting{background:url("../images/sort_both.png") no-repeat center right}table.dataTable thead .sorting_asc{background:url("../images/sort_asc.png") no-repeat center right}table.dataTable thead .sorting_desc{background:url("../images/sort_desc.png") no-repeat center right}table.dataTable thead .sorting_asc_disabled{background:url("../images/sort_asc_disabled.png") no-repeat center right}table.dataTable thead .sorting_desc_disabled{background:url("../images/sort_desc_disabled.png") no-repeat center right}table.dataTable tbody tr{background-color:#fff}table.dataTable tbody tr.selected{background-color:#b0bed9}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border tbody th,table.dataTable.row-border tbody td,table.dataTable.display tbody th,table.dataTable.display tbody td{border-top:1px solid #ddd}table.dataTable.row-border tbody tr:first-child th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display tbody tr:first-child th,table.dataTable.display tbody tr:first-child td{border-top:none}table.dataTable.cell-border tbody th,table.dataTable.cell-border tbody td{border-top:1px solid #ddd;border-right:1px solid #ddd}table.dataTable.cell-border tbody tr th:first-child,table.dataTable.cell-border tbody tr td:first-child{border-left:1px solid #ddd}table.dataTable.cell-border tbody tr:first-child th,table.dataTable.cell-border tbody tr:first-child td{border-top:none}table.dataTable.stripe tbody tr.odd,table.dataTable.display tbody tr.odd{background-color:#f9f9f9}table.dataTable.stripe tbody tr.odd.selected,table.dataTable.display tbody tr.odd.selected{background-color:#abb9d3}table.dataTable.hover tbody tr:hover,table.dataTable.hover tbody tr.odd:hover,table.dataTable.hover tbody tr.even:hover,table.dataTable.display tbody tr:hover,table.dataTable.display tbody tr.odd:hover,table.dataTable.display tbody tr.even:hover{background-color:#f5f5f5}table.dataTable.hover tbody tr:hover.selected,table.dataTable.hover tbody tr.odd:hover.selected,table.dataTable.hover tbody tr.even:hover.selected,table.dataTable.display tbody tr:hover.selected,table.dataTable.display tbody tr.odd:hover.selected,table.dataTable.display tbody tr.even:hover.selected{background-color:#a9b7d1}table.dataTable.order-column tbody tr>.sorting_1,table.dataTable.order-column tbody tr>.sorting_2,table.dataTable.order-column tbody tr>.sorting_3,table.dataTable.display tbody tr>.sorting_1,table.dataTable.display tbody tr>.sorting_2,table.dataTable.display tbody tr>.sorting_3{background-color:#f9f9f9}table.dataTable.order-column tbody tr.selected>.sorting_1,table.dataTable.order-column tbody tr.selected>.sorting_2,table.dataTable.order-column tbody tr.selected>.sorting_3,table.dataTable.display tbody tr.selected>.sorting_1,table.dataTable.display tbody tr.selected>.sorting_2,table.dataTable.display tbody tr.selected>.sorting_3{background-color:#acbad4}table.dataTable.display tbody tr.odd>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd>.sorting_1{background-color:#f1f1f1}table.dataTable.display tbody tr.odd>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd>.sorting_2{background-color:#f3f3f3}table.dataTable.display tbody tr.odd>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd>.sorting_3{background-color:#f5f5f5}table.dataTable.display tbody tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_1{background-color:#a6b3cd}table.dataTable.display tbody tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_2{background-color:#a7b5ce}table.dataTable.display tbody tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_3{background-color:#a9b6d0}table.dataTable.display tbody tr.even>.sorting_1,table.dataTable.order-column.stripe tbody tr.even>.sorting_1{background-color:#f9f9f9}table.dataTable.display tbody tr.even>.sorting_2,table.dataTable.order-column.stripe tbody tr.even>.sorting_2{background-color:#fbfbfb}table.dataTable.display tbody tr.even>.sorting_3,table.dataTable.order-column.stripe tbody tr.even>.sorting_3{background-color:#fdfdfd}table.dataTable.display tbody tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_1{background-color:#acbad4}table.dataTable.display tbody tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_2{background-color:#adbbd6}table.dataTable.display tbody tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.display tbody tr.odd:hover>.sorting_1,table.dataTable.display tbody tr.even:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr.odd:hover>.sorting_1,table.dataTable.order-column.hover tbody tr.even:hover>.sorting_1{background-color:#eaeaea}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.display tbody tr.odd:hover>.sorting_2,table.dataTable.display tbody tr.even:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr.odd:hover>.sorting_2,table.dataTable.order-column.hover tbody tr.even:hover>.sorting_2{background-color:#ebebeb}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.display tbody tr.odd:hover>.sorting_3,table.dataTable.display tbody tr.even:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr.odd:hover>.sorting_3,table.dataTable.order-column.hover tbody tr.even:hover>.sorting_3{background-color:#eee}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.display tbody tr.odd:hover.selected>.sorting_1,table.dataTable.display tbody tr.even:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr.odd:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr.even:hover.selected>.sorting_1{background-color:#a1aec7}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.display tbody tr.odd:hover.selected>.sorting_2,table.dataTable.display tbody tr.even:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr.odd:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr.even:hover.selected>.sorting_2{background-color:#a2afc8}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.display tbody tr.odd:hover.selected>.sorting_3,table.dataTable.display tbody tr.even:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr.odd:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr.even:hover.selected>.sorting_3{background-color:#a4b2cb}table.dataTable.no-footer{border-bottom:1px solid #111}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable.compact thead th,table.dataTable.compact thead td{padding:5px 9px}table.dataTable.compact tfoot th,table.dataTable.compact tfoot td{padding:5px 9px 3px 9px}table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px 5px}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable,table.dataTable th,table.dataTable td{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both;*zoom:1;zoom:1}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{margin-left:0.5em}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:0.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:0.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:0.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;*cursor:hand;color:#333 !important;border:1px solid transparent}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:#333 !important;border:1px solid #cacaca;background-color:#fff;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(100%, #dcdcdc));background:-webkit-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-moz-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-ms-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-o-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:linear-gradient(to bottom, #fff 0%, #dcdcdc 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:40px;margin-left:-50%;margin-top:-25px;padding-top:20px;text-align:center;font-size:1.2em;background-color:white;background:-webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0)));background:-webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%)}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:#333}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid #111}.dataTables_wrapper.no-footer div.dataTables_scrollHead table,.dataTables_wrapper.no-footer div.dataTables_scrollBody table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:0.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:0.5em}} 2 | -------------------------------------------------------------------------------- /css/prettify.min.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:700}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:700}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:700}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | :focus {outline:none !important;} /* remove dotted outlines in FF */ 2 | 3 | body { font-size: 140%; } 4 | 5 | table { 6 | table-layout:fixed; 7 | } 8 | tbody td { 9 | word-wrap:break-word !important; 10 | } 11 | td.details-control { 12 | background: url('img/details_open.png') no-repeat center center; 13 | cursor: pointer; 14 | } 15 | tr.shown td.details-control { 16 | background: url('img/details_close.png') no-repeat center center; 17 | } 18 | .table-bordered>tfoot>tr>th { 19 | border-left:0; 20 | border-bottom:0; 21 | } 22 | 23 | pre { 24 | font-size:10px; 25 | } 26 | 27 | .page-header i { 28 | color: #94D5F5; 29 | text-shadow: 1px 1px 1px #ccc; 30 | } 31 | 32 | .panel-heading.collapser h4 > a:after { 33 | font-family:'Glyphicons Halflings'; 34 | content:"\e114"; 35 | float: right; 36 | } 37 | .panel-heading.collapser h4 > a.collapsed:after { 38 | content:"\e080"; 39 | } 40 | #get-statements-with-search { 41 | position: relative; 42 | top: -3px; 43 | } 44 | [data-notify="progressbar"] { 45 | margin-bottom: 0px; 46 | position: absolute; 47 | bottom: 0px; 48 | left: 0px; 49 | width: 100%; 50 | height: 1px; 51 | } 52 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlnet/xapi-statement-viewer/3d18472feec00445257bab0c22480c06fd1c2367/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | xAPI Statement Viewer 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 29 | 30 |
31 |

Statement List Get Statements

32 |
33 | 34 | 35 |
36 |
37 |

38 |
39 |
40 |
41 | 42 |
43 | 44 |
45 | 46 | 49 |
50 | 51 |
52 | 53 | 57 |
58 | 59 |
60 | 61 |
62 | 63 |
64 | 65 | 66 |
67 | 68 |
69 | 70 |
71 | 72 |
73 | 74 | 75 |
76 | 77 |
78 | 79 | 84 |
85 | 86 |
87 | 88 |
89 | 90 |
91 | 92 | 93 |
94 | 95 |
96 | 97 | 102 |
103 | 104 |
105 | 106 |
107 | 108 |
109 | 110 | 111 |
112 | 113 |
114 | 115 |
116 | 117 |
118 | 119 | 120 |
121 | 122 | 123 |
124 | 125 | 126 |
127 | 128 |
129 | 130 |
131 | 132 |
133 | 134 |
135 | 136 | 137 | 138 | 139 |
140 |
141 | 142 |
143 | 144 |
145 | 146 | 147 | 148 | 149 |
150 |
151 | 152 |
153 | 154 | 155 |
156 | 157 |
158 | 159 |
160 | 161 |
162 | 163 | 164 |
165 | 166 |
167 | 168 |

169 | Clear Form 170 |

171 | 172 |
173 |
174 |
175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 |
TimestampActor NameVerbObject NameObject TypeAuthority Name
TimestampActor NameVerbObject NameObject TypeAuthority Name
201 | 202 |
203 | Get More 204 |
205 | 206 |
207 |
208 | 209 |
210 |
211 |

212 |
213 |
214 |
215 | 216 |
217 | 218 |
219 | 220 |
221 | 222 |
223 | 224 | 225 |
226 |
227 | 228 |
229 | 230 |
231 | 232 | 233 |
234 |
235 | 236 |
237 | 238 |
239 | 240 | 241 |
242 |
243 | 244 |
245 |

246 | Reset to Defaults 247 | Save Auth 248 |

249 |
250 | 251 |
252 | 253 |
254 | 255 |
256 |
257 |
258 | 259 |

About

260 |
261 |

This tool retrieves and displays statements from an LRS. xAPI Statement Viewer is free and open-source, check it out on github.

262 |

Experiment with creating statements like these with xAPI Lab

263 |

Tip: Open your browser's developer tools (F12) to see more info in the console.

264 |
265 | 266 | 272 | 273 |
274 | 275 | 276 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | require.config({ 2 | baseUrl: 'js/lib', 3 | 4 | paths: { 5 | jquery: 'jquery', 6 | datatables: 'jquery.dataTables.min', 7 | cookie: 'jquery.cookie', 8 | dtbootstrap: 'dataTables.bootstrap', 9 | transition: 'transition', 10 | collapse: 'collapse', 11 | prettify: 'prettify.min', 12 | moment: 'moment.min', 13 | datetimepicker: 'bootstrap-datetimepicker.min', 14 | notify: 'bootstrap-notify.min', 15 | xapiwrapper: 'xapiwrapper.min', 16 | //store: 'store+json2.min', 17 | }, 18 | shim: { 19 | datatables: { 20 | deps: ['jquery'] 21 | }, 22 | cookie: { 23 | deps: ['jquery'] 24 | }, 25 | dtbootstrap: { 26 | deps: ['datatables'] 27 | }, 28 | transition: { 29 | deps: ['dtbootstrap'] 30 | }, 31 | collapse: { 32 | deps: ['dtbootstrap'] 33 | }, 34 | datetimepicker: { 35 | deps: ['dtbootstrap', 'moment'] 36 | }, 37 | notify: { 38 | deps: ['dtbootstrap'] 39 | } 40 | } 41 | }); 42 | 43 | requirejs(['../app/main']); 44 | -------------------------------------------------------------------------------- /js/app/main.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var $ = require('jquery'); 3 | 4 | require(['xapiwrapper', 'datatables', 'cookie', 'transition', 'collapse', 'prettify', 'datetimepicker', 'notify'], function() { 5 | 6 | $(document).ready(function() { 7 | // get an array with all querystring values 8 | // example: var valor = getUrlVars()["valor"]; 9 | function getUrlVars() { 10 | var vars = [], hash; 11 | var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); 12 | for (var i = 0; i < hashes.length; i++) { 13 | hash = hashes[i].split('='); 14 | vars.push(hash[0]); 15 | vars[hash[0]] = hash[1]; 16 | } 17 | return vars; 18 | } 19 | 20 | // shim for old-style Base64 lib 21 | function fromBase64(text){ 22 | if(CryptoJS && CryptoJS.enc.Base64) 23 | return CryptoJS.enc.Base64.parse(text).toString(CryptoJS.enc.Latin1); 24 | else 25 | return Base64.decode(text); 26 | } 27 | 28 | // Override any credentials put in the XAPIWrapper.js 29 | function resetConfig() { 30 | $("#endpoint").val("https://lrs.adlnet.gov/xapi/"); 31 | $("#username").val("xapi-tools"); 32 | $("#password").val("xapi-tools"); 33 | saveConfig(); 34 | setupConfig(); 35 | // Populate the table 36 | getStatementsWithSearch(null, 0); 37 | } 38 | 39 | function saveConfig() { 40 | if (!store.enabled) { 41 | console.log("your browser does not support localstorage, cannot save your auth"); 42 | } else { 43 | var endpoint = $("#endpoint").val(); 44 | var user = $("#username").val(); 45 | var password = $("#password").val(); 46 | store.set('conf', { "endpoint": endpoint, "user": user, "password": password}); 47 | } 48 | setupConfig(); 49 | } 50 | 51 | function setupConfig() { 52 | var qs = getUrlVars(); 53 | if (qs['endpoint'] || qs['auth']) { 54 | if (qs['endpoint']) { $("#endpoint").val(qs['endpoint']); } 55 | if (qs['auth']) { 56 | var auth = fromBase64(qs['auth'].replace('Basic%20','')).split(':'); 57 | $("#username").val(auth[0]); 58 | $("#password").val(auth[1]); 59 | } 60 | } else if (store.enabled && store.get("conf")) { 61 | var config = store.get('conf'); 62 | $("#endpoint").val(config.endpoint); 63 | $("#username").val(config.user); 64 | $("#password").val(config.password); 65 | var conf = { 66 | "endpoint" : config.endpoint, 67 | "auth" : "Basic " + toBase64(config.user + ":" + config.password), 68 | }; 69 | } else { 70 | // get LRS credentials from user interface 71 | var endpoint = $("#endpoint").val(); 72 | var user = $("#username").val(); 73 | var password = $("#password").val(); 74 | 75 | var conf = { 76 | "endpoint" : endpoint, 77 | "auth" : "Basic " + toBase64(user + ":" + password), 78 | }; 79 | } 80 | 81 | ADL.XAPIWrapper.changeConfig(conf); 82 | } 83 | 84 | // Configure xAPIWrapper and save credentials 85 | setupConfig(); 86 | 87 | var notificationSettings = { 88 | animate: { 89 | enter: 'animated fadeInUp', 90 | exit: 'animated fadeOutDown' 91 | }, 92 | type: "success", 93 | placement: { 94 | from: "bottom", 95 | align: "right" 96 | }, 97 | }; 98 | 99 | var notificationErrorSettings = jQuery.extend(true, {}, notificationSettings); 100 | notificationErrorSettings.type = "danger"; 101 | 102 | var dateTimeSettings = { 103 | // format: 'YYYY-MM-DDTHH:mm:ss', // ISO 8601 104 | showTodayButton: true, 105 | showClear: true 106 | }; 107 | 108 | gmore = null; 109 | 110 | $("#reset-search").click(function(e) { 111 | $("#search-predefined-verb").val(""); 112 | $("#search-verb-sort").val(""); 113 | $("#search-user-verb-id").val(""); 114 | $("#search-actor-email").val(""); 115 | $("#search-related-agents").val(""); 116 | $("#search-activity-id").val(""); 117 | $("#search-related-activities").val(""); 118 | $("#search-registration-id").val(""); 119 | $("#search-statement-id").val(""); 120 | $("#search-voided-statement-id").val(""); 121 | $("#search-statements-since-date input").val(""); 122 | $("#search-statements-until-date input").val(""); 123 | $("#search-limit").val(""); 124 | e.preventDefault(); 125 | }); 126 | 127 | // Handle XAPIWrapper XHR Errors 128 | ADL.xhrRequestOnError = function(xhr, method, url, callback, callbackargs) { 129 | //console.log(xhr); 130 | $.notify({ title: "Status " + xhr.status + " " + xhr.statusText + ": ", message: xhr.response }, notificationErrorSettings); 131 | }; 132 | 133 | var table = $('#statement-list').DataTable({ 134 | "columns": [ 135 | { width: "10%", data: "timestamp", "defaultContent": "" }, 136 | { width: "17%", data: "actor.name", "defaultContent": "" }, 137 | { width: "13%", data: function (row, type, val, meta){ 138 | if ('display' in row.verb){ 139 | if (!('en-US' in row.verb.display)){ 140 | if ('en' in row.verb.display){ 141 | return row.verb.display.en; 142 | } 143 | } 144 | return row.verb.display['en-US']; 145 | } 146 | }, "defaultContent": "" }, 147 | { width: "28%", data: "object.definition.name.en-US", "defaultContent": "" }, 148 | { width: "12%", data: "object.objectType", "defaultContent": "" }, 149 | { width: "15%", data: "authority.name", "defaultContent": "" }, 150 | { 151 | width: "5%", 152 | "className": 'details-control', 153 | "orderable": false, 154 | "data": null, 155 | "defaultContent": '' 156 | } 157 | ], 158 | "rowCallback": function( row, data ) { 159 | var display = moment(data.timestamp); 160 | $('td:eq(0)', row).html( '' + display.fromNow() + '' ); 161 | if (data.actor.hasOwnProperty('account') && data.actor.account.hasOwnProperty('name')) { $('td:eq(1)', row).html( data.actor.account.name ); } 162 | else if (data.actor.hasOwnProperty('name') == false && data.actor.hasOwnProperty('mbox')) { $('td:eq(1)', row).html( data.actor.mbox.replace('mailto:','') ); } 163 | if (data.object.hasOwnProperty('name')) { $('td:eq(3)', row).html( data.object.name ); } 164 | else if (data.object.hasOwnProperty('definition') && data.object.definition.hasOwnProperty('name') == false && data.object.hasOwnProperty('id')) { $('td:eq(3)', row).html( data.object.id ); } 165 | else if (data.object.hasOwnProperty('id') && data.object.hasOwnProperty('definition') == false ) { $('td:eq(3)', row).html( data.object.id ); } 166 | }, 167 | "order": [[0, 'desc']], 168 | "pageLength": 25 169 | }); 170 | 171 | // Retreive statements from the LRS 172 | function getStatementsWithSearch(more, curPage) { 173 | var verbSort = $("#search-verb-sort").val(); 174 | var verbId = $("#search-user-verb-id").val(); 175 | var actor = $("#search-actor").val(); 176 | var relatedAgents = $("#search-related-agents").val(); 177 | var activityId = $("#search-activity-id").val(); 178 | var relatedActivities = $("#search-related-activities").val(); 179 | var registrationId = $("#search-registration-id").val(); 180 | var statementId = $("#search-statement-id").val(); 181 | var voidedStatementId = $("#search-voided-statement-id").val(); 182 | var sinceDate = $("#search-statements-since-date input").val(); 183 | var untilDate = $("#search-statements-until-date input").val(); 184 | var limit = $("#search-limit").val(); 185 | 186 | // Build Search 187 | var search = ADL.XAPIWrapper.searchParams(); 188 | if (verbId != "") { search['verb'] = verbId; } 189 | if (verbSort != "") { search['ascending'] = verbSort; } 190 | if (actor != "") { search['agent'] = actor; } 191 | if (relatedAgents != "") { search['related_agents'] = relatedAgents; } 192 | if (activityId != "") { search['activity'] = activityId; } 193 | if (relatedActivities != "") { search['related_activities'] = relatedActivities; } 194 | if (registrationId != "") { search['registration'] = registrationId; } 195 | if (statementId != "") { search['statementId'] = statementId; } 196 | if (voidedStatementId != "") { search['voidedStatementId'] = voidedStatementId; } 197 | if (sinceDate != "") { search['since'] = sinceDate; } 198 | if (untilDate != "") { search['until'] = untilDate; } 199 | if (limit != "") { search['limit'] = limit; } 200 | //console.log(search); 201 | 202 | // Put together the xAPI Query 203 | var urlparams = new Array(); 204 | var url = "https://lrs.adlnet.gov/xapi/statements"; 205 | 206 | for (s in search) { 207 | urlparams.push(s + "=" + encodeURIComponent(search[s])); 208 | } 209 | if (urlparams.length > 0) 210 | url = url + "?" + urlparams.join("&"); 211 | 212 | //console.log(url); 213 | $("#xapi-query").val(url); 214 | 215 | ADL.XAPIWrapper.getStatements(search, more, function(r) { 216 | //console.log(r); 217 | var response = $.parseJSON(r.response); 218 | 219 | // update the status in the HTML 220 | if (r.status == 200) { 221 | 222 | // Handle case where only a single statement is returned 223 | // using statementId or voidedStatementId 224 | if (response.hasOwnProperty('statements')) { 225 | var stmts = response.statements; 226 | var length = stmts.length; 227 | } else { 228 | var stmt = response; 229 | var length = 1; 230 | } 231 | 232 | $.notify({ message: "Status " + r.status + " " + r.statusText }, notificationSettings); 233 | 234 | if (response.more != "") { 235 | gmore = response.more; 236 | } else { 237 | gmore = null; 238 | } 239 | //console.log(gmore); 240 | 241 | if (length > 0) { 242 | if (stmt) { 243 | var stmts = $.parseJSON("[" + JSON.stringify(stmt) + "]"); 244 | } else { 245 | var stmts = $.parseJSON(JSON.stringify(stmts)); 246 | //console.log(stmts); 247 | } 248 | } 249 | 250 | $('#statement-list').DataTable().rows.add(stmts).draw(); 251 | $('#statement-list').DataTable().page(curPage).draw(false); 252 | prettyPrint(); 253 | } 254 | }); 255 | } 256 | 257 | /* Formatting function for row details - modify as you need */ 258 | function format ( d ) { 259 | // `d` is the original data object for the row 260 | return '
'+
261 |           JSON.stringify(d, null, 2)+
262 |           '
'; 263 | } 264 | 265 | // Add event listener for opening and closing details 266 | $('#statement-list tbody').on('click', 'td.details-control', function () { 267 | var tr = $(this).closest('tr'); 268 | var row = table.row( tr ); 269 | 270 | if ( row.child.isShown() ) { 271 | // This row is already open - close it 272 | row.child.hide(); 273 | tr.removeClass('shown'); 274 | } 275 | else { 276 | // Open this row 277 | row.child( format(row.data()) ).show(); 278 | tr.addClass('shown'); 279 | PR.prettyPrint(); 280 | } 281 | }); 282 | 283 | // save panel state 284 | $("#query-options").on('shown.bs.collapse', function () { 285 | var active = $("#query-options.in").attr('id'); 286 | $.cookie('activePanel', active); 287 | }); 288 | $("#query-options").on('hidden.bs.collapse', function () { 289 | $.removeCookie('activePanel'); 290 | }); 291 | var last = $.cookie('activePanel'); 292 | if (last != null) { 293 | $("#query-options.panel-collapse").removeClass('in'); 294 | $("#" + last).addClass("in"); 295 | } 296 | 297 | $(".collapser a").click(function (e) { e.preventDefault(); }); 298 | 299 | // Populate the predefined verbs dropdown 300 | for (var key in ADL.verbs) { 301 | var $options = $("#search-predefined-verb"); 302 | if (ADL.verbs.hasOwnProperty(key)) { 303 | $options.append($("