├── doc └── screenshot.png ├── .gitignore ├── process └── rating_check_recola.m ├── static ├── css │ ├── images │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_454545_256x240.png │ │ ├── ui-icons_888888_256x240.png │ │ ├── ui-icons_cd0a0a_256x240.png │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png │ ├── style.css │ └── jquery-ui-1.8.18.custom.css └── js │ └── jquery-1.7.2.min.js ├── config.coffee ├── package.json ├── license_annemo.txt ├── README.md ├── Cakefile └── emotions.coffee /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/doc/screenshot.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | results.csv 3 | results/ 4 | videos/ 5 | node_modules 6 | video.coffee -------------------------------------------------------------------------------- /process/rating_check_recola.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/process/rating_check_recola.m -------------------------------------------------------------------------------- /static/css/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /static/css/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /static/css/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /static/css/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /static/css/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilyabo/annemo/HEAD/static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /config.coffee: -------------------------------------------------------------------------------- 1 | @include = -> 2 | 3 | # location of the videos to show in the sidebar 4 | location: "http://myserver.com/myvideos/" 5 | 6 | # list of the videos shown in the sidebar 7 | files: [ 8 | "video1.avi", 9 | "video2.avi", 10 | ] 11 | 12 | # list of user ids who will be granted access, 13 | # you can then send links with these ids to the annotators. 14 | # these ids can be anything 15 | users: [ 16 | "8935", "7656", "9234" 17 | ] 18 | 19 | 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emotions", 3 | "version": "0.0.1", 4 | "description": "Emotion recognition experiments", 5 | "main": "./emotions.coffee", 6 | "repository": { 7 | "type": "git", 8 | "url": "http://github.com/ilyabo/aiddata.git" 9 | }, 10 | "dependencies": { 11 | "eco": "1.1.0-rc-3", 12 | "zappa": "0.3.3", 13 | "forever": "0.9.2", 14 | "dateformat": "1.0.2-1.2.3", 15 | "express": "2.5.9" 16 | }, 17 | "engines": { "node": ">= 0.4.1 < 0.7.0" } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /license_annemo.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 ANNEMO - Author: Ilya Boyandin 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | the ANNEMO software (the Software) and associated documentation files, to use, 5 | copy and modify the Software for commercial or public research purposes, and to 6 | permit persons to whom the Software is furnished to do so, subject to the 7 | following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Annemo 2 | ====== 3 | 4 | A simplistic web app for annotating emotions in human speech video recordings. 5 | 6 |  7 | 8 | 9 | Installation and running 10 | ====== 11 | Install [Node.js 0.6.x](http://nodejs.org/dist/v0.6.16/docs/#) 12 | 13 | Then, install CoffeeScript: 14 | 15 | npm install -g coffee-script 16 | 17 | 18 | To download the project dependencies in the project directory run: 19 | 20 | npm install 21 | 22 | 23 | Then, configure the videos and the allowed user ids in [config.coffee](https://github.com/ilyabo/annemo/blob/master/config.coffee). 24 | 25 | 26 | To start the server run: 27 | 28 | cake forever-start 29 | 30 | Then, open in your browser [http://localhost:3001/?subject=8935](http://localhost:3001/?subject=8935) 31 | where 8935 is one of the valid user ids specified in your [config.coffee](https://github.com/ilyabo/annemo/blob/master/config.coffee). 32 | 33 | The annotation results will be saved in CSV files in results/ directory. 34 | 35 | To restart the server: 36 | 37 | cake forever-restart 38 | 39 | To stop: 40 | 41 | cake forever-stop 42 | 43 | -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | {spawn, exec} = require 'child_process' 2 | path = require 'path' 3 | 4 | app = "emotions" 5 | mainfile = "emotions.coffee" 6 | 7 | 8 | option '-e', '--environment [ENVIRONMENT_NAME]', 'set the environment for `restart`' 9 | 10 | task 'build', -> 11 | 12 | ### 13 | task 'restart', 'Restart #{app}', (options) -> 14 | invoke 'build' 15 | run 'PATH=/usr/bin:/usr/local/bin:/opt/local/bin && kill -9 `pgrep -f "coffee '+mainfile+'"`' 16 | run "coffee #{mainfile}" 17 | ### 18 | 19 | task 'start', "Start #{app}", (options) -> 20 | invoke 'build' 21 | run "coffee #{mainfile}" 22 | 23 | task 'stop', "Stop #{app}", (options) -> 24 | run 'PATH=/usr/bin:/usr/local/bin:/opt/local/bin && kill -9 `pgrep -f "coffee '+mainfile+'"`' 25 | 26 | 27 | task 'restart', "Restart #{app}", (options) -> 28 | invoke 'stop' 29 | invoke 'start' 30 | 31 | 32 | foreverBinary = "node_modules/forever/bin/forever" 33 | forever = (action, options) -> 34 | invoke 'build' 35 | options.environment or= 'production' 36 | run "NODE_ENV=#{options.environment} " + 37 | "#{foreverBinary} #{action} -c coffee " + 38 | " --sourceDir ./" + 39 | " -l #{app}.log "+ 40 | #" -o logs/#{app}.out "+ 41 | #" -e logs/#{app}.err "+ 42 | " -a" + # append logs 43 | " #{mainfile}" 44 | 45 | 46 | task 'forever-restart', (options) -> forever 'restart', options 47 | task 'forever-start', (options) -> forever 'start', options 48 | task 'forever-stop', (options) -> run "#{foreverBinary} stop -c coffee #{mainfile}" 49 | task 'forever-list', (options) -> run "#{foreverBinary} list" 50 | 51 | 52 | 53 | 54 | run = (args...) -> 55 | for a in args 56 | switch typeof a 57 | when 'string' then command = a 58 | when 'object' 59 | if a instanceof Array then params = a 60 | else options = a 61 | when 'function' then callback = a 62 | 63 | command += ' ' + params.join ' ' if params? 64 | cmd = spawn '/bin/sh', ['-c', command], options 65 | cmd.stdout.on 'data', (data) -> process.stdout.write data 66 | cmd.stderr.on 'data', (data) -> process.stderr.write data 67 | process.on 'SIGHUP', -> cmd.kill() 68 | cmd.on 'exit', (code) -> callback() if callback? and code is 0 69 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | body, h1, div { font-family:arial;} 2 | 3 | body { padding:20px;} 4 | 5 | #content { width:640px; } 6 | 7 | 8 | #slider { width:100%; } 9 | 10 | #startVideo { width:5em; } 11 | 12 | #startSubmit { width:100px; height:20px; margin-top:20px; } 13 | 14 | div.formelem { padding:10px;} 15 | 16 | #slider.arousal, #slider.valence { 17 | background: #6290e0; /* Old browsers */ 18 | background: -moz-linear-gradient(left, #6290e0 0%, #a8a8a8 51%, #bc3d27 100%); /* FF3.6+ */ 19 | background: -webkit-gradient(linear, left top, right top, color-stop(0%,#6290e0), color-stop(51%,#a8a8a8), color-stop(100%,#bc3d27)); /* Chrome,Safari4+ */ 20 | background: -webkit-linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* Chrome10+,Safari5.1+ */ 21 | background: -o-linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* Opera 11.10+ */ 22 | background: -ms-linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* IE10+ */ 23 | background: linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* W3C */ 24 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6290e0', endColorstr='#bc3d27',GradientType=1 ); /* IE6-9 */ 25 | } 26 | 27 | #dimension { width:100%; text-align:center; font-size:20px; font-weight:bold; margin-bottom:10px;} 28 | 29 | #labels { width:100%; padding:2px; } 30 | #labels .left { width:50%;text-align:left; display:inline-block;} 31 | #labels .right { width:50%;text-align:right; display:inline-block; } 32 | 33 | #buttonArea { width:100%; text-align:center; margin-top:20px; } 34 | 35 | .videolist {font-size:12px; list-style:none; padding-left:0;} 36 | .videolist li { padding:5px; padding-left:0px; } 37 | 38 | 39 | 40 | .prop { margin-bottom: 20px} 41 | .propLabel { margin-bottom:5px; font-weight: bold; text-align:center; width: 100% } 42 | .slider.social { 43 | width:640px; margin-top:30px 44 | background: #6290e0; /* Old browsers */ 45 | background: -moz-linear-gradient(left, #6290e0 0%, #a8a8a8 51%, #bc3d27 100%); /* FF3.6+ */ 46 | background: -webkit-gradient(linear, left top, right top, color-stop(0%,#6290e0), color-stop(51%,#a8a8a8), color-stop(100%,#bc3d27)); /* Chrome,Safari4+ */ 47 | background: -webkit-linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* Chrome10+,Safari5.1+ */ 48 | background: -o-linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* Opera 11.10+ */ 49 | background: -ms-linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* IE10+ */ 50 | background: linear-gradient(left, #6290e0 0%,#a8a8a8 51%,#bc3d27 100%); /* W3C */ 51 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6290e0', endColorstr='#bc3d27',GradientType=1 ); /* IE6-9 */ 52 | } 53 | 54 | #saveBut { font-size:1.5em; margin-top:20px; } -------------------------------------------------------------------------------- /emotions.coffee: -------------------------------------------------------------------------------- 1 | require('zappa').run 3001, -> 2 | 3 | fs = require("fs") 4 | path = require("path") 5 | dateFormat = require('dateformat') 6 | 7 | @use 'static': __dirname + '/static' 8 | 9 | video = @include './config' 10 | 11 | #resultsFile = fs.createWriteStream __dirname + '/results.csv', {'flags': 'a'} 12 | resultsDir = __dirname + "/results" 13 | 14 | mkdir = (dir) -> if !path.existsSync(dir) then fs.mkdirSync(dir, parseInt('0755', 8)) 15 | 16 | mkdir(resultsDir) 17 | 18 | 19 | @use 'bodyParser', 'methodOverride', @app.router, 'static' 20 | 21 | @get '/': -> 22 | unless @query.subject in video.users 23 | @send "Subject must be properly specified" 24 | @render "home" : { subject:@query.subject, layout: "frameset"} 25 | 26 | 27 | @view home: -> 28 | console.log @subject 29 | frame name:"menuFrame", src:"menu?subject=#{@subject}" 30 | frame id:"videoFrame", name:"videoFrame", src:"about:blank" 31 | 32 | 33 | 34 | @view frameset: -> 35 | doctype 5 36 | html -> 37 | head -> title @title 38 | frameset cols:"25%,*", -> @body 39 | 40 | 41 | @get '/menu': -> 42 | @render "menu": { videos : video.files, users : video.users, subject:@query.subject} 43 | 44 | 45 | @view menu: -> 46 | 47 | ### 48 | 49 | form action: "video", target:"videoFrame", -> 50 | div class:"formelem", -> 51 | span -> "Test subject: " 52 | select name: "subject", id:"subject", -> 53 | option value:"", -> "" 54 | for v in @users 55 | option -> v 56 | 57 | div class:"formelem", -> 58 | span -> "Dimension: " 59 | select name: "dim", id:"dim", -> 60 | option value:"", -> "" 61 | option -> "arousal" 62 | option -> "valence" 63 | div class:"formelem", -> 64 | span -> "Video to play: " 65 | select name: "video", id:"video", -> 66 | option value:"", -> "" 67 | for v in @videos 68 | option -> v 69 | ### 70 | 71 | 72 | div class:"formelem", -> 73 | ul class:"videolist", -> 74 | for v in @videos 75 | for dim in ["arousal", "valence"] 76 | li -> 77 | a href:"video?video=#{v}&dim=#{dim}&subject=#{@subject}", target:"videoFrame",-> dim + " - " + v 78 | li -> a href:"social?video=#{v}&subject=#{@subject}", target:"videoFrame", -> "social dimension annotation" 79 | li -> hr width:"100%" 80 | 81 | ### 82 | div class:"formelem", -> 83 | input id:"startSubmit", type:"submit", value:"Start" 84 | ### 85 | 86 | #script src: 'home.js' 87 | 88 | 89 | 90 | ### 91 | @coffee '/home.js': -> 92 | $ -> 93 | $(".videolist a").click -> 94 | if $("#subject").val().trim() is "" or $("#dimension").val() is "" 95 | alert("Please, fill in the form fields") 96 | return false 97 | return true 98 | ### 99 | 100 | 101 | 102 | @get '/social': -> 103 | if not (@query.subject in video.users) or (not @query.video?) 104 | @send "Subject, video must be properly specified" 105 | 106 | 107 | @render social: 108 | videoName: @query.video 109 | subject: @query.subject 110 | 111 | 112 | @view social: -> 113 | 114 | script src: 'social.js' 115 | 116 | script -> """ 117 | subject = "#{@subject.replace(/"/g, '\\"')}" 118 | videoName = "#{@videoName}" 119 | """ 120 | 121 | h1 -> "Social Interaction Dimensions Annotation" 122 | div -> "Video: #{@videoName}" 123 | 124 | div id:'content', -> 125 | div id:'propsToAnnotate',style:'margin-top:20px',-> 126 | div style:'margin:20px 0', -> "Please, annotate the following dimensions: " 127 | 128 | props = [ 129 | "Agreement", "Engagement", "Dominance", "Performance", "Rapport" 130 | ] 131 | 132 | for p in props 133 | div class:'prop',-> 134 | div class:'propLabel', -> p 135 | div class:'slider social', id:p 136 | div id:"labels", -> 137 | span class:"left", -> "very low" 138 | span class:"right", -> "very high" 139 | 140 | button id:'saveBut', -> "Save" 141 | 142 | 143 | 144 | 145 | @coffee '/social.js': -> 146 | $ -> 147 | $(".slider") 148 | .slider({ 149 | orientation: 'horizontal', 150 | min: -1, 151 | max: 1, 152 | value: 0, 153 | step:0.33 154 | }) 155 | 156 | 157 | $("#saveBut").click -> 158 | 159 | propVals = {} 160 | $(".slider").each (i, slider) -> 161 | propVals[$(slider).attr("id")] = $(slider).slider("option", "value") 162 | 163 | #console.log values 164 | 165 | 166 | $.ajax 167 | type: 'get' 168 | url: "save_social?subject=#{subject}&video=#{videoName}" 169 | dataType: 'json' 170 | data: propVals 171 | 172 | 173 | $("#propsToAnnotate").html("Thanks! Please, proceed to the next video.") 174 | 175 | 176 | 177 | 178 | @get '/video': -> 179 | if not (@query.subject in video.users) or (not @query.video?) or (not @query.dim?) 180 | @send "Subject, video, dim must be properly specified" 181 | 182 | @render video: 183 | video: video.location + @query.video 184 | videoName: @query.video 185 | subject: @query.subject 186 | dimension: @query.dim 187 | 188 | 189 | @view video: -> 190 | script src: 'video.js' 191 | 192 | script -> """ 193 | subject = "#{@subject.replace(/"/g, '\\"')}" 194 | video = "#{@video}" 195 | videoName = "#{@videoName}" 196 | dimension = "#{@dimension}" 197 | """ 198 | 199 | div id:"content", -> 200 | 201 | #div id:"buttonArea",-> 202 | # button id:"start", -> "Start" 203 | 204 | video id:"video", width:640, height:480, preload:"auto", controls:"controls", -> 205 | source src: @video 206 | 207 | #div id:"loadProgress" 208 | 209 | div id:"dimension", -> "#{@dimension}" 210 | 211 | div id:"slider", class:"#{@dimension}" 212 | 213 | div id:"labels", -> 214 | span class:"left", -> 215 | switch @dimension 216 | when "arousal" then "very passive" 217 | when "valence" then "very negative" 218 | 219 | span class:"right", -> 220 | switch @dimension 221 | when "arousal" then "very active" 222 | when "valence" then "very positive" 223 | 224 | 225 | @coffee '/video.js': -> 226 | $ -> 227 | $("#video").get(0).play() 228 | $("#video").delay(1000).get(0).pause() 229 | 230 | $("#video") 231 | .data("isPlaying", false) 232 | ### 233 | .on("progress", -> 234 | $("#loadProgress").html("Progress: " + $('#video').get(0).buffered.end(0) / $('#video').get(0).duration) 235 | ) 236 | ### 237 | 238 | 239 | buffer = [] 240 | maxBufferSize = 1 241 | 242 | sendBufferToServer = -> 243 | tosend = buffer 244 | buffer = [] 245 | $.ajax 246 | type: 'post' 247 | url: 'save_value?subject=' + subject 248 | dataType: 'json' 249 | data: 250 | buffer: tosend 251 | 252 | 253 | onValueChange = (e, ui) -> 254 | buffer.push 255 | clienttime: Date.now() 256 | subject: subject 257 | video: videoName 258 | dimension: dimension 259 | time: $("#video").get(0).currentTime 260 | value: ui.value 261 | playing: $("#video").data("isPlaying") 262 | 263 | if buffer.length >= maxBufferSize 264 | sendBufferToServer() 265 | 266 | 267 | $(document).mousemove (e) -> 268 | s = $("#slider") 269 | h = $(".ui-slider-handle", s) 270 | if h.hasClass("ui-state-focus") 271 | val = ((e.clientX - s.offset().left) / s.width()) * 2 - 1 272 | if val > 1 then val = 1 273 | if val < -1 then val = -1 274 | s.slider("option", "value", val) 275 | 276 | $("#slider") 277 | .slider({ 278 | orientation: 'horizontal', 279 | min: -1, 280 | max: 1, 281 | value: 0, 282 | step:0.01, 283 | slide: onValueChange, 284 | change: onValueChange 285 | }) 286 | 287 | $("#video").bind "ended", -> 288 | $(this).data("isPlaying", false) 289 | sendBufferToServer() 290 | 291 | ### 292 | $("#start").click -> 293 | v = $("#video") 294 | if not v.data("isPlaying") 295 | v.get(0).currentTime = 0 296 | v.data("isPlaying", true) 297 | .get(0).play() 298 | 299 | $(this).html("Pause") 300 | else 301 | v.data("isPlaying", false) 302 | .get(0).pause() 303 | 304 | $(this).html("Restart") 305 | ### 306 | 307 | 308 | 309 | q = (s) -> 310 | if (s.indexOf(",") >= 0) 311 | '"' + s.replace(/"/g, '\\"') + '"' 312 | else 313 | s 314 | 315 | 316 | saveCsv = (subj, csv, callback) -> 317 | resultsFile = fs.createWriteStream("#{resultsDir}/#{subj}.csv", {'flags': 'a'}) 318 | resultsFile.write csv, callback 319 | 320 | 321 | 322 | @post '/save_value': -> 323 | if not (@query.subject in video.users) 324 | @next(new Error "Subject must be properly specified") 325 | 326 | subj = @query.subject 327 | 328 | 329 | csv = "" 330 | for obj in @body.buffer 331 | formattedDate = q(dateFormat(Date.now(), "dddd, mmmm dS, yyyy, h:MM:ss TT")) 332 | csv = csv + formattedDate + "," + ((q(v) for k, v of obj).join(",") + "\n") 333 | 334 | saveCsv subj, csv, (err) => 335 | 336 | unless err? 337 | @send 338 | result: 'Ok' 339 | else 340 | @next(err) 341 | 342 | 343 | 344 | 345 | 346 | 347 | @get '/save_social': -> 348 | if not (@query.subject in video.users) or not (@query.video in video.files) 349 | @next(new Error "Subject, video must be properly specified") 350 | 351 | subj = @query.subject 352 | 353 | console.log @query.values 354 | 355 | csv = "Social," + ((q(v) for k, v of @query).join(",") + "\n") 356 | console.log @query 357 | 358 | saveCsv subj, csv, (err) => 359 | 360 | unless err? 361 | @send 362 | result: 'Ok' 363 | else 364 | @next(err) 365 | 366 | 367 | 368 | 369 | 370 | @view layout: -> 371 | doctype 5 372 | html -> 373 | head -> 374 | title @title 375 | link rel:"stylesheet", type:"text/css", href:"css/jquery-ui-1.8.18.custom.css" 376 | link rel:"stylesheet", type:"text/css", href:"css/style.css" 377 | script src: 'js/jquery-1.7.2.min.js' 378 | script src: 'js/jquery-ui-1.8.18.custom.min.js' 379 | body @body 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | -------------------------------------------------------------------------------- /static/css/jquery-ui-1.8.18.custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 1.8.18 3 | * 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Theming/API 9 | */ 10 | 11 | /* Layout helpers 12 | ----------------------------------*/ 13 | .ui-helper-hidden { display: none; } 14 | .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } 15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 16 | .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; } 17 | .ui-helper-clearfix:after { clear: both; } 18 | .ui-helper-clearfix { zoom: 1; } 19 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 20 | 21 | 22 | /* Interaction Cues 23 | ----------------------------------*/ 24 | .ui-state-disabled { cursor: default !important; } 25 | 26 | 27 | /* Icons 28 | ----------------------------------*/ 29 | 30 | /* states and images */ 31 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 32 | 33 | 34 | /* Misc visuals 35 | ----------------------------------*/ 36 | 37 | /* Overlays */ 38 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 39 | 40 | 41 | /* 42 | * jQuery UI CSS Framework 1.8.18 43 | * 44 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 45 | * Dual licensed under the MIT or GPL Version 2 licenses. 46 | * http://jquery.org/license 47 | * 48 | * http://docs.jquery.com/UI/Theming/API 49 | * 50 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 51 | */ 52 | 53 | 54 | /* Component containers 55 | ----------------------------------*/ 56 | .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } 57 | .ui-widget .ui-widget { font-size: 1em; } 58 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } 59 | .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } 60 | .ui-widget-content a { color: #222222; } 61 | .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } 62 | .ui-widget-header a { color: #222222; } 63 | 64 | /* Interaction states 65 | ----------------------------------*/ 66 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } 67 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } 68 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 69 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } 70 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 71 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } 72 | .ui-widget :active { outline: none; } 73 | 74 | /* Interaction Cues 75 | ----------------------------------*/ 76 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } 77 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } 78 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } 79 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } 80 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } 81 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } 82 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 83 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 84 | 85 | /* Icons 86 | ----------------------------------*/ 87 | 88 | /* states and images */ 89 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } 90 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } 91 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } 92 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } 93 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } 94 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } 95 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } 96 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } 97 | 98 | /* positioning */ 99 | .ui-icon-carat-1-n { background-position: 0 0; } 100 | .ui-icon-carat-1-ne { background-position: -16px 0; } 101 | .ui-icon-carat-1-e { background-position: -32px 0; } 102 | .ui-icon-carat-1-se { background-position: -48px 0; } 103 | .ui-icon-carat-1-s { background-position: -64px 0; } 104 | .ui-icon-carat-1-sw { background-position: -80px 0; } 105 | .ui-icon-carat-1-w { background-position: -96px 0; } 106 | .ui-icon-carat-1-nw { background-position: -112px 0; } 107 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 108 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 109 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 110 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 111 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 112 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 113 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 114 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 115 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 116 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 117 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 118 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 119 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 120 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 121 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 122 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 123 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 124 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 125 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 126 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 127 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 128 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 129 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 130 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 131 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 132 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 133 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 134 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 135 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 136 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 137 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 138 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 139 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 140 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 141 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 142 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 143 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 144 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 145 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 146 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 147 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 148 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 149 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 150 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 151 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 152 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 153 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 154 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 155 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 156 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 157 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 158 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 159 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 160 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 161 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 162 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 163 | .ui-icon-arrow-4 { background-position: 0 -80px; } 164 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 165 | .ui-icon-extlink { background-position: -32px -80px; } 166 | .ui-icon-newwin { background-position: -48px -80px; } 167 | .ui-icon-refresh { background-position: -64px -80px; } 168 | .ui-icon-shuffle { background-position: -80px -80px; } 169 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 170 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 171 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 172 | .ui-icon-folder-open { background-position: -16px -96px; } 173 | .ui-icon-document { background-position: -32px -96px; } 174 | .ui-icon-document-b { background-position: -48px -96px; } 175 | .ui-icon-note { background-position: -64px -96px; } 176 | .ui-icon-mail-closed { background-position: -80px -96px; } 177 | .ui-icon-mail-open { background-position: -96px -96px; } 178 | .ui-icon-suitcase { background-position: -112px -96px; } 179 | .ui-icon-comment { background-position: -128px -96px; } 180 | .ui-icon-person { background-position: -144px -96px; } 181 | .ui-icon-print { background-position: -160px -96px; } 182 | .ui-icon-trash { background-position: -176px -96px; } 183 | .ui-icon-locked { background-position: -192px -96px; } 184 | .ui-icon-unlocked { background-position: -208px -96px; } 185 | .ui-icon-bookmark { background-position: -224px -96px; } 186 | .ui-icon-tag { background-position: -240px -96px; } 187 | .ui-icon-home { background-position: 0 -112px; } 188 | .ui-icon-flag { background-position: -16px -112px; } 189 | .ui-icon-calendar { background-position: -32px -112px; } 190 | .ui-icon-cart { background-position: -48px -112px; } 191 | .ui-icon-pencil { background-position: -64px -112px; } 192 | .ui-icon-clock { background-position: -80px -112px; } 193 | .ui-icon-disk { background-position: -96px -112px; } 194 | .ui-icon-calculator { background-position: -112px -112px; } 195 | .ui-icon-zoomin { background-position: -128px -112px; } 196 | .ui-icon-zoomout { background-position: -144px -112px; } 197 | .ui-icon-search { background-position: -160px -112px; } 198 | .ui-icon-wrench { background-position: -176px -112px; } 199 | .ui-icon-gear { background-position: -192px -112px; } 200 | .ui-icon-heart { background-position: -208px -112px; } 201 | .ui-icon-star { background-position: -224px -112px; } 202 | .ui-icon-link { background-position: -240px -112px; } 203 | .ui-icon-cancel { background-position: 0 -128px; } 204 | .ui-icon-plus { background-position: -16px -128px; } 205 | .ui-icon-plusthick { background-position: -32px -128px; } 206 | .ui-icon-minus { background-position: -48px -128px; } 207 | .ui-icon-minusthick { background-position: -64px -128px; } 208 | .ui-icon-close { background-position: -80px -128px; } 209 | .ui-icon-closethick { background-position: -96px -128px; } 210 | .ui-icon-key { background-position: -112px -128px; } 211 | .ui-icon-lightbulb { background-position: -128px -128px; } 212 | .ui-icon-scissors { background-position: -144px -128px; } 213 | .ui-icon-clipboard { background-position: -160px -128px; } 214 | .ui-icon-copy { background-position: -176px -128px; } 215 | .ui-icon-contact { background-position: -192px -128px; } 216 | .ui-icon-image { background-position: -208px -128px; } 217 | .ui-icon-video { background-position: -224px -128px; } 218 | .ui-icon-script { background-position: -240px -128px; } 219 | .ui-icon-alert { background-position: 0 -144px; } 220 | .ui-icon-info { background-position: -16px -144px; } 221 | .ui-icon-notice { background-position: -32px -144px; } 222 | .ui-icon-help { background-position: -48px -144px; } 223 | .ui-icon-check { background-position: -64px -144px; } 224 | .ui-icon-bullet { background-position: -80px -144px; } 225 | .ui-icon-radio-off { background-position: -96px -144px; } 226 | .ui-icon-radio-on { background-position: -112px -144px; } 227 | .ui-icon-pin-w { background-position: -128px -144px; } 228 | .ui-icon-pin-s { background-position: -144px -144px; } 229 | .ui-icon-play { background-position: 0 -160px; } 230 | .ui-icon-pause { background-position: -16px -160px; } 231 | .ui-icon-seek-next { background-position: -32px -160px; } 232 | .ui-icon-seek-prev { background-position: -48px -160px; } 233 | .ui-icon-seek-end { background-position: -64px -160px; } 234 | .ui-icon-seek-start { background-position: -80px -160px; } 235 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 236 | .ui-icon-seek-first { background-position: -80px -160px; } 237 | .ui-icon-stop { background-position: -96px -160px; } 238 | .ui-icon-eject { background-position: -112px -160px; } 239 | .ui-icon-volume-off { background-position: -128px -160px; } 240 | .ui-icon-volume-on { background-position: -144px -160px; } 241 | .ui-icon-power { background-position: 0 -176px; } 242 | .ui-icon-signal-diag { background-position: -16px -176px; } 243 | .ui-icon-signal { background-position: -32px -176px; } 244 | .ui-icon-battery-0 { background-position: -48px -176px; } 245 | .ui-icon-battery-1 { background-position: -64px -176px; } 246 | .ui-icon-battery-2 { background-position: -80px -176px; } 247 | .ui-icon-battery-3 { background-position: -96px -176px; } 248 | .ui-icon-circle-plus { background-position: 0 -192px; } 249 | .ui-icon-circle-minus { background-position: -16px -192px; } 250 | .ui-icon-circle-close { background-position: -32px -192px; } 251 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 252 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 253 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 254 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 255 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 256 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 257 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 258 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 259 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 260 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 261 | .ui-icon-circle-check { background-position: -208px -192px; } 262 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 263 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 264 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 265 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 266 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 267 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 268 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 269 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 270 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 271 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 272 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 273 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 274 | 275 | 276 | /* Misc visuals 277 | ----------------------------------*/ 278 | 279 | /* Corner radius */ 280 | .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } 281 | .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } 282 | .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } 283 | .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 284 | 285 | /* Overlays */ 286 | .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } 287 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* 288 | * jQuery UI Resizable 1.8.18 289 | * 290 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 291 | * Dual licensed under the MIT or GPL Version 2 licenses. 292 | * http://jquery.org/license 293 | * 294 | * http://docs.jquery.com/UI/Resizable#theming 295 | */ 296 | .ui-resizable { position: relative;} 297 | .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; } 298 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } 299 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } 300 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } 301 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } 302 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } 303 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } 304 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } 305 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } 306 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* 307 | * jQuery UI Selectable 1.8.18 308 | * 309 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 310 | * Dual licensed under the MIT or GPL Version 2 licenses. 311 | * http://jquery.org/license 312 | * 313 | * http://docs.jquery.com/UI/Selectable#theming 314 | */ 315 | .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } 316 | /* 317 | * jQuery UI Accordion 1.8.18 318 | * 319 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 320 | * Dual licensed under the MIT or GPL Version 2 licenses. 321 | * http://jquery.org/license 322 | * 323 | * http://docs.jquery.com/UI/Accordion#theming 324 | */ 325 | /* IE/Win - Fix animation bug - #4615 */ 326 | .ui-accordion { width: 100%; } 327 | .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } 328 | .ui-accordion .ui-accordion-li-fix { display: inline; } 329 | .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } 330 | .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } 331 | .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } 332 | .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } 333 | .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } 334 | .ui-accordion .ui-accordion-content-active { display: block; } 335 | /* 336 | * jQuery UI Autocomplete 1.8.18 337 | * 338 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 339 | * Dual licensed under the MIT or GPL Version 2 licenses. 340 | * http://jquery.org/license 341 | * 342 | * http://docs.jquery.com/UI/Autocomplete#theming 343 | */ 344 | .ui-autocomplete { position: absolute; cursor: default; } 345 | 346 | /* workarounds */ 347 | * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ 348 | 349 | /* 350 | * jQuery UI Menu 1.8.18 351 | * 352 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 353 | * Dual licensed under the MIT or GPL Version 2 licenses. 354 | * http://jquery.org/license 355 | * 356 | * http://docs.jquery.com/UI/Menu#theming 357 | */ 358 | .ui-menu { 359 | list-style:none; 360 | padding: 2px; 361 | margin: 0; 362 | display:block; 363 | float: left; 364 | } 365 | .ui-menu .ui-menu { 366 | margin-top: -3px; 367 | } 368 | .ui-menu .ui-menu-item { 369 | margin:0; 370 | padding: 0; 371 | zoom: 1; 372 | float: left; 373 | clear: left; 374 | width: 100%; 375 | } 376 | .ui-menu .ui-menu-item a { 377 | text-decoration:none; 378 | display:block; 379 | padding:.2em .4em; 380 | line-height:1.5; 381 | zoom:1; 382 | } 383 | .ui-menu .ui-menu-item a.ui-state-hover, 384 | .ui-menu .ui-menu-item a.ui-state-active { 385 | font-weight: normal; 386 | margin: -1px; 387 | } 388 | /* 389 | * jQuery UI Button 1.8.18 390 | * 391 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 392 | * Dual licensed under the MIT or GPL Version 2 licenses. 393 | * http://jquery.org/license 394 | * 395 | * http://docs.jquery.com/UI/Button#theming 396 | */ 397 | .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: hidden; *overflow: visible; } /* the overflow property removes extra width in IE */ 398 | .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ 399 | button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ 400 | .ui-button-icons-only { width: 3.4em; } 401 | button.ui-button-icons-only { width: 3.7em; } 402 | 403 | /*button text element */ 404 | .ui-button .ui-button-text { display: block; line-height: 1.4; } 405 | .ui-button-text-only .ui-button-text { padding: .4em 1em; } 406 | .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } 407 | .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } 408 | .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } 409 | .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } 410 | /* no icon support for input elements, provide padding by default */ 411 | input.ui-button { padding: .4em 1em; } 412 | 413 | /*button icon element(s) */ 414 | .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } 415 | .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } 416 | .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } 417 | .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 418 | .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 419 | 420 | /*button sets*/ 421 | .ui-buttonset { margin-right: 7px; } 422 | .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } 423 | 424 | /* workarounds */ 425 | button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ 426 | /* 427 | * jQuery UI Dialog 1.8.18 428 | * 429 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 430 | * Dual licensed under the MIT or GPL Version 2 licenses. 431 | * http://jquery.org/license 432 | * 433 | * http://docs.jquery.com/UI/Dialog#theming 434 | */ 435 | .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } 436 | .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } 437 | .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 438 | .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } 439 | .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } 440 | .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } 441 | .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } 442 | .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } 443 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } 444 | .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } 445 | .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } 446 | .ui-draggable .ui-dialog-titlebar { cursor: move; } 447 | /* 448 | * jQuery UI Slider 1.8.18 449 | * 450 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 451 | * Dual licensed under the MIT or GPL Version 2 licenses. 452 | * http://jquery.org/license 453 | * 454 | * http://docs.jquery.com/UI/Slider#theming 455 | */ 456 | .ui-slider { position: relative; text-align: left; } 457 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } 458 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } 459 | 460 | .ui-slider-horizontal { height: .8em; } 461 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } 462 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } 463 | .ui-slider-horizontal .ui-slider-range-min { left: 0; } 464 | .ui-slider-horizontal .ui-slider-range-max { right: 0; } 465 | 466 | .ui-slider-vertical { width: .8em; height: 100px; } 467 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } 468 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } 469 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; } 470 | .ui-slider-vertical .ui-slider-range-max { top: 0; }/* 471 | * jQuery UI Tabs 1.8.18 472 | * 473 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 474 | * Dual licensed under the MIT or GPL Version 2 licenses. 475 | * http://jquery.org/license 476 | * 477 | * http://docs.jquery.com/UI/Tabs#theming 478 | */ 479 | .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 480 | .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } 481 | .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } 482 | .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } 483 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } 484 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } 485 | .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ 486 | .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } 487 | .ui-tabs .ui-tabs-hide { display: none !important; } 488 | /* 489 | * jQuery UI Datepicker 1.8.18 490 | * 491 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 492 | * Dual licensed under the MIT or GPL Version 2 licenses. 493 | * http://jquery.org/license 494 | * 495 | * http://docs.jquery.com/UI/Datepicker#theming 496 | */ 497 | .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } 498 | .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } 499 | .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } 500 | .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } 501 | .ui-datepicker .ui-datepicker-prev { left:2px; } 502 | .ui-datepicker .ui-datepicker-next { right:2px; } 503 | .ui-datepicker .ui-datepicker-prev-hover { left:1px; } 504 | .ui-datepicker .ui-datepicker-next-hover { right:1px; } 505 | .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } 506 | .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } 507 | .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } 508 | .ui-datepicker select.ui-datepicker-month-year {width: 100%;} 509 | .ui-datepicker select.ui-datepicker-month, 510 | .ui-datepicker select.ui-datepicker-year { width: 49%;} 511 | .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } 512 | .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } 513 | .ui-datepicker td { border: 0; padding: 1px; } 514 | .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } 515 | .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } 516 | .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } 517 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } 518 | 519 | /* with multiple calendars */ 520 | .ui-datepicker.ui-datepicker-multi { width:auto; } 521 | .ui-datepicker-multi .ui-datepicker-group { float:left; } 522 | .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } 523 | .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } 524 | .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } 525 | .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } 526 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } 527 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } 528 | .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } 529 | .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } 530 | 531 | /* RTL support */ 532 | .ui-datepicker-rtl { direction: rtl; } 533 | .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } 534 | .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } 535 | .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } 536 | .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } 537 | .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } 538 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } 539 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } 540 | .ui-datepicker-rtl .ui-datepicker-group { float:right; } 541 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 542 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 543 | 544 | /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ 545 | .ui-datepicker-cover { 546 | display: none; /*sorry for IE5*/ 547 | display/**/: block; /*sorry for IE5*/ 548 | position: absolute; /*must have*/ 549 | z-index: -1; /*must have*/ 550 | filter: mask(); /*must have*/ 551 | top: -4px; /*must have*/ 552 | left: -4px; /*must have*/ 553 | width: 200px; /*must have*/ 554 | height: 200px; /*must have*/ 555 | }/* 556 | * jQuery UI Progressbar 1.8.18 557 | * 558 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 559 | * Dual licensed under the MIT or GPL Version 2 licenses. 560 | * http://jquery.org/license 561 | * 562 | * http://docs.jquery.com/UI/Progressbar#theming 563 | */ 564 | .ui-progressbar { height:2em; text-align: left; overflow: hidden; } 565 | .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } -------------------------------------------------------------------------------- /static/js/jquery-1.7.2.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v1.7.2 jquery.com | jquery.org/license */ 2 | (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"":"")+"
"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;e| t |