diff --git a/ajax-test.html b/ajax-test.html new file mode 100644 index 0000000..b839ee2 --- /dev/null +++ b/ajax-test.html @@ -0,0 +1,2 @@ +

This is AJAX content

+Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. \ No newline at end of file diff --git a/app/css/bootstrap-responsive.css b/app/css/bootstrap-responsive.css new file mode 100644 index 0000000..a09b826 --- /dev/null +++ b/app/css/bootstrap-responsive.css @@ -0,0 +1,720 @@ +/*! + * Bootstrap Responsive v2.0.0 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ +.hidden { + display: none; + visibility: hidden; +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + + .page-header h1 small { + display: block; + line-height: 18px; + } + + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + height: 28px; + /* Make inputs at least the height of their button counterpart */ + + /* Makes inputs behave like true block-level elements */ + + -webkit-box-sizing: border-box; + /* Older Webkit */ + + -moz-box-sizing: border-box; + /* Older FF */ + + -ms-box-sizing: border-box; + /* IE8 */ + + box-sizing: border-box; + /* CSS3 spec*/ + + } + + .input-prepend input[class*="span"], .input-append input[class*="span"] { + width: auto; + } + + input[type="checkbox"], input[type="radio"] { + border: 1px solid #ccc; + } + + .form-horizontal .control-group > label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + + .form-horizontal .controls { + margin-left: 0; + } + + .form-horizontal .control-list { + padding-top: 0; + } + + .form-horizontal .form-actions { + padding-left: 10px; + padding-right: 10px; + } + + .modal { + position: absolute; + top: 10px; + left: 10px; + right: 10px; + width: auto; + margin: 0; + } + + .modal.fade.in { + top: auto; + } + + .modal-header .close { + padding: 10px; + margin: -10px; + } + + .carousel-caption { + position: static; + } +} + +@media (max-width: 768px) { + .container { + width: auto; + padding: 0 20px; + } + + .row-fluid { + width: 100%; + } + + .row { + margin-left: 0; + } + + .row > [class*="span"], .row-fluid > [class*="span"] { + float: none; + display: block; + width: auto; + margin: 0; + } +} + +@media (min-width: 768px) and (max-width: 980px) { + .row { + margin-left: -20px; + *zoom: 1; + } + + .row:before, .row:after { + display: table; + content: ""; + } + + .row:after { + clear: both; + } + + [class*="span"] { + float: left; + margin-left: 20px; + } + + .span1 { + width: 42px; + } + + .span2 { + width: 104px; + } + + .span3 { + width: 166px; + } + + .span4 { + width: 228px; + } + + .span5 { + width: 290px; + } + + .span6 { + width: 352px; + } + + .span7 { + width: 414px; + } + + .span8 { + width: 476px; + } + + .span9 { + width: 538px; + } + + .span10 { + width: 600px; + } + + .span11 { + width: 662px; + } + + .span12, .container { + width: 724px; + } + + .offset1 { + margin-left: 82px; + } + + .offset2 { + margin-left: 144px; + } + + .offset3 { + margin-left: 206px; + } + + .offset4 { + margin-left: 268px; + } + + .offset5 { + margin-left: 330px; + } + + .offset6 { + margin-left: 392px; + } + + .offset7 { + margin-left: 454px; + } + + .offset8 { + margin-left: 516px; + } + + .offset9 { + margin-left: 578px; + } + + .offset10 { + margin-left: 640px; + } + + .offset11 { + margin-left: 702px; + } + + .row-fluid { + width: 100%; + *zoom: 1; + } + + .row-fluid:before, .row-fluid:after { + display: table; + content: ""; + } + + .row-fluid:after { + clear: both; + } + + .row-fluid > [class*="span"] { + float: left; + margin-left: 2.762430939%; + } + + .row-fluid > [class*="span"]:first-child { + margin-left: 0; + } + + .row-fluid .span1 { + width: 5.801104972%; + } + + .row-fluid .span2 { + width: 14.364640883%; + } + + .row-fluid .span3 { + width: 22.928176794%; + } + + .row-fluid .span4 { + width: 31.491712705%; + } + + .row-fluid .span5 { + width: 40.055248616%; + } + + .row-fluid .span6 { + width: 48.618784527%; + } + + .row-fluid .span7 { + width: 57.182320438000005%; + } + + .row-fluid .span8 { + width: 65.74585634900001%; + } + + .row-fluid .span9 { + width: 74.30939226%; + } + + .row-fluid .span10 { + width: 82.87292817100001%; + } + + .row-fluid .span11 { + width: 91.436464082%; + } + + .row-fluid .span12 { + width: 99.999999993%; + } + + input.span1, textarea.span1, .uneditable-input.span1 { + width: 32px; + } + + input.span2, textarea.span2, .uneditable-input.span2 { + width: 94px; + } + + input.span3, textarea.span3, .uneditable-input.span3 { + width: 156px; + } + + input.span4, textarea.span4, .uneditable-input.span4 { + width: 218px; + } + + input.span5, textarea.span5, .uneditable-input.span5 { + width: 280px; + } + + input.span6, textarea.span6, .uneditable-input.span6 { + width: 342px; + } + + input.span7, textarea.span7, .uneditable-input.span7 { + width: 404px; + } + + input.span8, textarea.span8, .uneditable-input.span8 { + width: 466px; + } + + input.span9, textarea.span9, .uneditable-input.span9 { + width: 528px; + } + + input.span10, textarea.span10, .uneditable-input.span10 { + width: 590px; + } + + input.span11, textarea.span11, .uneditable-input.span11 { + width: 652px; + } + + input.span12, textarea.span12, .uneditable-input.span12 { + width: 714px; + } +} + +@media (max-width: 980px) { + body { + padding-top: 0; + } + + .navbar-fixed-top { + position: static; + margin-bottom: 18px; + } + + .navbar-fixed-top .navbar-inner { + padding: 5px; + } + + .navbar .container { + width: auto; + padding: 0; + } + + .navbar .brand { + padding-left: 10px; + padding-right: 10px; + margin: 0 0 0 -5px; + } + + .navbar .nav-collapse { + clear: left; + } + + .navbar .nav { + float: none; + margin: 0 0 9px; + } + + .navbar .nav > li { + float: none; + } + + .navbar .nav > li > a { + margin-bottom: 2px; + } + + .navbar .nav > .divider-vertical { + display: none; + } + + .navbar .nav > li > a, .navbar .dropdown-menu a { + padding: 6px 15px; + font-weight: bold; + color: #999999; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + + .navbar .dropdown-menu li + li a { + margin-bottom: 2px; + } + + .navbar .nav > li > a:hover, .navbar .dropdown-menu a:hover { + background-color: #222222; + } + + .navbar .dropdown-menu { + position: static; + top: auto; + left: auto; + float: none; + display: block; + max-width: none; + margin: 0 15px; + padding: 0; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + + .navbar .dropdown-menu:before, .navbar .dropdown-menu:after { + display: none; + } + + .navbar .dropdown-menu .divider { + display: none; + } + + .navbar-form, .navbar-search { + float: none; + padding: 9px 15px; + margin: 9px 0; + border-top: 1px solid #222222; + border-bottom: 1px solid #222222; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + + .navbar .nav.pull-right { + float: none; + margin-left: 0; + } + + .navbar-static .navbar-inner { + padding-left: 10px; + padding-right: 10px; + } + + .navbar .btn-navbar { + display: block; + } + + .nav-collapse { + overflow: hidden; + height: 0; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + + .row:before, .row:after { + display: table; + content: ""; + } + + .row:after { + clear: both; + } + + [class*="span"] { + float: left; + margin-left: 30px; + } + + .span1 { + width: 70px; + } + + .span2 { + width: 170px; + } + + .span3 { + width: 270px; + } + + .span4 { + width: 370px; + } + + .span5 { + width: 470px; + } + + .span6 { + width: 570px; + } + + .span7 { + width: 670px; + } + + .span8 { + width: 770px; + } + + .span9 { + width: 870px; + } + + .span10 { + width: 970px; + } + + .span11 { + width: 1070px; + } + + .span12, .container { + width: 1170px; + } + + .offset1 { + margin-left: 130px; + } + + .offset2 { + margin-left: 230px; + } + + .offset3 { + margin-left: 330px; + } + + .offset4 { + margin-left: 430px; + } + + .offset5 { + margin-left: 530px; + } + + .offset6 { + margin-left: 630px; + } + + .offset7 { + margin-left: 730px; + } + + .offset8 { + margin-left: 830px; + } + + .offset9 { + margin-left: 930px; + } + + .offset10 { + margin-left: 1030px; + } + + .offset11 { + margin-left: 1130px; + } + + .row-fluid { + width: 100%; + *zoom: 1; + } + + .row-fluid:before, .row-fluid:after { + display: table; + content: ""; + } + + .row-fluid:after { + clear: both; + } + + .row-fluid > [class*="span"] { + float: left; + margin-left: 2.564102564%; + } + + .row-fluid > [class*="span"]:first-child { + margin-left: 0; + } + + .row-fluid .span1 { + width: 5.982905983%; + } + + .row-fluid .span2 { + width: 14.529914530000001%; + } + + .row-fluid .span3 { + width: 23.076923077%; + } + + .row-fluid .span4 { + width: 31.623931624%; + } + + .row-fluid .span5 { + width: 40.170940171000005%; + } + + .row-fluid .span6 { + width: 48.717948718%; + } + + .row-fluid .span7 { + width: 57.264957265%; + } + + .row-fluid .span8 { + width: 65.81196581200001%; + } + + .row-fluid .span9 { + width: 74.358974359%; + } + + .row-fluid .span10 { + width: 82.905982906%; + } + + .row-fluid .span11 { + width: 91.45299145300001%; + } + + .row-fluid .span12 { + width: 100%; + } + + input.span1, textarea.span1, .uneditable-input.span1 { + width: 60px; + } + + input.span2, textarea.span2, .uneditable-input.span2 { + width: 160px; + } + + input.span3, textarea.span3, .uneditable-input.span3 { + width: 260px; + } + + input.span4, textarea.span4, .uneditable-input.span4 { + width: 360px; + } + + input.span5, textarea.span5, .uneditable-input.span5 { + width: 460px; + } + + input.span6, textarea.span6, .uneditable-input.span6 { + width: 560px; + } + + input.span7, textarea.span7, .uneditable-input.span7 { + width: 660px; + } + + input.span8, textarea.span8, .uneditable-input.span8 { + width: 760px; + } + + input.span9, textarea.span9, .uneditable-input.span9 { + width: 860px; + } + + input.span10, textarea.span10, .uneditable-input.span10 { + width: 960px; + } + + input.span11, textarea.span11, .uneditable-input.span11 { + width: 1060px; + } + + input.span12, textarea.span12, .uneditable-input.span12 { + width: 1160px; + } + + .thumbnails { + margin-left: -30px; + } + + .thumbnails > li { + margin-left: 30px; + } +} diff --git a/app/css/bootstrap.css b/app/css/bootstrap.css new file mode 100644 index 0000000..bfbfd33 --- /dev/null +++ b/app/css/bootstrap.css @@ -0,0 +1,4983 @@ +/*! + * Bootstrap v2.0.4 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 28px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover { + color: #005580; + text-decoration: underline; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + margin-left: 20px; +} + +.container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 28px; + margin-left: 2.127659574%; + *margin-left: 2.0744680846382977%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .span12 { + width: 99.99999998999999%; + *width: 99.94680850063828%; +} + +.row-fluid .span11 { + width: 91.489361693%; + *width: 91.4361702036383%; +} + +.row-fluid .span10 { + width: 82.97872339599999%; + *width: 82.92553190663828%; +} + +.row-fluid .span9 { + width: 74.468085099%; + *width: 74.4148936096383%; +} + +.row-fluid .span8 { + width: 65.95744680199999%; + *width: 65.90425531263828%; +} + +.row-fluid .span7 { + width: 57.446808505%; + *width: 57.3936170156383%; +} + +.row-fluid .span6 { + width: 48.93617020799999%; + *width: 48.88297871863829%; +} + +.row-fluid .span5 { + width: 40.425531911%; + *width: 40.3723404216383%; +} + +.row-fluid .span4 { + width: 31.914893614%; + *width: 31.8617021246383%; +} + +.row-fluid .span3 { + width: 23.404255317%; + *width: 23.3510638276383%; +} + +.row-fluid .span2 { + width: 14.89361702%; + *width: 14.8404255306383%; +} + +.row-fluid .span1 { + width: 6.382978723%; + *width: 6.329787233638298%; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 9px; +} + +p small { + font-size: 11px; + color: #999999; +} + +.lead { + margin-bottom: 18px; + font-size: 20px; + font-weight: 200; + line-height: 27px; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + font-family: inherit; + font-weight: bold; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + color: #999999; +} + +h1 { + font-size: 30px; + line-height: 36px; +} + +h1 small { + font-size: 18px; +} + +h2 { + font-size: 24px; + line-height: 36px; +} + +h2 small { + font-size: 18px; +} + +h3 { + font-size: 18px; + line-height: 27px; +} + +h3 small { + font-size: 14px; +} + +h4, +h5, +h6 { + line-height: 18px; +} + +h4 { + font-size: 14px; +} + +h4 small { + font-size: 12px; +} + +h5 { + font-size: 12px; +} + +h6 { + font-size: 11px; + color: #999999; + text-transform: uppercase; +} + +.page-header { + padding-bottom: 17px; + margin: 18px 0; + border-bottom: 1px solid #eeeeee; +} + +.page-header h1 { + line-height: 1; +} + +ul, +ol { + padding: 0; + margin: 0 0 9px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +ul { + list-style: disc; +} + +ol { + list-style: decimal; +} + +li { + line-height: 18px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +dl { + margin-bottom: 18px; +} + +dt, +dd { + line-height: 18px; +} + +dt { + font-weight: bold; + line-height: 17px; +} + +dd { + margin-left: 9px; +} + +.dl-horizontal dt { + float: left; + width: 120px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 130px; +} + +hr { + margin: 18px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +.muted { + color: #999999; +} + +abbr[title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 18px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 16px; + font-weight: 300; + line-height: 22.5px; +} + +blockquote small { + display: block; + line-height: 18px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 18px; + font-style: normal; + line-height: 18px; +} + +small { + font-size: 100%; +} + +cite { + font-style: normal; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 8.5px; + margin: 0 0 9px; + font-size: 12.025px; + line-height: 18px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 18px; +} + +pre code { + padding: 0; + color: inherit; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 18px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 27px; + font-size: 19.5px; + line-height: 36px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 13.5px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 13px; + font-weight: normal; + line-height: 18px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 18px; + padding: 4px; + margin-bottom: 9px; + font-size: 13px; + line-height: 18px; + color: #555555; +} + +input, +textarea { + width: 210px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 3px 0; + *margin-top: 0; + /* IE7 */ + + line-height: normal; + cursor: pointer; +} + +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +select, +input[type="file"] { + height: 28px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 28px; +} + +select { + width: 220px; + border: 1px solid #bbb; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.radio, +.checkbox { + min-height: 18px; + padding-left: 18px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -18px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 930px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 850px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 770px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 690px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 610px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 530px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 450px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 370px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 290px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 210px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 130px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 50px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; + border-color: #ddd; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning > label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; + border-color: #c09853; +} + +.control-group.warning .checkbox:focus, +.control-group.warning .radio:focus, +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: 0 0 6px #dbc59e; + -moz-box-shadow: 0 0 6px #dbc59e; + box-shadow: 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error > label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; + border-color: #b94a48; +} + +.control-group.error .checkbox:focus, +.control-group.error .radio:focus, +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: 0 0 6px #d59392; + -moz-box-shadow: 0 0 6px #d59392; + box-shadow: 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success > label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; + border-color: #468847; +} + +.control-group.success .checkbox:focus, +.control-group.success .radio:focus, +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: 0 0 6px #7aba7b; + -moz-box-shadow: 0 0 6px #7aba7b; + box-shadow: 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +input:focus:required:invalid, +textarea:focus:required:invalid, +select:focus:required:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:required:invalid:focus, +textarea:focus:required:invalid:focus, +select:focus:required:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 17px 20px 18px; + margin-top: 18px; + margin-bottom: 18px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; + cursor: not-allowed; + background-color: #ffffff; + border-color: #eee; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +:-moz-placeholder { + color: #999999; +} + +:-ms-input-placeholder { + color: #999999; +} + +::-webkit-input-placeholder { + color: #999999; +} + +.help-block, +.help-inline { + color: #555555; +} + +.help-block { + display: block; + margin-bottom: 9px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-prepend, +.input-append { + margin-bottom: 5px; +} + +.input-prepend input, +.input-append input, +.input-prepend select, +.input-append select, +.input-prepend .uneditable-input, +.input-append .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: middle; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.input-prepend input:focus, +.input-append input:focus, +.input-prepend select:focus, +.input-append select:focus, +.input-prepend .uneditable-input:focus, +.input-append .uneditable-input:focus { + z-index: 2; +} + +.input-prepend .uneditable-input, +.input-append .uneditable-input { + border-left-color: #ccc; +} + +.input-prepend .add-on, +.input-append .add-on { + display: inline-block; + width: auto; + height: 18px; + min-width: 16px; + padding: 4px 5px; + font-weight: normal; + line-height: 18px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + vertical-align: middle; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-prepend .add-on, +.input-append .add-on, +.input-prepend .btn, +.input-append .btn { + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend .active, +.input-append .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.input-append .uneditable-input { + border-right-color: #ccc; + border-left-color: #eee; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 14px; + -moz-border-radius: 14px; + border-radius: 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 9px; +} + +legend + .control-group { + margin-top: 18px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 18px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 140px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 160px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 160px; +} + +.form-horizontal .help-block { + margin-top: 9px; + margin-bottom: 0; +} + +.form-horizontal .form-actions { + padding-left: 160px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 18px; +} + +.table th, +.table td { + padding: 8px; + line-height: 18px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapsed; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child th:first-child, +.table-bordered tbody:first-child tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child th:last-child, +.table-bordered tbody:first-child tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child th:first-child, +.table-bordered tbody:last-child tr:last-child td:first-child { + -webkit-border-radius: 0 0 0 4px; + -moz-border-radius: 0 0 0 4px; + border-radius: 0 0 0 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child th:last-child, +.table-bordered tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-striped tbody tr:nth-child(odd) td, +.table-striped tbody tr:nth-child(odd) th { + background-color: #f9f9f9; +} + +.table tbody tr:hover td, +.table tbody tr:hover th { + background-color: #f5f5f5; +} + +table .span1 { + float: none; + width: 44px; + margin-left: 0; +} + +table .span2 { + float: none; + width: 124px; + margin-left: 0; +} + +table .span3 { + float: none; + width: 204px; + margin-left: 0; +} + +table .span4 { + float: none; + width: 284px; + margin-left: 0; +} + +table .span5 { + float: none; + width: 364px; + margin-left: 0; +} + +table .span6 { + float: none; + width: 444px; + margin-left: 0; +} + +table .span7 { + float: none; + width: 524px; + margin-left: 0; +} + +table .span8 { + float: none; + width: 604px; + margin-left: 0; +} + +table .span9 { + float: none; + width: 684px; + margin-left: 0; +} + +table .span10 { + float: none; + width: 764px; + margin-left: 0; +} + +table .span11 { + float: none; + width: 844px; + margin-left: 0; +} + +table .span12 { + float: none; + width: 924px; + margin-left: 0; +} + +table .span13 { + float: none; + width: 1004px; + margin-left: 0; +} + +table .span14 { + float: none; + width: 1084px; + margin-left: 0; +} + +table .span15 { + float: none; + width: 1164px; + margin-left: 0; +} + +table .span16 { + float: none; + width: 1244px; + margin-left: 0; +} + +table .span17 { + float: none; + width: 1324px; + margin-left: 0; +} + +table .span18 { + float: none; + width: 1404px; + margin-left: 0; +} + +table .span19 { + float: none; + width: 1484px; + margin-left: 0; +} + +table .span20 { + float: none; + width: 1564px; + margin-left: 0; +} + +table .span21 { + float: none; + width: 1644px; + margin-left: 0; +} + +table .span22 { + float: none; + width: 1724px; + margin-left: 0; +} + +table .span23 { + float: none; + width: 1804px; + margin-left: 0; +} + +table .span24 { + float: none; + width: 1884px; + margin-left: 0; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +[class^="icon-"]:last-child, +[class*=" icon-"]:last-child { + *margin-left: 0; +} + +.icon-white { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + background-position: -384px -120px; +} + +.icon-folder-open { + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; + opacity: 0.3; + filter: alpha(opacity = 30); +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown:hover .caret, +.open .caret { + opacity: 1; + filter: alpha(opacity = 100); +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 4px 0; + margin: 1px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 8px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu a { + display: block; + padding: 3px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu li > a:hover, +.dropdown-menu .active > a, +.dropdown-menu .active > a:hover { + color: #ffffff; + text-decoration: none; + background-color: #0088cc; +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: "\2191"; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.typeahead { + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -ms-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 18px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity = 20); +} + +.close:hover { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity = 40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 10px 4px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 13px; + line-height: 18px; + *line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(top, #ffffff, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#e6e6e6', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn:hover, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover { + color: #333333; + text-decoration: none; + background-color: #e6e6e6; + *background-color: #d9d9d9; + /* Buttons in IE7 don't get borders, so darken on hover */ + + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -ms-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-color: #e6e6e6; + background-color: #d9d9d9 \9; + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-color: #e6e6e6; + background-image: none; + opacity: 0.65; + filter: alpha(opacity = 65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 9px 14px; + font-size: 15px; + line-height: normal; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.btn-large [class^="icon-"] { + margin-top: 1px; +} + +.btn-small { + padding: 5px 9px; + font-size: 11px; + line-height: 16px; +} + +.btn-small [class^="icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 2px 6px; + font-size: 11px; + line-height: 14px; +} + +.btn-primary, +.btn-primary:hover, +.btn-warning, +.btn-warning:hover, +.btn-danger, +.btn-danger:hover, +.btn-success, +.btn-success:hover, +.btn-info, +.btn-info:hover, +.btn-inverse, +.btn-inverse:hover { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn { + border-color: #ccc; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} + +.btn-primary { + background-color: #0074cc; + *background-color: #0055cc; + background-image: -ms-linear-gradient(top, #0088cc, #0055cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0055cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0055cc); + background-image: -o-linear-gradient(top, #0088cc, #0055cc); + background-image: -moz-linear-gradient(top, #0088cc, #0055cc); + background-image: linear-gradient(top, #0088cc, #0055cc); + background-repeat: repeat-x; + border-color: #0055cc #0055cc #003580; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#0088cc', endColorstr = '#0055cc', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); +} + +.btn-primary:hover, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + background-color: #0055cc; + *background-color: #004ab3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #004099 \9; +} + +.btn-warning { + background-color: #faa732; + *background-color: #f89406; + background-image: -ms-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(top, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#fbb450', endColorstr = '#f89406', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); +} + +.btn-warning:hover, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + background-color: #da4f49; + *background-color: #bd362f; + background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(top, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#ee5f5b', endColorstr = '#bd362f', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); +} + +.btn-danger:hover, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + background-color: #5bb75b; + *background-color: #51a351; + background-image: -ms-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(top, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#62c462', endColorstr = '#51a351', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); +} + +.btn-success:hover, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(top, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#5bc0de', endColorstr = '#2f96b4', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); +} + +.btn-info:hover, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + background-color: #414141; + *background-color: #222222; + background-image: -ms-linear-gradient(top, #555555, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#222222)); + background-image: -webkit-linear-gradient(top, #555555, #222222); + background-image: -o-linear-gradient(top, #555555, #222222); + background-image: -moz-linear-gradient(top, #555555, #222222); + background-image: linear-gradient(top, #555555, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#555555', endColorstr = '#222222', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); +} + +.btn-inverse:hover, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 2px; + *padding-bottom: 2px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-group { + position: relative; + *margin-left: .3em; + *zoom: 1; +} + +.btn-group:before, +.btn-group:after { + display: table; + content: ""; +} + +.btn-group:after { + clear: both; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 9px; + margin-bottom: 9px; +} + +.btn-toolbar .btn-group { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group > .btn { + position: relative; + float: left; + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .dropdown-toggle { + *padding-top: 4px; + padding-right: 8px; + *padding-bottom: 4px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini.dropdown-toggle { + padding-right: 5px; + padding-left: 5px; +} + +.btn-group > .btn-small.dropdown-toggle { + *padding-top: 4px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large.dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0055cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 7px; + margin-left: 0; +} + +.btn:hover .caret, +.open.btn-group .caret { + opacity: 1; + filter: alpha(opacity = 100); +} + +.btn-mini .caret { + margin-top: 5px; +} + +.btn-small .caret { + margin-top: 6px; +} + +.btn-large .caret { + margin-top: 6px; + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.dropup .btn-large .caret { + border-top: 0; + border-bottom: 5px solid #000000; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 0.75; + filter: alpha(opacity = 75); +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 18px; + color: #c09853; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert-heading { + color: inherit; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 18px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 18px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > .pull-right { + float: right; +} + +.nav .nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 18px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 8px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 18px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.nav-tabs.nav-stacked > li > a:hover { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.nav-tabs .dropdown-toggle .caret, +.nav-pills .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav-tabs .dropdown-toggle:hover .caret, +.nav-pills .dropdown-toggle:hover .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +.nav-tabs .active .dropdown-toggle .caret, +.nav-pills .active .dropdown-toggle .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.nav > .dropdown.active > a:hover { + color: #000000; + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity = 100); +} + +.tabs-stacked .open > a:hover { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 18px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #2c2c2c; + background-image: -moz-linear-gradient(top, #333333, #222222); + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#333333', endColorstr = '#222222', GradientType = 0); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; +} + +.navbar { + color: #999999; +} + +.navbar .brand:hover { + text-decoration: none; +} + +.navbar .brand { + display: block; + float: left; + padding: 8px 20px 12px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + line-height: 1; + color: #999999; +} + +.navbar .navbar-text { + margin-bottom: 0; + line-height: 40px; +} + +.navbar .navbar-link { + color: #999999; +} + +.navbar .navbar-link:hover { + color: #ffffff; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn { + margin: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 6px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 6px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 9px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + color: #ffffff; + background-color: #626262; + border: 1px solid #151515; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-search .search-query:focus, +.navbar-search .search-query.focused { + padding: 5px 10px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; +} + +.navbar .nav > li { + display: block; + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 9px 10px 11px; + line-height: 19px; + color: #999999; + text-decoration: none; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar .btn { + display: inline-block; + padding: 4px 10px 4px; + margin: 5px 5px 6px; + line-height: 18px; +} + +.navbar .btn-group { + padding: 5px 5px 6px; + margin: 0; +} + +.navbar .nav > li > a:hover { + color: #ffffff; + text-decoration: none; + background-color: transparent; +} + +.navbar .nav .active > a, +.navbar .nav .active > a:hover { + color: #ffffff; + text-decoration: none; + background-color: #222222; +} + +.navbar .divider-vertical { + width: 1px; + height: 40px; + margin: 0 9px; + overflow: hidden; + background-color: #222222; + border-right: 1px solid #333333; +} + +.navbar .nav.pull-right { + margin-right: 0; + margin-left: 10px; +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + background-color: #2c2c2c; + *background-color: #222222; + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + background-image: -moz-linear-gradient(top, #333333, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#333333', endColorstr = '#222222', GradientType = 0); + filter: progid:dximagetransform.microsoft.gradient(enabled = false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + background-color: #222222; + *background-color: #151515; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #080808 \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown .dropdown-toggle .caret, +.navbar .nav li.dropdown.open .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar .nav li.dropdown.active .caret { + opacity: 1; + filter: alpha(opacity = 100); +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + background-color: transparent; +} + +.navbar .nav li.dropdown.active > .dropdown-toggle:hover { + color: #ffffff; +} + +.navbar .pull-right .dropdown-menu, +.navbar .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right .dropdown-menu:before, +.navbar .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right .dropdown-menu:after, +.navbar .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.breadcrumb { + padding: 7px 14px; + margin: 0 0 18px; + list-style: none; + background-color: #fbfbfb; + background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); + background-image: linear-gradient(top, #ffffff, #f5f5f5); + background-repeat: repeat-x; + border: 1px solid #ddd; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#f5f5f5', GradientType = 0); + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.breadcrumb li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb .divider { + padding: 0 5px; + color: #999999; +} + +.breadcrumb .active a { + color: #333333; +} + +.pagination { + height: 36px; + margin: 18px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination li { + display: inline; +} + +.pagination a { + float: left; + padding: 0 14px; + line-height: 34px; + text-decoration: none; + border: 1px solid #ddd; + border-left-width: 0; +} + +.pagination a:hover, +.pagination .active a { + background-color: #f5f5f5; +} + +.pagination .active a { + color: #999999; + cursor: default; +} + +.pagination .disabled span, +.pagination .disabled a, +.pagination .disabled a:hover { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination li:first-child a { + border-left-width: 1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.pagination li:last-child a { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pager { + margin-bottom: 18px; + margin-left: 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager a { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager a:hover { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next a { + float: right; +} + +.pager .previous a { + float: left; +} + +.pager .disabled a, +.pager .disabled a:hover { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-open .dropdown-menu { + z-index: 2050; +} + +.modal-open .dropdown.open { + *z-index: 2050; +} + +.modal-open .popover { + z-index: 2060; +} + +.modal-open .tooltip { + z-index: 2070; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity = 80); +} + +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 1050; + width: 560px; + margin: -250px 0 0 -280px; + overflow: auto; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -ms-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 50%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-body { + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.tooltip { + position: absolute; + z-index: 1020; + display: block; + padding: 5px; + font-size: 11px; + opacity: 0; + filter: alpha(opacity = 0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity = 80); +} + +.tooltip.top { + margin-top: -2px; +} + +.tooltip.right { + margin-left: 2px; +} + +.tooltip.bottom { + margin-top: 2px; +} + +.tooltip.left { + margin-left: -2px; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top: 5px solid #000000; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; + border-left: 5px solid transparent; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-right: 5px solid #000000; + border-bottom: 5px solid transparent; +} + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + padding: 5px; +} + +.popover.top { + margin-top: -5px; +} + +.popover.right { + margin-left: 5px; +} + +.popover.bottom { + margin-top: 5px; +} + +.popover.left { + margin-left: -5px; +} + +.popover.top .arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top: 5px solid #000000; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.popover.right .arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-right: 5px solid #000000; + border-bottom: 5px solid transparent; +} + +.popover.bottom .arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; + border-left: 5px solid transparent; +} + +.popover.left .arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} + +.popover .arrow { + position: absolute; + width: 0; + height: 0; +} + +.popover-inner { + width: 280px; + padding: 3px; + overflow: hidden; + background: #000000; + background: rgba(0, 0, 0, 0.8); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); +} + +.popover-title { + padding: 9px 15px; + line-height: 1; + background-color: #f5f5f5; + border-bottom: 1px solid #eee; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} + +.popover-content { + padding: 14px; + background-color: #ffffff; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.popover-content p, +.popover-content ul, +.popover-content ol { + margin-bottom: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 18px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 1; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); +} + +a.thumbnail:hover { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; +} + +.label, +.badge { + font-size: 10.998px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + padding: 1px 4px 2px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding: 1px 9px 2px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +a.label:hover, +a.badge:hover { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 18px; + margin-bottom: 18px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(top, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#f5f5f5', endColorstr = '#f9f9f9', GradientType = 0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + width: 0; + height: 18px; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(top, #149bdf, #0480be); + background-image: -ms-linear-gradient(top, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#149bdf', endColorstr = '#0480be', GradientType = 0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -ms-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#ee5f5b', endColorstr = '#c43c35', GradientType = 0); +} + +.progress-danger.progress-striped .bar { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#62c462', endColorstr = '#57a957', GradientType = 0); +} + +.progress-success.progress-striped .bar { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(top, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#5bc0de', endColorstr = '#339bb9', GradientType = 0); +} + +.progress-info.progress-striped .bar { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -ms-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(top, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr = '#fbb450', endColorstr = '#f89406', GradientType = 0); +} + +.progress-warning.progress-striped .bar { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 18px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 18px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -ms-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel .item > img { + display: block; + line-height: 1; +} + +.carousel .active, +.carousel .next, +.carousel .prev { + display: block; +} + +.carousel .active { + left: 0; +} + +.carousel .next, +.carousel .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel .next { + left: 100%; +} + +.carousel .prev { + left: -100%; +} + +.carousel .next.left, +.carousel .prev.right { + left: 0; +} + +.carousel .active.left { + left: -100%; +} + +.carousel .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity = 50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity = 90); +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 10px 15px 5px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + color: #ffffff; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit p { + font-size: 18px; + font-weight: 200; + line-height: 27px; + color: inherit; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} diff --git a/app/css/docs.css b/app/css/docs.css new file mode 100644 index 0000000..006158f --- /dev/null +++ b/app/css/docs.css @@ -0,0 +1,903 @@ +/* Add additional stylesheets below +-------------------------------------------------- */ +/* + Bootstrap's documentation styles + Special styles for presenting Bootstrap's documentation and examples +*/ + +/* Body and structure +-------------------------------------------------- */ +body { + position: relative; + padding-top: 90px; + background-color: #fff; + background-image: url(../img/grid-18px-masked.png); + background-repeat: repeat-x; + background-position: 0 40px; +} + +/* Tweak navbar brand link to be super sleek +-------------------------------------------------- */ +.navbar-fixed-top .brand { + padding-right: 0; + padding-left: 0; + margin-left: 20px; + float: right; + font-weight: bold; + color: #000; + text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125); + -webkit-transition: all .2s linear; + -moz-transition: all .2s linear; + transition: all .2s linear; +} + +.navbar-fixed-top .brand:hover { + text-decoration: none; +} + +/* Space out sub-sections more +-------------------------------------------------- */ +section { + padding-top: 60px; +} + +/* Faded out hr */ +hr.soften { + height: 1px; + margin: 54px 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, .1), rgba(0, 0, 0, 0)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, .1), rgba(0, 0, 0, 0)); + background-image: -ms-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, .1), rgba(0, 0, 0, 0)); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, .1), rgba(0, 0, 0, 0)); + border: 0; +} + +/* Jumbotrons +-------------------------------------------------- */ +.jumbotron { + position: relative; +} + +.jumbotron h1 { + margin-bottom: 9px; + font-size: 81px; + font-weight: bold; + letter-spacing: -1px; + line-height: 1; +} + +.jumbotron p { + margin-bottom: 18px; + font-weight: 300; +} + +.jumbotron .btn-large { + font-size: 20px; + font-weight: normal; + padding: 14px 24px; + margin-right: 10px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.jumbotron .btn-large small { + font-size: 14px; +} + +/* Masthead (docs home) */ +.masthead { + padding-top: 36px; + margin-bottom: 72px; +} + +.masthead h1, +.masthead p { + text-align: center; +} + +.masthead h1 { + margin-bottom: 18px; +} + +.masthead p { + margin-left: 5%; + margin-right: 5%; + font-size: 30px; + line-height: 36px; +} + +/* Specific jumbotrons +------------------------- */ +/* supporting docs pages */ +.subhead { + padding-bottom: 0; + margin-bottom: 9px; +} + +.subhead h1 { + font-size: 54px; +} + +/* Subnav */ +.subnav { + width: 100%; + height: 36px; + background-color: #eeeeee; /* Old browsers */ + background-repeat: repeat-x; /* Repeat the gradient */ + background-image: -moz-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* FF3.6+ */ + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f5f5f5), color-stop(100%, #eeeeee)); /* Chrome,Safari4+ */ + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* Chrome 10+,Safari 5.1+ */ + background-image: -ms-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* IE10+ */ + background-image: -o-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* Opera 11.10+ */ + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#f5f5f5', endColorstr = '#eeeeee', GradientType = 0); /* IE6-9 */ + background-image: linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* W3C */ + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.subnav .nav { + margin-bottom: 0; +} + +.subnav .nav > li > a { + margin: 0; + padding-top: 11px; + padding-bottom: 11px; + border-left: 1px solid #f5f5f5; + border-right: 1px solid #e5e5e5; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.subnav .nav > .active > a, +.subnav .nav > .active > a:hover { + padding-left: 13px; + color: #777; + background-color: #e9e9e9; + border-right-color: #ddd; + border-left: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .05); + -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .05); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .05); +} + +.subnav .nav > .active > a .caret, +.subnav .nav > .active > a:hover .caret { + border-top-color: #777; +} + +.subnav .nav > li:first-child > a, +.subnav .nav > li:first-child > a:hover { + border-left: 0; + padding-left: 12px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.subnav .nav > li:last-child > a { + border-right: 0; +} + +.subnav .dropdown-menu { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +/* Fixed subnav on scroll, but only for 980px and up (sorry IE!) */ +@media (min-width: 980px) { + .subnav-fixed { + position: fixed; + top: 40px; + left: 0; + right: 0; + z-index: 1020; /* 10 less than .navbar-fixed to prevent any overlap */ + border-color: #d5d5d5; + border-width: 0 0 1px; /* drop the border on the fixed edges */ + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0, 0, 0, .1); + -moz-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0, 0, 0, .1); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); /* IE6-9 */ + } + + .subnav-fixed .nav { + width: 938px; + margin: 0 auto; + padding: 0 1px; + } + + .subnav .nav > li:first-child > a, + .subnav .nav > li:first-child > a:hover { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + } +} + +/* Quick links +-------------------------------------------------- */ +.bs-links { + margin: 36px 0; +} + +.quick-links { + min-height: 30px; + margin: 0; + padding: 5px 20px; + list-style: none; + text-align: center; + overflow: hidden; +} + +.quick-links:first-child { + min-height: 0; +} + +.quick-links li { + display: inline; + margin: 0 8px; + color: #999; +} + +.quick-links .github-btn, +.quick-links .tweet-btn, +.quick-links .follow-btn { + position: relative; + top: 5px; +} + +/* Marketing section of Overview +-------------------------------------------------- */ +.marketing .row { + margin-bottom: 9px; +} + +.marketing h1 { + margin: 36px 0 27px; + font-size: 40px; + font-weight: 300; + text-align: center; +} + +.marketing h2, +.marketing h3 { + font-weight: 300; +} + +.marketing h2 { + font-size: 22px; +} + +.marketing p { + margin-right: 10px; +} + +.marketing .bs-icon { + float: left; + margin: 7px 10px 0 0; + opacity: .8; +} + +.marketing .small-bs-icon { + float: left; + margin: 4px 5px 0 0; +} + +/* Footer +-------------------------------------------------- */ +.footer { + margin-top: 45px; + padding: 35px 0 36px; + border-top: 1px solid #e5e5e5; +} + +.footer p { + margin-bottom: 0; + color: #555; +} + +/* Special grid styles +-------------------------------------------------- */ +.show-grid { + margin-top: 10px; + margin-bottom: 20px; +} + +.show-grid [class*="span"] { + background-color: #eee; + text-align: center; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + min-height: 30px; + line-height: 30px; +} + +.show-grid:hover [class*="span"] { + background: #ddd; +} + +.show-grid .show-grid { + margin-top: 0; + margin-bottom: 0; +} + +.show-grid .show-grid [class*="span"] { + background-color: #ccc; +} + +/* Render mini layout previews +-------------------------------------------------- */ +.mini-layout { + border: 1px solid #ddd; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} + +.mini-layout { + height: 240px; + margin-bottom: 20px; + padding: 9px; +} + +.mini-layout div { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.mini-layout .mini-layout-body { + background-color: #dceaf4; + margin: 0 auto; + width: 70%; + height: 240px; +} + +.mini-layout.fluid .mini-layout-sidebar, +.mini-layout.fluid .mini-layout-header, +.mini-layout.fluid .mini-layout-body { + float: left; +} + +.mini-layout.fluid .mini-layout-sidebar { + background-color: #bbd8e9; + width: 20%; + height: 240px; +} + +.mini-layout.fluid .mini-layout-body { + width: 77.5%; + margin-left: 2.5%; +} + +/* Popover docs +-------------------------------------------------- */ +.popover-well { + min-height: 160px; +} + +.popover-well .popover { + display: block; +} + +.popover-well .popover-wrapper { + width: 50%; + height: 160px; + float: left; + margin-left: 55px; + position: relative; +} + +.popover-well .popover-menu-wrapper { + height: 80px; +} + +.large-bird { + margin: 5px 0 0 310px; + opacity: .1; +} + +/* Download page +-------------------------------------------------- */ +.download .page-header { + margin-top: 36px; +} + +.page-header .toggle-all { + margin-top: 5px; +} + +/* Space out h3s when following a section */ +.download h3 { + margin-bottom: 5px; +} + +.download-builder input + h3, +.download-builder .checkbox + h3 { + margin-top: 9px; +} + +/* Fields for variables */ +.download-builder input[type=text] { + margin-bottom: 9px; + font-family: Menlo, Monaco, "Courier New", monospace; + font-size: 12px; + color: #d14; +} + +.download-builder input[type=text]:focus { + background-color: #fff; +} + +/* Custom, larger checkbox labels */ +.download .checkbox { + padding: 6px 10px 6px 25px; + color: #555; + background-color: #f9f9f9; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + cursor: pointer; +} + +.download .checkbox:hover { + color: #333; + background-color: #f5f5f5; +} + +.download .checkbox small { + font-size: 12px; + color: #777; +} + +/* Variables section */ +#variables label { + margin-bottom: 0; +} + +/* Giant download button */ +.download-btn { + margin: 36px 0 108px; +} + +#download p, +#download h4 { + max-width: 50%; + margin: 0 auto; + color: #999; + text-align: center; +} + +#download h4 { + margin-bottom: 0; +} + +#download p { + margin-bottom: 18px; +} + +.download-btn .btn { + display: block; + width: auto; + padding: 19px 24px; + margin-bottom: 27px; + font-size: 30px; + line-height: 1; + text-align: center; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +/* Color swatches on LESS docs page +-------------------------------------------------- */ +/* Sets the width of the td */ +.swatch-col { + width: 30px; +} + +/* Le swatch */ +.swatch { + display: inline-block; + width: 30px; + height: 20px; + margin: -6px 0; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +/* For white swatches, give a border */ +.swatch-bordered { + width: 28px; + height: 18px; + border: 1px solid #eee; +} + +/* Misc +-------------------------------------------------- */ + +/* Make tables spaced out a bit more */ +h2 + table, +h3 + table, +h4 + table, +h2 + .row { + margin-top: 5px; +} + +/* Example sites showcase */ +.example-sites img { + max-width: 100%; + margin: 0 auto; +} + +.marketing-byline { + margin: -18px 0 27px; + font-size: 18px; + font-weight: 300; + line-height: 24px; + color: #999; + text-align: center; +} + +.scrollspy-example { + height: 200px; + overflow: auto; + position: relative; +} + +/* Remove bottom margin on example forms in wells */ +form.well { + padding: 14px; +} + +/* Tighten up spacing */ +.well hr { + margin: 18px 0; +} + +/* Fake the :focus state to demo it */ +.focused { + border-color: rgba(82, 168, 236, .8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .1), 0 0 8px rgba(82, 168, 236, .6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .1), 0 0 8px rgba(82, 168, 236, .6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, .1), 0 0 8px rgba(82, 168, 236, .6); + outline: 0; +} + +/* For input sizes, make them display block */ +.docs-input-sizes select, +.docs-input-sizes input[type=text] { + display: block; + margin-bottom: 9px; +} + +/* Icons +------------------------- */ +.the-icons { + margin-left: 0; + list-style: none; +} + +.the-icons i:hover { + background-color: rgba(255, 0, 0, .25); +} + +/* Eaxmples page +------------------------- */ +.bootstrap-examples .thumbnail { + margin-bottom: 9px; + background-color: #fff; +} + +/* Responsive table +------------------------- */ +.responsive-utilities th small { + display: block; + font-weight: normal; + color: #999; +} + +.responsive-utilities tbody th { + font-weight: normal; +} + +.responsive-utilities td { + text-align: center; +} + +.responsive-utilities td.is-visible { + color: #468847; + background-color: #dff0d8 !important; +} + +.responsive-utilities td.is-hidden { + color: #ccc; + background-color: #f9f9f9 !important; +} + +/* Responsive tests +------------------------- */ +.responsive-utilities-test { + margin-top: 5px; + margin-left: 0; + list-style: none; + overflow: hidden; /* clear floats */ +} + +.responsive-utilities-test li { + position: relative; + float: left; + width: 25%; + height: 43px; + font-size: 14px; + font-weight: bold; + line-height: 43px; + color: #999; + text-align: center; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.responsive-utilities-test li + li { + margin-left: 10px; +} + +.responsive-utilities-test span { + position: absolute; + top: -1px; + left: -1px; + right: -1px; + bottom: -1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.responsive-utilities-test span { + color: #468847; + background-color: #dff0d8; + border: 1px solid #d6e9c6; +} + +/* Responsive Docs +-------------------------------------------------- */ +@media (max-width: 480px) { + + /* Reduce padding above jumbotron */ + body { + padding-top: 70px; + } + + /* Change up some type stuff */ + h2 { + margin-top: 27px; + } + + h2 small { + display: block; + line-height: 18px; + } + + h3 { + margin-top: 18px; + } + + /* icons */ + .marketing .bs-icon { + margin: 0; + } + + /* Adjust the jumbotron */ + .jumbotron h1, + .jumbotron p { + text-align: center; + margin-right: 0; + } + + .jumbotron h1 { + font-size: 45px; + margin-right: 0; + } + + .jumbotron p { + margin-right: 0; + margin-left: 0; + font-size: 18px; + line-height: 24px; + } + + .jumbotron .btn { + display: block; + font-size: 18px; + padding: 10px 14px; + margin: 0 auto 10px; + } + + /* Masthead (home page jumbotron) */ + .masthead { + padding-top: 0; + } + + /* Don't space out quick links so much */ + .quick-links { + margin: 40px 0 0; + } + + /* hide the bullets on mobile since our horizontal space is limited */ + .quick-links .divider { + display: none; + } + + /* center example sites */ + .example-sites { + margin-left: 0; + } + + .example-sites > li { + float: none; + display: block; + max-width: 280px; + margin: 0 auto 18px; + text-align: center; + } + + .example-sites .thumbnail > img { + max-width: 270px; + } + + table code { + white-space: normal; + word-wrap: break-word; + word-break: break-all; + } + + /* Modal example */ + .modal-example .modal { + position: relative; + top: auto; + right: auto; + bottom: auto; + left: auto; + } + +} + +@media (max-width: 768px) { + + /* Remove any padding from the body */ + body { + padding-top: 0; + } + + /* Jumbotron buttons */ + .jumbotron .btn { + margin-bottom: 10px; + } + + /* Subnav */ + .subnav { + position: static; + top: auto; + z-index: auto; + width: auto; + height: auto; + background: #fff; /* whole background property since we use a background-image for gradient */ + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + + .subnav .nav > li { + float: none; + } + + .subnav .nav > li > a { + border: 0; + } + + .subnav .nav > li + li > a { + border-top: 1px solid #e5e5e5; + } + + .subnav .nav > li:first-child > a, + .subnav .nav > li:first-child > a:hover { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; + } + + /* Popovers */ + .large-bird { + display: none; + } + + .popover-well .popover-wrapper { + margin-left: 0; + } + + /* Space out the show-grid examples */ + .show-grid [class*="span"] { + margin-bottom: 5px; + } + + /* Unfloat the back to top link in footer */ + .footer .pull-right { + float: none; + } + + .footer p { + margin-bottom: 9px; + } + +} + +@media (min-width: 480px) and (max-width: 768px) { + + /* Scale down the jumbotron content */ + .jumbotron h1 { + font-size: 54px; + } + + .jumbotron p { + margin-right: 0; + margin-left: 0; + } + +} + +@media (min-width: 768px) and (max-width: 980px) { + + /* Remove any padding from the body */ + body { + padding-top: 0; + } + + /* Scale down the jumbotron content */ + .jumbotron h1 { + font-size: 72px; + } + +} + +@media (max-width: 980px) { + + /* Unfloat brand */ + .navbar-fixed-top .brand { + float: left; + margin-left: 0; + padding-left: 10px; + padding-right: 10px; + } + + /* Inline-block quick links for more spacing */ + .quick-links li { + display: inline-block; + margin: 5px; + } + +} + +/* LARGE DESKTOP SCREENS */ +@media (min-width: 1210px) { + + /* Update subnav container */ + .subnav-fixed .nav { + width: 1168px; /* 2px less to account for left/right borders being removed when in fixed mode */ + } + +} diff --git a/app/img/ajax-loader.gif b/app/img/ajax-loader.gif new file mode 100644 index 0000000..3596a61 Binary files /dev/null and b/app/img/ajax-loader.gif differ diff --git a/app/img/glyphicons-cogwheels.png b/app/img/glyphicons-cogwheels.png new file mode 100644 index 0000000..5c14892 Binary files /dev/null and b/app/img/glyphicons-cogwheels.png differ diff --git a/app/img/glyphicons-halflings-white.png b/app/img/glyphicons-halflings-white.png new file mode 100755 index 0000000..3bf6484 Binary files /dev/null and b/app/img/glyphicons-halflings-white.png differ diff --git a/app/img/glyphicons-halflings.png b/app/img/glyphicons-halflings.png new file mode 100755 index 0000000..79bc568 Binary files /dev/null and b/app/img/glyphicons-halflings.png differ diff --git a/app/img/grid-18px-masked.png b/app/img/grid-18px-masked.png new file mode 100644 index 0000000..1bc82b0 Binary files /dev/null and b/app/img/grid-18px-masked.png differ diff --git a/app/js/boilerplate/collection-boilerplate.js b/app/js/boilerplate/collection-boilerplate.js new file mode 100644 index 0000000..be6c7e8 --- /dev/null +++ b/app/js/boilerplate/collection-boilerplate.js @@ -0,0 +1,16 @@ +// Use this as a quick template for future collections +// Use this as a quick template for future models +define([ + 'jquery', + 'underscore', + 'backbone', + 'models/{{modelname}}' +], function ($, _, Backbone, ModelName) { + + var MyCollection = Backbone.Collection.extend({ + model:ModelName, + url:'url' + }); + + return MyCollection; +}); diff --git a/app/js/boilerplate/model-boilerplate.js b/app/js/boilerplate/model-boilerplate.js new file mode 100644 index 0000000..0f144b2 --- /dev/null +++ b/app/js/boilerplate/model-boilerplate.js @@ -0,0 +1,18 @@ +// Use this as a quick template for future models +define([ + 'jquery', + 'underscore', + 'backbone' +], function ($, _, Backbone) { + + var MyModel = Backbone.Model.extend({ + + urlRoot:'url/root', + + defaults:{}, + url:function () { + } + }); + + return MyModel; +}); diff --git a/app/js/boilerplate/module-boilerplate.js b/app/js/boilerplate/module-boilerplate.js new file mode 100755 index 0000000..509d36d --- /dev/null +++ b/app/js/boilerplate/module-boilerplate.js @@ -0,0 +1,9 @@ +// Use this as a quick template for future modules +define([ + 'jquery', + 'underscore', + 'backbone' +], function ($, _, Backbone) { + + return {}; +}); diff --git a/app/js/boilerplate/view-boilerplate.js b/app/js/boilerplate/view-boilerplate.js new file mode 100644 index 0000000..6271644 --- /dev/null +++ b/app/js/boilerplate/view-boilerplate.js @@ -0,0 +1,16 @@ +// Use this as a quick template for future views +define([ + 'jquery', + 'underscore', + 'backbone' +], function ($, _, Backbone) { + + var MyView = Backbone.View.extend({ + initialize:function (options) { + }, + render:function () { + } + }); + + return MyView; +}); diff --git a/app/js/libs/backbone/backbone-relational.js b/app/js/libs/backbone/backbone-relational.js new file mode 100644 index 0000000..02f7a84 --- /dev/null +++ b/app/js/libs/backbone/backbone-relational.js @@ -0,0 +1,1338 @@ +/** + * Backbone-relational.js 0.5.0 + * (c) 2011 Paul Uithol + * + * Backbone-relational may be freely distributed under the MIT license. + * For details and documentation: https://github.com/PaulUithol/Backbone-relational. + * Depends on (as in, compeletely useless without) Backbone: https://github.com/documentcloud/backbone. + */ +(function (root, factory) { + // Set up appropriately for the environment. + if (typeof exports !== 'undefined') { + // Node/CommonJS + factory(exports, require('underscore'), require('backbone')); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(['exports', 'underscore', 'backbone'], factory); + } else { + // Browser globals + factory({}, root._, root.Backbone); + } +}(this, function (exports, _, Backbone) { + + Backbone.Relational = { + showWarnings:true + }; + + /** + * Semaphore mixin; can be used as both binary and counting. + **/ + Backbone.Semaphore = { + _permitsAvailable:null, + _permitsUsed:0, + + acquire:function () { + if (this._permitsAvailable && this._permitsUsed >= this._permitsAvailable) { + throw new Error('Max permits acquired'); + } + else { + this._permitsUsed++; + } + }, + + release:function () { + if (this._permitsUsed === 0) { + throw new Error('All permits released'); + } + else { + this._permitsUsed--; + } + }, + + isLocked:function () { + return this._permitsUsed > 0; + }, + + setAvailablePermits:function (amount) { + if (this._permitsUsed > amount) { + throw new Error('Available permits cannot be less than used permits'); + } + this._permitsAvailable = amount; + } + }; + + /** + * A BlockingQueue that accumulates items while blocked (via 'block'), + * and processes them when unblocked (via 'unblock'). + * Process can also be called manually (via 'process'). + */ + Backbone.BlockingQueue = function () { + this._queue = []; + }; + _.extend(Backbone.BlockingQueue.prototype, Backbone.Semaphore, { + _queue:null, + + add:function (func) { + if (this.isBlocked()) { + this._queue.push(func); + } + else { + func(); + } + }, + + process:function () { + while (this._queue && this._queue.length) { + this._queue.shift()(); + } + }, + + block:function () { + this.acquire(); + }, + + unblock:function () { + this.release(); + if (!this.isBlocked()) { + this.process(); + } + }, + + isBlocked:function () { + return this.isLocked(); + } + }); + /** + * Global event queue. Accumulates external events ('add:', 'remove:' and 'update:') + * until the top-level object is fully initialized (see 'Backbone.RelationalModel'). + */ + Backbone.Relational.eventQueue = new Backbone.BlockingQueue(); + + /** + * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel. + * Handles lookup for relations. + */ + Backbone.Store = function () { + this._collections = []; + this._reverseRelations = []; + }; + _.extend(Backbone.Store.prototype, Backbone.Events, { + _collections:null, + _reverseRelations:null, + + /** + * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to + * existing instances of 'model' in the store as well. + * @param {object} relation + * @param {Backbone.RelationalModel} relation.model + * @param {String} relation.type + * @param {String} relation.key + * @param {String|object} relation.relatedModel + */ + addReverseRelation:function (relation) { + var exists = _.any(this._reverseRelations, function (rel) { + return _.all(relation, function (val, key) { + return val === rel[ key ]; + }); + }); + + if (!exists && relation.model && relation.type) { + this._reverseRelations.push(relation); + + if (!relation.model.prototype.relations) { + relation.model.prototype.relations = []; + } + relation.model.prototype.relations.push(relation); + + this.retroFitRelation(relation); + } + }, + + /** + * Add a 'relation' to all existing instances of 'relation.model' in the store + * @param {object} relation + */ + retroFitRelation:function (relation) { + var coll = this.getCollection(relation.model); + coll.each(function (model) { + new relation.type(model, relation); + }, this); + }, + + /** + * Find the Store's collection for a certain type of model. + * @param {Backbone.RelationalModel} model + * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null + */ + getCollection:function (model) { + var coll = _.detect(this._collections, function (c) { + // Check if model is the type itself (a ref to the constructor), or is of type c.model + return model === c.model || model.constructor === c.model; + }); + + if (!coll) { + coll = this._createCollection(model); + } + + return coll; + }, + + /** + * Find a type on the global object by name. Splits name on dots. + * @param {String} name + * @return {Object} + */ + getObjectByName:function (name) { + var type = _.reduce(name.split('.'), function (memo, val) { + return memo[ val ]; + }, exports); + return type !== exports ? type : null; + }, + + _createCollection:function (type) { + var coll; + + // If 'type' is an instance, take it's constructor + if (type instanceof Backbone.RelationalModel) { + type = type.constructor; + } + + // Type should inherit from Backbone.RelationalModel. + if (type.prototype instanceof Backbone.RelationalModel.prototype.constructor) { + coll = new Backbone.Collection(); + coll.model = type; + + this._collections.push(coll); + } + + return coll; + }, + + find:function (type, id) { + var coll = this.getCollection(type); + return coll && coll.get(id); + }, + + /** + * Add a 'model' to it's appropriate collection. Retain the original contents of 'model.collection'. + * @param {Backbone.RelationalModel} model + */ + register:function (model) { + var modelColl = model.collection; + var coll = this.getCollection(model); + coll && coll.add(model); + model.bind('destroy', this.unregister, this); + model.collection = modelColl; + }, + + /** + * Explicitly update a model's id in it's store collection + * @param {Backbone.RelationalModel} model + */ + update:function (model) { + var coll = this.getCollection(model); + coll._onModelEvent('change:' + model.idAttribute, model, coll); + }, + + /** + * Remove a 'model' from the store. + * @param {Backbone.RelationalModel} model + */ + unregister:function (model) { + model.unbind('destroy', this.unregister); + var coll = this.getCollection(model); + coll && coll.remove(model); + } + }); + Backbone.Relational.store = new Backbone.Store(); + + /** + * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:' events + * are used to regulate addition and removal of models from relations. + * + * @param {Backbone.RelationalModel} instance + * @param {object} options + * @param {string} options.key + * @param {Backbone.RelationalModel.constructor} options.relatedModel + * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids. + * @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store. + * @param {object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate + * the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs + * {Backbone.Relation|String} type ('HasOne' or 'HasMany'). + */ + Backbone.Relation = function (instance, options) { + this.instance = instance; + // Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype + options = ( typeof options === 'object' && options ) || {}; + this.reverseRelation = _.defaults(options.reverseRelation || {}, this.options.reverseRelation); + this.reverseRelation.type = !_.isString(this.reverseRelation.type) ? this.reverseRelation.type : + Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName(this.reverseRelation.type); + this.model = options.model || this.instance.constructor; + this.options = _.defaults(options, this.options, Backbone.Relation.prototype.options); + + this.key = this.options.key; + this.keySource = this.options.keySource || this.key; + + // 'exports' should be the global object where 'relatedModel' can be found on if given as a string. + this.relatedModel = this.options.relatedModel; + if (_.isString(this.relatedModel)) { + this.relatedModel = Backbone.Relational.store.getObjectByName(this.relatedModel); + } + + if (!this.checkPreconditions()) { + return false; + } + + if (instance) { + this.keyContents = this.instance.get(this.keySource); + + // Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'. + if (this.key !== this.keySource) { + this.instance.unset(this.keySource, { silent:true }); + } + + // Add this Relation to instance._relations + this.instance._relations.push(this); + } + + // Add the reverse relation on 'relatedModel' to the store's reverseRelations + if (!this.options.isAutoRelation && this.reverseRelation.type && this.reverseRelation.key) { + Backbone.Relational.store.addReverseRelation(_.defaults({ + isAutoRelation:true, + model:this.relatedModel, + relatedModel:this.model, + reverseRelation:this.options // current relation is the 'reverseRelation' for it's own reverseRelation + }, + this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.) + )); + } + + _.bindAll(this, '_modelRemovedFromCollection', '_relatedModelAdded', '_relatedModelRemoved'); + + if (instance) { + this.initialize(); + + // When a model in the store is destroyed, check if it is 'this.instance'. + Backbone.Relational.store.getCollection(this.instance) + .bind('relational:remove', this._modelRemovedFromCollection); + + // When 'relatedModel' are created or destroyed, check if it affects this relation. + Backbone.Relational.store.getCollection(this.relatedModel) + .bind('relational:add', this._relatedModelAdded) + .bind('relational:remove', this._relatedModelRemoved); + } + }; + // Fix inheritance :\ + Backbone.Relation.extend = Backbone.Model.extend; + // Set up all inheritable **Backbone.Relation** properties and methods. + _.extend(Backbone.Relation.prototype, Backbone.Events, Backbone.Semaphore, { + options:{ + createModels:true, + includeInJSON:true, + isAutoRelation:false + }, + + instance:null, + key:null, + keyContents:null, + relatedModel:null, + reverseRelation:null, + related:null, + + _relatedModelAdded:function (model, coll, options) { + // Allow 'model' to set up it's relations, before calling 'tryAddRelated' + // (which can result in a call to 'addRelated' on a relation of 'model') + var dit = this; + model.queue(function () { + dit.tryAddRelated(model, options); + }); + }, + + _relatedModelRemoved:function (model, coll, options) { + this.removeRelated(model, options); + }, + + _modelRemovedFromCollection:function (model) { + if (model === this.instance) { + this.destroy(); + } + }, + + /** + * Check several pre-conditions. + * @return {Boolean} True if pre-conditions are satisfied, false if they're not. + */ + checkPreconditions:function () { + var i = this.instance, + k = this.key, + m = this.model, + rm = this.relatedModel, + warn = Backbone.Relational.showWarnings && typeof console !== 'undefined'; + + if (!m || !k || !rm) { + warn && console.warn('Relation=%o; no model, key or relatedModel (%o, %o, %o)', this, m, k, rm); + return false; + } + // Check if the type in 'relatedModel' inherits from Backbone.RelationalModel + if (!( m.prototype instanceof Backbone.RelationalModel.prototype.constructor )) { + warn && console.warn('Relation=%o; model does not inherit from Backbone.RelationalModel (%o)', this, i); + return false; + } + // Check if the type in 'relatedModel' inherits from Backbone.RelationalModel + if (!( rm.prototype instanceof Backbone.RelationalModel.prototype.constructor )) { + warn && console.warn('Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)', this, rm); + return false; + } + // Check if this is not a HasMany, and the reverse relation is HasMany as well + if (this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany.prototype.constructor) { + warn && console.warn('Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.', this); + return false; + } + + // Check if we're not attempting to create a duplicate relationship + if (i && i._relations.length) { + var exists = _.any(i._relations, function (rel) { + var hasReverseRelation = this.reverseRelation.key && rel.reverseRelation.key; + return rel.relatedModel === rm && rel.key === k && + ( !hasReverseRelation || this.reverseRelation.key === rel.reverseRelation.key ); + }, this); + + if (exists) { + warn && console.warn('Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists', + this, i, k, rm, this.reverseRelation.key); + return false; + } + } + + return true; + }, + + /** + * Set the related model(s) for this relation + * @param {Backbone.Mode|Backbone.Collection} related + * @param {Object} [options] + */ + setRelated:function (related, options) { + this.related = related; + + this.instance.acquire(); + this.instance.set(this.key, related, _.defaults(options || {}, { silent:true })); + this.instance.release(); + }, + + createModel:function (item) { + if (this.options.createModels && typeof( item ) === 'object') { + return new this.relatedModel(item); + } + }, + + /** + * Determine if a relation (on a different RelationalModel) is the reverse + * relation of the current one. + * @param {Backbone.Relation} relation + * @return {Boolean} + */ + _isReverseRelation:function (relation) { + if (relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key && + this.key === relation.reverseRelation.key) { + return true; + } + return false; + }, + + /** + * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s). + * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model. + * If not specified, 'this.related' is used. + * @return {Backbone.Relation[]} + */ + getReverseRelations:function (model) { + var reverseRelations = []; + // Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array. + var models = !_.isUndefined(model) ? [ model ] : this.related && ( this.related.models || [ this.related ] ); + _.each(models, function (related) { + _.each(related.getRelations(), function (relation) { + if (this._isReverseRelation(relation)) { + reverseRelations.push(relation); + } + }, this); + }, this); + + return reverseRelations; + }, + + /** + * Rename options.silent to options.silentChange, so events propagate properly. + * (for example in HasMany, from 'addRelated'->'handleAddition') + * @param {Object} [options] + * @return {Object} + */ + sanitizeOptions:function (options) { + options = options ? _.clone(options) : {}; + if (options.silent) { + options = _.extend({}, options, { silentChange:true }); + delete options.silent; + } + return options; + }, + + /** + * Rename options.silentChange to options.silent, so events are silenced as intended in Backbone's + * original functions. + * @param {Object} [options] + * @return {Object} + */ + unsanitizeOptions:function (options) { + options = options ? _.clone(options) : {}; + if (options.silentChange) { + options = _.extend({}, options, { silent:true }); + delete options.silentChange; + } + return options; + }, + + // Cleanup. Get reverse relation, call removeRelated on each. + destroy:function () { + Backbone.Relational.store.getCollection(this.instance) + .unbind('relational:remove', this._modelRemovedFromCollection); + + Backbone.Relational.store.getCollection(this.relatedModel) + .unbind('relational:add', this._relatedModelAdded) + .unbind('relational:remove', this._relatedModelRemoved); + + _.each(this.getReverseRelations(), function (relation) { + relation.removeRelated(this.instance); + }, this); + } + }); + + Backbone.HasOne = Backbone.Relation.extend({ + options:{ + reverseRelation:{ type:'HasMany' } + }, + + initialize:function () { + _.bindAll(this, 'onChange'); + + this.instance.bind('relational:change:' + this.key, this.onChange); + + var model = this.findRelated({ silent:true }); + this.setRelated(model); + + // Notify new 'related' object of the new relation. + var dit = this; + _.each(dit.getReverseRelations(), function (relation) { + relation.addRelated(dit.instance); + }); + }, + + findRelated:function (options) { + var item = this.keyContents; + var model = null; + + if (item instanceof this.relatedModel) { + model = item; + } + else if (item && ( _.isString(item) || _.isNumber(item) || typeof( item ) === 'object' )) { + // Try to find an instance of the appropriate 'relatedModel' in the store, or create it + var id = _.isString(item) || _.isNumber(item) ? item : item[ this.relatedModel.prototype.idAttribute ]; + model = Backbone.Relational.store.find(this.relatedModel, id); + if (model && _.isObject(item)) { + model.set(item, options); + } + else if (!model) { + model = this.createModel(item); + } + } + + return model; + }, + + /** + * If the key is changed, notify old & new reverse relations and initialize the new relation + */ + onChange:function (model, attr, options) { + // Don't accept recursive calls to onChange (like onChange->findRelated->createModel->initializeRelations->addRelated->onChange) + if (this.isLocked()) { + return; + } + this.acquire(); + options = this.sanitizeOptions(options); + + // 'options._related' is set by 'addRelated'/'removeRelated'. If it is set, the change + // is the result of a call from a relation. If it's not, the change is the result of + // a 'set' call on this.instance. + var changed = _.isUndefined(options._related); + var oldRelated = changed ? this.related : options._related; + + if (changed) { + this.keyContents = attr; + + // Set new 'related' + if (attr instanceof this.relatedModel) { + this.related = attr; + } + else if (attr) { + var related = this.findRelated(options); + this.setRelated(related); + } + else { + this.setRelated(null); + } + } + + // Notify old 'related' object of the terminated relation + if (oldRelated && this.related !== oldRelated) { + _.each(this.getReverseRelations(oldRelated), function (relation) { + relation.removeRelated(this.instance, options); + }, this); + } + + // Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated; + // that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'. + // In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet. + _.each(this.getReverseRelations(), function (relation) { + relation.addRelated(this.instance, options); + }, this); + + // Fire the 'update:' event if 'related' was updated + if (!options.silentChange && this.related !== oldRelated) { + var dit = this; + Backbone.Relational.eventQueue.add(function () { + dit.instance.trigger('update:' + dit.key, dit.instance, dit.related, options); + }); + } + this.release(); + }, + + /** + * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents' + */ + tryAddRelated:function (model, options) { + if (this.related) { + return; + } + options = this.sanitizeOptions(options); + + var item = this.keyContents; + if (item && ( _.isString(item) || _.isNumber(item) || typeof( item ) === 'object' )) { + var id = _.isString(item) || _.isNumber(item) ? item : item[ this.relatedModel.prototype.idAttribute ]; + if (model.id === id) { + this.addRelated(model, options); + } + } + }, + + addRelated:function (model, options) { + if (model !== this.related) { + var oldRelated = this.related || null; + this.setRelated(model); + this.onChange(this.instance, model, { _related:oldRelated }); + } + }, + + removeRelated:function (model, options) { + if (!this.related) { + return; + } + + if (model === this.related) { + var oldRelated = this.related || null; + this.setRelated(null); + this.onChange(this.instance, model, { _related:oldRelated }); + } + } + }); + + Backbone.HasMany = Backbone.Relation.extend({ + collectionType:null, + + options:{ + reverseRelation:{ type:'HasOne' }, + collectionType:Backbone.Collection, + collectionKey:true + }, + + initialize:function () { + _.bindAll(this, 'onChange', 'handleAddition', 'handleRemoval', 'handleReset'); + this.instance.bind('relational:change:' + this.key, this.onChange); + + // Handle a custom 'collectionType' + this.collectionType = this.options.collectionType; + if (_(this.collectionType).isString()) { + this.collectionType = Backbone.Relational.store.getObjectByName(this.collectionType); + } + if (!this.collectionType.prototype instanceof Backbone.Collection.prototype.constructor) { + throw new Error('collectionType must inherit from Backbone.Collection'); + } + + this.setRelated(this.prepareCollection(new this.collectionType())); + this.findRelated({ silent:true }); + }, + + prepareCollection:function (collection) { + if (this.related) { + this.related + .unbind('relational:add', this.handleAddition) + .unbind('relational:remove', this.handleRemoval) + .unbind('relational:reset', this.handleReset) + } + + collection.model = this.relatedModel; + + if (this.options.collectionKey) { + var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey; + + if (collection[ key ] && collection[ key ] !== this.instance) { + if (Backbone.Relational.showWarnings && typeof console !== 'undefined') { + console.warn('Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey); + } + } + else { + collection[ key ] = this.instance; + } + } + + collection + .bind('relational:add', this.handleAddition) + .bind('relational:remove', this.handleRemoval) + .bind('relational:reset', this.handleReset); + + return collection; + }, + + findRelated:function (options) { + if (this.keyContents) { + // Handle cases the an API/user supplies just an Object/id instead of an Array + this.keyContents = _.isArray(this.keyContents) ? this.keyContents : [ this.keyContents ]; + + var models = []; + + // Try to find instances of the appropriate 'relatedModel' in the store + _.each(this.keyContents, function (item) { + var id = _.isString(item) || _.isNumber(item) ? item : item[ this.relatedModel.prototype.idAttribute ]; + + var model = Backbone.Relational.store.find(this.relatedModel, id); + if (model && _.isObject(item)) { + model.set(item, options); + } + else if (!model) { + model = this.createModel(item); + } + + if (model && !this.related.getByCid(model) && !this.related.get(model)) { + models.push(model); + } + }, this); + + // Add all found 'models' in on go, so 'add' will only be called once (and thus 'sort', etc.) + if (models.length) { + options = this.unsanitizeOptions(options); + this.related.add(models, options); + } + } + }, + + /** + * If the key is changed, notify old & new reverse relations and initialize the new relation + */ + onChange:function (model, attr, options) { + options = this.sanitizeOptions(options); + this.keyContents = attr; + + // Notify old 'related' object of the terminated relation + _.each(this.getReverseRelations(), function (relation) { + relation.removeRelated(this.instance, options); + }, this); + + // Replace 'this.related' by 'attr' if it is a Backbone.Collection + if (attr instanceof Backbone.Collection) { + this.prepareCollection(attr); + this.related = attr; + } + // Otherwise, 'attr' should be an array of related object ids. + // Re-use the current 'this.related' if it is a Backbone.Collection. + else { + var coll = this.related instanceof Backbone.Collection ? this.related : new this.collectionType(); + this.setRelated(this.prepareCollection(coll)); + this.findRelated(options); + } + + // Notify new 'related' object of the new relation + _.each(this.getReverseRelations(), function (relation) { + relation.addRelated(this.instance, options); + }, this); + + var dit = this; + Backbone.Relational.eventQueue.add(function () { + !options.silentChange && dit.instance.trigger('update:' + dit.key, dit.instance, dit.related, options); + }); + }, + + tryAddRelated:function (model, options) { + options = this.sanitizeOptions(options); + if (!this.related.getByCid(model) && !this.related.get(model)) { + // Check if this new model was specified in 'this.keyContents' + var item = _.any(this.keyContents, function (item) { + var id = _.isString(item) || _.isNumber(item) ? item : item[ this.relatedModel.prototype.idAttribute ]; + return id && id === model.id; + }, this); + + if (item) { + this.related.add(model, options); + } + } + }, + + /** + * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations. + * (should be 'HasOne', must set 'this.instance' as their related). + */ + handleAddition:function (model, coll, options) { + //console.debug('handleAddition called; args=%o', arguments); + // Make sure the model is in fact a valid model before continuing. + // (it can be invalid as a result of failing validation in Backbone.Collection._prepareModel) + if (!( model instanceof Backbone.Model )) { + return; + } + + options = this.sanitizeOptions(options); + + _.each(this.getReverseRelations(model), function (relation) { + relation.addRelated(this.instance, options); + }, this); + + // Only trigger 'add' once the newly added model is initialized (so, has it's relations set up) + var dit = this; + Backbone.Relational.eventQueue.add(function () { + !options.silentChange && dit.instance.trigger('add:' + dit.key, model, dit.related, options); + }); + }, + + /** + * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations. + * (should be 'HasOne', which should be nullified) + */ + handleRemoval:function (model, coll, options) { + //console.debug('handleRemoval called; args=%o', arguments); + if (!( model instanceof Backbone.Model )) { + return; + } + + options = this.sanitizeOptions(options); + + _.each(this.getReverseRelations(model), function (relation) { + relation.removeRelated(this.instance, options); + }, this); + + var dit = this; + Backbone.Relational.eventQueue.add(function () { + !options.silentChange && dit.instance.trigger('remove:' + dit.key, model, dit.related, options); + }); + }, + + handleReset:function (coll, options) { + options = this.sanitizeOptions(options); + + var dit = this; + Backbone.Relational.eventQueue.add(function () { + !options.silentChange && dit.instance.trigger('reset:' + dit.key, dit.related, options); + }); + }, + + addRelated:function (model, options) { + var dit = this; + options = this.unsanitizeOptions(options); + model.queue(function () { // Queued to avoid errors for adding 'model' to the 'this.related' set twice + if (dit.related && !dit.related.getByCid(model) && !dit.related.get(model)) { + dit.related.add(model, options); + } + }); + }, + + removeRelated:function (model, options) { + options = this.unsanitizeOptions(options); + if (this.related.getByCid(model) || this.related.get(model)) { + this.related.remove(model, options); + } + } + }); + + /** + * A type of Backbone.Model that also maintains relations to other models and collections. + * New events when compared to the original: + * - 'add:' (model, related collection, options) + * - 'remove:' (model, related collection, options) + * - 'update:' (model, related model or collection, options) + */ + Backbone.RelationalModel = Backbone.Model.extend({ + relations:null, // Relation descriptions on the prototype + _relations:null, // Relation instances + _isInitialized:false, + _deferProcessing:false, + _queue:null, + + constructor:function (attributes, options) { + // Nasty hack, for cases like 'model.get( ).add( item )'. + // Defer 'processQueue', so that when 'Relation.createModels' is used we: + // a) Survive 'Backbone.Collection.add'; this takes care we won't error on "can't add model to a set twice" + // (by creating a model from properties, having the model add itself to the collection via one of + // it's relations, then trying to add it to the collection). + // b) Trigger 'HasMany' collection events only after the model is really fully set up. + // Example that triggers both a and b: "p.get('jobs').add( { company: c, person: p } )". + var dit = this; + if (options && options.collection) { + this._deferProcessing = true; + + var processQueue = function (model) { + if (model === dit) { + dit._deferProcessing = false; + dit.processQueue(); + options.collection.unbind('relational:add', processQueue); + } + }; + options.collection.bind('relational:add', processQueue); + + // So we do process the queue eventually, regardless of whether this model really gets added to 'options.collection'. + _.defer(function () { + processQueue(dit); + }); + } + + this._queue = new Backbone.BlockingQueue(); + this._queue.block(); + Backbone.Relational.eventQueue.block(); + + Backbone.Model.prototype.constructor.apply(this, arguments); + + // Try to run the global queue holding external events + Backbone.Relational.eventQueue.unblock(); + }, + + /** + * Override 'trigger' to queue 'change' and 'change:*' events + */ + trigger:function (eventName) { + if (eventName.length > 5 && 'change' === eventName.substr(0, 6)) { + var dit = this, args = arguments; + Backbone.Relational.eventQueue.add(function () { + Backbone.Model.prototype.trigger.apply(dit, args); + }); + } + else { + Backbone.Model.prototype.trigger.apply(this, arguments); + } + + return this; + }, + + /** + * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance. + * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor). + */ + initializeRelations:function () { + this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once + this._relations = []; + + _.each(this.relations, function (rel) { + var type = !_.isString(rel.type) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName(rel.type); + if (type && type.prototype instanceof Backbone.Relation.prototype.constructor) { + new type(this, rel); // Also pushes the new Relation into _relations + } + else { + Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn('Relation=%o; missing or invalid type!', rel); + } + }, this); + + this._isInitialized = true; + this.release(); + this.processQueue(); + }, + + /** + * When new values are set, notify this model's relations (also if options.silent is set). + * (Relation.setRelated locks this model before calling 'set' on it to prevent loops) + */ + updateRelations:function (options) { + if (this._isInitialized && !this.isLocked()) { + _.each(this._relations, function (rel) { + var val = this.attributes[ rel.key ]; + if (rel.related !== val) { + this.trigger('relational:change:' + rel.key, this, val, options || {}); + } + }, this); + } + }, + + /** + * Either add to the queue (if we're not initialized yet), or execute right away. + */ + queue:function (func) { + this._queue.add(func); + }, + + /** + * Process _queue + */ + processQueue:function () { + if (this._isInitialized && !this._deferProcessing && this._queue.isBlocked()) { + this._queue.unblock(); + } + }, + + /** + * Get a specific relation. + * @param key {string} The relation key to look for. + * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'key', or null. + */ + getRelation:function (key) { + return _.detect(this._relations, function (rel) { + if (rel.key === key) { + return true; + } + }, this); + }, + + /** + * Get all of the created relations. + * @return {Backbone.Relation[]} + */ + getRelations:function () { + return this._relations; + }, + + /** + * Retrieve related objects. + * @param key {string} The relation key to fetch models for. + * @param options {object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'. + * @return {jQuery.when[]} An array of request objects + */ + fetchRelated:function (key, options) { + options || ( options = {} ); + var setUrl, + requests = [], + rel = this.getRelation(key), + keyContents = rel && rel.keyContents, + toFetch = keyContents && _.select(_.isArray(keyContents) ? keyContents : [ keyContents ], function (item) { + var id = _.isString(item) || _.isNumber(item) ? item : item[ rel.relatedModel.prototype.idAttribute ]; + return id && !Backbone.Relational.store.find(rel.relatedModel, id); + }, this); + + if (toFetch && toFetch.length) { + // Create a model for each entry in 'keyContents' that is to be fetched + var models = _.map(toFetch, function (item) { + var model; + + if (typeof( item ) === 'object') { + model = new rel.relatedModel(item); + } + else { + var attrs = {}; + attrs[ rel.relatedModel.prototype.idAttribute ] = item; + model = new rel.relatedModel(attrs); + } + + return model; + }, this); + + // Try if the 'collection' can provide a url to fetch a set of models in one request. + if (rel.related instanceof Backbone.Collection && _.isFunction(rel.related.url)) { + setUrl = rel.related.url(models); + } + + // An assumption is that when 'Backbone.Collection.url' is a function, it can handle building of set urls. + // To make sure it can, test if the url we got by supplying a list of models to fetch is different from + // the one supplied for the default fetch action (without args to 'url'). + if (setUrl && setUrl !== rel.related.url()) { + var opts = _.defaults( + { + error:function () { + var args = arguments; + _.each(models, function (model) { + model.trigger('destroy', model, model.collection, options); + options.error && options.error.apply(model, args); + }); + }, + url:setUrl + }, + options, + { add:true } + ); + + requests = [ rel.related.fetch(opts) ]; + } + else { + requests = _.map(models, function (model) { + var opts = _.defaults( + { + error:function () { + model.trigger('destroy', model, model.collection, options); + options.error && options.error.apply(model, arguments); + } + }, + options + ); + return model.fetch(opts); + }, this); + } + } + + return requests; + }, + + set:function (key, value, options) { + Backbone.Relational.eventQueue.block(); + + // Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object + var attributes; + if (_.isObject(key) || key == null) { + attributes = key; + options = value; + } + else { + attributes = {}; + attributes[ key ] = value; + } + + var result = Backbone.Model.prototype.set.apply(this, arguments); + + // 'set' is called quite late in 'Backbone.Model.prototype.constructor', but before 'initialize'. + // Ideal place to set up relations :) + if (!this._isInitialized && !this.isLocked()) { + Backbone.Relational.store.register(this); + this.initializeRelations(); + } + // Update the 'idAttribute' in Backbone.store if; we don't want it to miss an 'id' update due to {silent:true} + else if (attributes && this.idAttribute in attributes) { + Backbone.Relational.store.update(this); + } + + if (attributes) { + this.updateRelations(options); + } + + // Try to run the global queue holding external events + Backbone.Relational.eventQueue.unblock(); + + return result; + }, + + unset:function (attribute, options) { + Backbone.Relational.eventQueue.block(); + + var result = Backbone.Model.prototype.unset.apply(this, arguments); + this.updateRelations(options); + + // Try to run the global queue holding external events + Backbone.Relational.eventQueue.unblock(); + + return result; + }, + + clear:function (options) { + Backbone.Relational.eventQueue.block(); + + var result = Backbone.Model.prototype.clear.apply(this, arguments); + this.updateRelations(options); + + // Try to run the global queue holding external events + Backbone.Relational.eventQueue.unblock(); + + return result; + }, + + /** + * Override 'change', so the change will only execute after 'set' has finised (relations are updated), + * and 'previousAttributes' will be available when the event is fired. + */ + change:function (options) { + var dit = this; + Backbone.Relational.eventQueue.add(function () { + Backbone.Model.prototype.change.apply(dit, arguments); + }); + }, + + clone:function () { + var attributes = _.clone(this.attributes); + if (!_.isUndefined(attributes[ this.idAttribute ])) { + attributes[ this.idAttribute ] = null; + } + + _.each(this.getRelations(), function (rel) { + delete attributes[ rel.key ]; + }); + + return new this.constructor(attributes); + }, + + /** + * Convert relations to JSON, omits them when required + */ + toJSON:function () { + // If this Model has already been fully serialized in this branch once, return to avoid loops + if (this.isLocked()) { + return this.id; + } + + this.acquire(); + var json = Backbone.Model.prototype.toJSON.call(this); + + _.each(this._relations, function (rel) { + var value = json[ rel.key ]; + + if (rel.options.includeInJSON === true && value && _.isFunction(value.toJSON)) { + json[ rel.keySource ] = value.toJSON(); + } + else if (_.isString(rel.options.includeInJSON)) { + if (value instanceof Backbone.Collection) { + json[ rel.keySource ] = value.pluck(rel.options.includeInJSON); + } + else if (value instanceof Backbone.Model) { + json[ rel.keySource ] = value.get(rel.options.includeInJSON); + } + } + else { + delete json[ rel.key ]; + } + + if (rel.keySource !== rel.key) { + delete json[ rel.key ]; + } + }, this); + + this.release(); + return json; + } + }); + _.extend(Backbone.RelationalModel.prototype, Backbone.Semaphore); + + /** + * Override Backbone.Collection.add, so objects fetched from the server multiple times will + * update the existing Model. Also, trigger 'relational:add'. + */ + var add = Backbone.Collection.prototype.__add = Backbone.Collection.prototype.add; + Backbone.Collection.prototype.add = function (models, options) { + options || (options = {}); + if (!_.isArray(models)) { + models = [ models ]; + } + + var modelsToAdd = []; + + //console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options ); + _.each(models, function (model) { + if (!( model instanceof Backbone.Model )) { + // Try to find 'model' in Backbone.store. If it already exists, set the new properties on it. + var existingModel = Backbone.Relational.store.find(this.model, model[ this.model.prototype.idAttribute ]); + if (existingModel) { + existingModel.set(existingModel.parse ? existingModel.parse(model) : model, options); + model = existingModel; + } + else { + model = Backbone.Collection.prototype._prepareModel.call(this, model, options); + } + } + + if (model instanceof Backbone.Model && !this.get(model) && !this.getByCid(model)) { + modelsToAdd.push(model); + } + }, this); + + + // Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc). + if (modelsToAdd.length) { + add.call(this, modelsToAdd, options); + + _.each(modelsToAdd, function (model) { + this.trigger('relational:add', model, this, options); + }, this); + } + + return this; + }; + + /** + * Override 'Backbone.Collection.remove' to trigger 'relational:remove'. + */ + var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove; + Backbone.Collection.prototype.remove = function (models, options) { + options || (options = {}); + if (!_.isArray(models)) { + models = [ models ]; + } + + //console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options ); + _.each(models, function (model) { + model = this.getByCid(model) || this.get(model); + + if (model instanceof Backbone.Model) { + remove.call(this, model, options); + this.trigger('relational:remove', model, this, options); + } + }, this); + + return this; + }; + + /** + * Override 'Backbone.Collection.reset' to trigger 'relational:reset'. + */ + var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset; + Backbone.Collection.prototype.reset = function (models, options) { + reset.call(this, models, options); + this.trigger('relational:reset', models, options); + + return this; + }; + + /** + * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations + * are ready. + */ + var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger; + Backbone.Collection.prototype.trigger = function (eventName) { + if (eventName === 'add' || eventName === 'remove' || eventName === 'reset') { + var dit = this, args = arguments; + Backbone.Relational.eventQueue.add(function () { + trigger.apply(dit, args); + }); + } + else { + trigger.apply(this, arguments); + } + + return this; + }; + + // Override .extend() to check for reverseRelations to initialize. + Backbone.RelationalModel.extend = function (protoProps, classProps) { + var child = Backbone.Model.extend.apply(this, arguments); + + var relations = ( protoProps && protoProps.relations ) || []; + _.each(relations, function (rel) { + if (rel.reverseRelation) { + rel.model = child; + + var preInitialize = true; + if (_.isString(rel.relatedModel)) { + /** + * The related model might not be defined for two reasons + * 1. it never gets defined, e.g. a typo + * 2. it is related to itself + * In neither of these cases do we need to pre-initialize reverse relations. + */ + var relatedModel = Backbone.Relational.store.getObjectByName(rel.relatedModel); + preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel.prototype.constructor ); + } + + var type = !_.isString(rel.type) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName(rel.type); + if (preInitialize && type && type.prototype instanceof Backbone.Relation.prototype.constructor) { + new type(null, rel); + } + } + }); + + return child; + }; + +})); diff --git a/app/js/libs/backbone/backbone.collection-view-binder.js b/app/js/libs/backbone/backbone.collection-view-binder.js new file mode 100755 index 0000000..67a51a1 --- /dev/null +++ b/app/js/libs/backbone/backbone.collection-view-binder.js @@ -0,0 +1,250 @@ +// Backbone.CollectionViewBinder v0.1.0 +// (c) 2012 Bart Wood +// Distributed Under MIT License + +(function () { + + if (!Backbone) { + throw 'Please include Backbone.js before Backbone.ModelBinder.js'; + } + + if (!Backbone.ModelBinder) { + throw 'Please include Backbone.ModelBinder.js before Backbone.CollectionViewBinder.js'; + } + + Backbone.CollectionViewBinder = function (elManagerFactory) { + _.bindAll(this); + + this._elManagerFactory = elManagerFactory; + if (!this._elManagerFactory) throw 'elManagerFactory must be defined.'; + + // Let the factory just use the trigger function on the view binder + this._elManagerFactory.trigger = this.trigger; + }; + + Backbone.CollectionViewBinder.VERSION = '0.1.0'; + + _.extend(Backbone.CollectionViewBinder.prototype, Backbone.Events, { + createBoundEls:function (collection, parentEl) { + this.unbind(); + + if (!collection) throw 'collection must be defined'; + if (!parentEl) throw 'parentEl must be defined'; + + this._collection = collection; + this._elManagerFactory.setParentEl(parentEl); + + this._collection.each(function (model) { + this._onCollectionAdd(model); + }, this); + + this._collection.on('add', this._onCollectionAdd, this); + this._collection.on('remove', this._onCollectionRemove, this); + this._collection.on('reset', this._onCollectionReset, this); + + }, + + unbind:function () { + if (this._collection !== undefined) { + this._collection.off('add', this._onCollectionAdd); + this._collection.off('remove', this._onCollectionRemove); + this._collection.off('reset', this._onCollectionReset); + } + + this._removeAllElManagers(); + }, + + getManagerForEl:function (el) { + var i, elManager, elManagers = _.values(this._elManagers); + + for (i = 0; i < elManagers.length; i++) { + elManager = elManagers[i]; + + if (elManager.isElContained(el)) { + return elManager; + } + } + + return undefined; + }, + + getManagerForModel:function (model) { + var i, elManager, elManagers = _.values(this._elManagers); + + for (i = 0; i < elManagers.length; i++) { + elManager = elManagers[i]; + + if (elManager.getModel() === model) { + return elManager; + } + } + + return undefined; + }, + + _onCollectionAdd:function (model) { + this._elManagers[model.cid] = this._elManagerFactory.makeElManager(model); + this._elManagers[model.cid].createEl(); + }, + + _onCollectionRemove:function (model) { + this._removeElManager(model); + }, + + _onCollectionReset:function () { + this._removeAllElManagers(); + + this._collection.each(function (model) { + this._onCollectionAdd(model); + }, this); + }, + + _removeAllElManagers:function () { + _.each(this._elManagers, function (elManager) { + elManager.removeEl(); + delete this._elManagers[elManager._model.cid]; + }, this); + + delete this._elManagers; + this._elManagers = {}; + }, + + _removeElManager:function (model) { + if (this._elManagers[model.cid] !== undefined) { + this._elManagers[model.cid].removeEl(); + delete this._elManagers[model.cid]; + } + } + }); + + // The DefaultElManagerFactory is used for els that are just html templates + // elHtml - how the model's html will be rendered. Must have a single root element (div,span). + // bindings (optional) - either a string which is the binding attribute (name, id, data-name, etc.) or a normal bindings hash + Backbone.CollectionViewBinder.ElManagerFactory = function (elHtml, bindings) { + _.bindAll(this); + + this._elHtml = elHtml; + this._bindings = bindings; + + if (!_.isString(this._elHtml)) throw 'elHtml must be a valid html string'; + }; + + _.extend(Backbone.CollectionViewBinder.ElManagerFactory.prototype, { + setParentEl:function (parentEl) { + this._parentEl = parentEl; + }, + + makeElManager:function (model) { + + var elManager = { + _model:model, + + createEl:function () { + + this._el = $(this._elHtml); + $(this._parentEl).append(this._el); + + if (this._bindings) { + if (_.isString(this._bindings)) { + this._modelBinder = new Backbone.ModelBinder(); + this._modelBinder.bind(this._model, this._el, Backbone.ModelBinder.createDefaultBindings(this._el, this._bindings)); + } + else if (_.isObject(this._bindings)) { + this._modelBinder = new Backbone.ModelBinder(); + this._modelBinder.bind(this._model, this._el, this._bindings); + } + else { + throw 'Unsupported bindings type, please use a boolean or a bindings hash'; + } + } + + this.trigger('elCreated', this._model, this._el); + }, + + removeEl:function () { + if (this._modelBinder !== undefined) { + this._modelBinder.unbind(); + } + + this._el.remove(); + this.trigger('elRemoved', this._model, this._el); + }, + + isElContained:function (findEl) { + return this._el === findEl || $(this._el).has(findEl).length > 0; + }, + + getModel:function () { + return this._model; + }, + + getEl:function () { + return this._el; + } + }; + + _.extend(elManager, this); + return elManager; + } + }); + + + // The ElManagerFactory is used for els that are created and owned by backbone views. + // There is no bindings option because the view made by the viewCreator should take care of any binding + // viewCreator - a callback that will create backbone view instances for a model passed to the callback + Backbone.CollectionViewBinder.ViewManagerFactory = function (viewCreator) { + _.bindAll(this); + this._viewCreator = viewCreator; + + if (!_.isFunction(this._viewCreator)) throw 'viewCreator must be a valid function that accepts a model and returns a backbone view'; + }; + + _.extend(Backbone.CollectionViewBinder.ViewManagerFactory.prototype, { + setParentEl:function (parentEl) { + this._parentEl = parentEl; + }, + + makeElManager:function (model) { + var elManager = { + + _model:model, + + createEl:function () { + this._view = this._viewCreator(model); + $(this._parentEl).append(this._view.render(this._model).el); + + this.trigger('elCreated', this._model, this._view); + }, + + removeEl:function () { + if (this._view.close !== undefined) { + this._view.close(); + } + else { + this._view.$el.remove(); + console.log('warning, you should implement a close() function for your view, you might end up with zombies'); + } + + this.trigger('elRemoved', this._model, this._view); + }, + + isElContained:function (findEl) { + return this._view.el === findEl || this._view.$el.has(findEl).length > 0; + }, + + getModel:function () { + return this._model; + }, + + getEl:function () { + return this._view.el; + } + }; + + _.extend(elManager, this); + + return elManager; + } + }); + +}).call(this); diff --git a/app/js/libs/backbone/backbone.js b/app/js/libs/backbone/backbone.js new file mode 100644 index 0000000..955bbab --- /dev/null +++ b/app/js/libs/backbone/backbone.js @@ -0,0 +1,1439 @@ +// Backbone.js 0.9.2 + +// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org + +(function (root, factory) { + // Set up Backbone appropriately for the environment. + if (typeof exports !== 'undefined') { + // Node/CommonJS, no need for jQuery in that case. + factory(root, exports, require('underscore')); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(['underscore', 'jquery', 'exports'], function (_, $, exports) { + // Export global even in AMD case in case this script is loaded with + // others that may still expect a global Backbone. + root.Backbone = factory(root, exports, _, $); + }); + } else { + // Browser globals + root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender)); + } +}(this, function (root, Backbone, _, $) { + + // Initial Setup + // ------------- + + // Save the previous value of the `Backbone` variable, so that it can be + // restored later on, if `noConflict` is used. + var previousBackbone = root.Backbone; + + // Create a local reference to slice/splice. + var slice = Array.prototype.slice; + var splice = Array.prototype.splice; + + // Current version of the library. Keep in sync with `package.json`. + Backbone.VERSION = '0.9.2'; + + // Set the JavaScript library that will be used for DOM manipulation and + // Ajax calls (a.k.a. the `$` variable). By default Backbone will use: jQuery, + // Zepto, or Ender; but the `setDomLibrary()` method lets you inject an + // alternate JavaScript library (or a mock library for testing your views + // outside of a browser). + Backbone.setDomLibrary = function (lib) { + $ = lib; + }; + + // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable + // to its previous owner. Returns a reference to this Backbone object. + Backbone.noConflict = function () { + root.Backbone = previousBackbone; + return Backbone; + }; + + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option + // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and + // set a `X-Http-Method-Override` header. + Backbone.emulateHTTP = false; + + // Turn on `emulateJSON` to support legacy servers that can't deal with direct + // `application/json` requests ... will encode the body as + // `application/x-www-form-urlencoded` instead and will send the model in a + // form param named `model`. + Backbone.emulateJSON = false; + + // Backbone.Events + // ----------------- + + // Regular expression used to split event strings + var eventSplitter = /\s+/; + + // A module that can be mixed in to *any object* in order to provide it with + // custom events. You may bind with `on` or remove with `off` callback functions + // to an event; trigger`-ing an event fires all callbacks in succession. + // + // var object = {}; + // _.extend(object, Backbone.Events); + // object.on('expand', function(){ alert('expanded'); }); + // object.trigger('expand'); + // + var Events = Backbone.Events = { + + // Bind one or more space separated events, `events`, to a `callback` + // function. Passing `"all"` will bind the callback to all events fired. + on:function (events, callback, context) { + + var calls, event, node, tail, list; + if (!callback) return this; + events = events.split(eventSplitter); + calls = this._callbacks || (this._callbacks = {}); + + // Create an immutable callback list, allowing traversal during + // modification. The tail is an empty object that will always be used + // as the next node. + while (event = events.shift()) { + list = calls[event]; + node = list ? list.tail : {}; + node.next = tail = {}; + node.context = context; + node.callback = callback; + calls[event] = {tail:tail, next:list ? list.next : node}; + } + + return this; + }, + + // Remove one or many callbacks. If `context` is null, removes all callbacks + // with that function. If `callback` is null, removes all callbacks for the + // event. If `events` is null, removes all bound callbacks for all events. + off:function (events, callback, context) { + var event, calls, node, tail, cb, ctx; + + // No events, or removing *all* events. + if (!(calls = this._callbacks)) return; + if (!(events || callback || context)) { + delete this._callbacks; + return this; + } + + // Loop through the listed events and contexts, splicing them out of the + // linked list of callbacks if appropriate. + events = events ? events.split(eventSplitter) : _.keys(calls); + while (event = events.shift()) { + node = calls[event]; + delete calls[event]; + if (!node || !(callback || context)) continue; + // Create a new list, omitting the indicated callbacks. + tail = node.tail; + while ((node = node.next) !== tail) { + cb = node.callback; + ctx = node.context; + if ((callback && cb !== callback) || (context && ctx !== context)) { + this.on(event, cb, ctx); + } + } + } + + return this; + }, + + // Trigger one or many events, firing all bound callbacks. Callbacks are + // passed the same arguments as `trigger` is, apart from the event name + // (unless you're listening on `"all"`, which will cause your callback to + // receive the true name of the event as the first argument). + trigger:function (events) { + var event, node, calls, tail, args, all, rest; + if (!(calls = this._callbacks)) return this; + all = calls.all; + events = events.split(eventSplitter); + rest = slice.call(arguments, 1); + + // For each event, walk through the linked list of callbacks twice, + // first to trigger the event, then to trigger any `"all"` callbacks. + while (event = events.shift()) { + if (node = calls[event]) { + tail = node.tail; + while ((node = node.next) !== tail) { + node.callback.apply(node.context || this, rest); + } + } + if (node = all) { + tail = node.tail; + args = [event].concat(rest); + while ((node = node.next) !== tail) { + node.callback.apply(node.context || this, args); + } + } + } + + return this; + } + + }; + + // Aliases for backwards compatibility. + Events.bind = Events.on; + Events.unbind = Events.off; + + // Backbone.Model + // -------------- + + // Create a new model, with defined attributes. A client id (`cid`) + // is automatically generated and assigned for you. + var Model = Backbone.Model = function (attributes, options) { + var defaults; + attributes || (attributes = {}); + if (options && options.parse) attributes = this.parse(attributes); + if (defaults = getValue(this, 'defaults')) { + attributes = _.extend({}, defaults, attributes); + } + if (options && options.collection) this.collection = options.collection; + this.attributes = {}; + this._escapedAttributes = {}; + this.cid = _.uniqueId('c'); + this.changed = {}; + this._silent = {}; + this._pending = {}; + this.set(attributes, {silent:true}); + // Reset change tracking. + this.changed = {}; + this._silent = {}; + this._pending = {}; + this._previousAttributes = _.clone(this.attributes); + this.initialize.apply(this, arguments); + }; + + // Attach all inheritable methods to the Model prototype. + _.extend(Model.prototype, Events, { + + // A hash of attributes whose current and previous value differ. + changed:null, + + // A hash of attributes that have silently changed since the last time + // `change` was called. Will become pending attributes on the next call. + _silent:null, + + // A hash of attributes that have changed since the last `'change'` event + // began. + _pending:null, + + // The default name for the JSON `id` attribute is `"id"`. MongoDB and + // CouchDB users may want to set this to `"_id"`. + idAttribute:'id', + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize:function () { + }, + + // Return a copy of the model's `attributes` object. + toJSON:function (options) { + return _.clone(this.attributes); + }, + + // Get the value of an attribute. + get:function (attr) { + return this.attributes[attr]; + }, + + // Get the HTML-escaped value of an attribute. + escape:function (attr) { + var html; + if (html = this._escapedAttributes[attr]) return html; + var val = this.get(attr); + return this._escapedAttributes[attr] = _.escape(val == null ? '' : '' + val); + }, + + // Returns `true` if the attribute contains a value that is not null + // or undefined. + has:function (attr) { + return this.get(attr) != null; + }, + + // Set a hash of model attributes on the object, firing `"change"` unless + // you choose to silence it. + set:function (key, value, options) { + var attrs, attr, val; + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (_.isObject(key) || key == null) { + attrs = key; + options = value; + } else { + attrs = {}; + attrs[key] = value; + } + + // Extract attributes and options. + options || (options = {}); + if (!attrs) return this; + if (attrs instanceof Model) attrs = attrs.attributes; + if (options.unset) for (attr in attrs) attrs[attr] = void 0; + + // Run validation. + if (!this._validate(attrs, options)) return false; + + // Check for changes of `id`. + if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; + + var changes = options.changes = {}; + var now = this.attributes; + var escaped = this._escapedAttributes; + var prev = this._previousAttributes || {}; + + // For each `set` attribute... + for (attr in attrs) { + val = attrs[attr]; + + // If the new and current value differ, record the change. + if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) { + delete escaped[attr]; + (options.silent ? this._silent : changes)[attr] = true; + } + + // Update or delete the current value. + options.unset ? delete now[attr] : now[attr] = val; + + // If the new and previous value differ, record the change. If not, + // then remove changes for this attribute. + if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) { + this.changed[attr] = val; + if (!options.silent) this._pending[attr] = true; + } else { + delete this.changed[attr]; + delete this._pending[attr]; + } + } + + // Fire the `"change"` events. + if (!options.silent) this.change(options); + return this; + }, + + // Remove an attribute from the model, firing `"change"` unless you choose + // to silence it. `unset` is a noop if the attribute doesn't exist. + unset:function (attr, options) { + (options || (options = {})).unset = true; + return this.set(attr, null, options); + }, + + // Clear all attributes on the model, firing `"change"` unless you choose + // to silence it. + clear:function (options) { + (options || (options = {})).unset = true; + return this.set(_.clone(this.attributes), options); + }, + + // Fetch the model from the server. If the server's representation of the + // model differs from its current attributes, they will be overriden, + // triggering a `"change"` event. + fetch:function (options) { + options = options ? _.clone(options) : {}; + var model = this; + var success = options.success; + options.success = function (resp, status, xhr) { + if (!model.set(model.parse(resp, xhr), options)) return false; + if (success) success(model, resp); + }; + options.error = Backbone.wrapError(options.error, model, options); + return (this.sync || Backbone.sync).call(this, 'read', this, options); + }, + + // Set a hash of model attributes, and sync the model to the server. + // If the server returns an attributes hash that differs, the model's + // state will be `set` again. + save:function (key, value, options) { + var attrs, current; + + // Handle both `("key", value)` and `({key: value})` -style calls. + if (_.isObject(key) || key == null) { + attrs = key; + options = value; + } else { + attrs = {}; + attrs[key] = value; + } + options = options ? _.clone(options) : {}; + + // If we're "wait"-ing to set changed attributes, validate early. + if (options.wait) { + if (!this._validate(attrs, options)) return false; + current = _.clone(this.attributes); + } + + // Regular saves `set` attributes before persisting to the server. + var silentOptions = _.extend({}, options, {silent:true}); + if (attrs && !this.set(attrs, options.wait ? silentOptions : options)) { + return false; + } + + // After a successful server-side save, the client is (optionally) + // updated with the server-side state. + var model = this; + var success = options.success; + options.success = function (resp, status, xhr) { + var serverAttrs = model.parse(resp, xhr); + if (options.wait) { + delete options.wait; + serverAttrs = _.extend(attrs || {}, serverAttrs); + } + if (!model.set(serverAttrs, options)) return false; + if (success) { + success(model, resp); + } else { + model.trigger('sync', model, resp, options); + } + }; + + // Finish configuring and sending the Ajax request. + options.error = Backbone.wrapError(options.error, model, options); + var method = this.isNew() ? 'create' : 'update'; + var xhr = (this.sync || Backbone.sync).call(this, method, this, options); + if (options.wait) this.set(current, silentOptions); + return xhr; + }, + + // Destroy this model on the server if it was already persisted. + // Optimistically removes the model from its collection, if it has one. + // If `wait: true` is passed, waits for the server to respond before removal. + destroy:function (options) { + options = options ? _.clone(options) : {}; + var model = this; + var success = options.success; + + var triggerDestroy = function () { + model.trigger('destroy', model, model.collection, options); + }; + + if (this.isNew()) { + triggerDestroy(); + return false; + } + + options.success = function (resp) { + if (options.wait) triggerDestroy(); + if (success) { + success(model, resp); + } else { + model.trigger('sync', model, resp, options); + } + }; + + options.error = Backbone.wrapError(options.error, model, options); + var xhr = (this.sync || Backbone.sync).call(this, 'delete', this, options); + if (!options.wait) triggerDestroy(); + return xhr; + }, + + // Default URL for the model's representation on the server -- if you're + // using Backbone's restful methods, override this to change the endpoint + // that will be called. + url:function () { + var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError(); + if (this.isNew()) return base; + return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id); + }, + + // **parse** converts a response into the hash of attributes to be `set` on + // the model. The default implementation is just to pass the response along. + parse:function (resp, xhr) { + return resp; + }, + + // Create a new model with identical attributes to this one. + clone:function () { + return new this.constructor(this.attributes); + }, + + // A model is new if it has never been saved to the server, and lacks an id. + isNew:function () { + return this.id == null; + }, + + // Call this method to manually fire a `"change"` event for this model and + // a `"change:attribute"` event for each changed attribute. + // Calling this will cause all objects observing the model to update. + change:function (options) { + options || (options = {}); + var changing = this._changing; + this._changing = true; + + // Silent changes become pending changes. + for (var attr in this._silent) this._pending[attr] = true; + + // Silent changes are triggered. + var changes = _.extend({}, options.changes, this._silent); + this._silent = {}; + for (var attr in changes) { + this.trigger('change:' + attr, this, this.get(attr), options); + } + if (changing) return this; + + // Continue firing `"change"` events while there are pending changes. + while (!_.isEmpty(this._pending)) { + this._pending = {}; + this.trigger('change', this, options); + // Pending and silent changes still remain. + for (var attr in this.changed) { + if (this._pending[attr] || this._silent[attr]) continue; + delete this.changed[attr]; + } + this._previousAttributes = _.clone(this.attributes); + } + + this._changing = false; + return this; + }, + + // Determine if the model has changed since the last `"change"` event. + // If you specify an attribute name, determine if that attribute has changed. + hasChanged:function (attr) { + if (!arguments.length) return !_.isEmpty(this.changed); + return _.has(this.changed, attr); + }, + + // Return an object containing all the attributes that have changed, or + // false if there are no changed attributes. Useful for determining what + // parts of a view need to be updated and/or what attributes need to be + // persisted to the server. Unset attributes will be set to undefined. + // You can also pass an attributes object to diff against the model, + // determining if there *would be* a change. + changedAttributes:function (diff) { + if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; + var val, changed = false, old = this._previousAttributes; + for (var attr in diff) { + if (_.isEqual(old[attr], (val = diff[attr]))) continue; + (changed || (changed = {}))[attr] = val; + } + return changed; + }, + + // Get the previous value of an attribute, recorded at the time the last + // `"change"` event was fired. + previous:function (attr) { + if (!arguments.length || !this._previousAttributes) return null; + return this._previousAttributes[attr]; + }, + + // Get all of the attributes of the model at the time of the previous + // `"change"` event. + previousAttributes:function () { + return _.clone(this._previousAttributes); + }, + + // Check if the model is currently in a valid state. It's only possible to + // get into an *invalid* state if you're using silent changes. + isValid:function () { + return !this.validate(this.attributes); + }, + + // Run validation against the next complete set of model attributes, + // returning `true` if all is well. If a specific `error` callback has + // been passed, call that instead of firing the general `"error"` event. + _validate:function (attrs, options) { + if (options.silent || !this.validate) return true; + attrs = _.extend({}, this.attributes, attrs); + var error = this.validate(attrs, options); + if (!error) return true; + if (options && options.error) { + options.error(this, error, options); + } else { + this.trigger('error', this, error, options); + } + return false; + } + + }); + + // Backbone.Collection + // ------------------- + + // Provides a standard collection class for our sets of models, ordered + // or unordered. If a `comparator` is specified, the Collection will maintain + // its models in sort order, as they're added and removed. + var Collection = Backbone.Collection = function (models, options) { + options || (options = {}); + if (options.model) this.model = options.model; + if (options.comparator) this.comparator = options.comparator; + this._reset(); + this.initialize.apply(this, arguments); + if (models) this.reset(models, {silent:true, parse:options.parse}); + }; + + // Define the Collection's inheritable methods. + _.extend(Collection.prototype, Events, { + + // The default model for a collection is just a **Backbone.Model**. + // This should be overridden in most cases. + model:Model, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize:function () { + }, + + // The JSON representation of a Collection is an array of the + // models' attributes. + toJSON:function (options) { + return this.map(function (model) { + return model.toJSON(options); + }); + }, + + // Add a model, or list of models to the set. Pass **silent** to avoid + // firing the `add` event for every new model. + add:function (models, options) { + var i, index, length, model, cid, id, cids = {}, ids = {}, dups = []; + options || (options = {}); + models = _.isArray(models) ? models.slice() : [models]; + + // Begin by turning bare objects into model references, and preventing + // invalid models or duplicate models from being added. + for (i = 0, length = models.length; i < length; i++) { + if (!(model = models[i] = this._prepareModel(models[i], options))) { + throw new Error("Can't add an invalid model to a collection"); + } + cid = model.cid; + id = model.id; + if (cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) { + dups.push(i); + continue; + } + cids[cid] = ids[id] = model; + } + + // Remove duplicates. + i = dups.length; + while (i--) { + models.splice(dups[i], 1); + } + + // Listen to added models' events, and index models for lookup by + // `id` and by `cid`. + for (i = 0, length = models.length; i < length; i++) { + (model = models[i]).on('all', this._onModelEvent, this); + this._byCid[model.cid] = model; + if (model.id != null) this._byId[model.id] = model; + } + + // Insert models into the collection, re-sorting if needed, and triggering + // `add` events unless silenced. + this.length += length; + index = options.at != null ? options.at : this.models.length; + splice.apply(this.models, [index, 0].concat(models)); + if (this.comparator) this.sort({silent:true}); + if (options.silent) return this; + for (i = 0, length = this.models.length; i < length; i++) { + if (!cids[(model = this.models[i]).cid]) continue; + options.index = i; + model.trigger('add', model, this, options); + } + return this; + }, + + // Remove a model, or a list of models from the set. Pass silent to avoid + // firing the `remove` event for every model removed. + remove:function (models, options) { + var i, l, index, model; + options || (options = {}); + models = _.isArray(models) ? models.slice() : [models]; + for (i = 0, l = models.length; i < l; i++) { + model = this.getByCid(models[i]) || this.get(models[i]); + if (!model) continue; + delete this._byId[model.id]; + delete this._byCid[model.cid]; + index = this.indexOf(model); + this.models.splice(index, 1); + this.length--; + if (!options.silent) { + options.index = index; + model.trigger('remove', model, this, options); + } + this._removeReference(model); + } + return this; + }, + + // Add a model to the end of the collection. + push:function (model, options) { + model = this._prepareModel(model, options); + this.add(model, options); + return model; + }, + + // Remove a model from the end of the collection. + pop:function (options) { + var model = this.at(this.length - 1); + this.remove(model, options); + return model; + }, + + // Add a model to the beginning of the collection. + unshift:function (model, options) { + model = this._prepareModel(model, options); + this.add(model, _.extend({at:0}, options)); + return model; + }, + + // Remove a model from the beginning of the collection. + shift:function (options) { + var model = this.at(0); + this.remove(model, options); + return model; + }, + + // Get a model from the set by id. + get:function (id) { + if (id == null) return void 0; + return this._byId[id.id != null ? id.id : id]; + }, + + // Get a model from the set by client id. + getByCid:function (cid) { + return cid && this._byCid[cid.cid || cid]; + }, + + // Get the model at the given index. + at:function (index) { + return this.models[index]; + }, + + // Return models with matching attributes. Useful for simple cases of `filter`. + where:function (attrs) { + if (_.isEmpty(attrs)) return []; + return this.filter(function (model) { + for (var key in attrs) { + if (attrs[key] !== model.get(key)) return false; + } + return true; + }); + }, + + // Force the collection to re-sort itself. You don't need to call this under + // normal circumstances, as the set will maintain sort order as each item + // is added. + sort:function (options) { + options || (options = {}); + if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); + var boundComparator = _.bind(this.comparator, this); + if (this.comparator.length == 1) { + this.models = this.sortBy(boundComparator); + } else { + this.models.sort(boundComparator); + } + if (!options.silent) this.trigger('reset', this, options); + return this; + }, + + // Pluck an attribute from each model in the collection. + pluck:function (attr) { + return _.map(this.models, function (model) { + return model.get(attr); + }); + }, + + // When you have more items than you want to add or remove individually, + // you can reset the entire set with a new list of models, without firing + // any `add` or `remove` events. Fires `reset` when finished. + reset:function (models, options) { + models || (models = []); + options || (options = {}); + for (var i = 0, l = this.models.length; i < l; i++) { + this._removeReference(this.models[i]); + } + this._reset(); + this.add(models, _.extend({silent:true}, options)); + if (!options.silent) this.trigger('reset', this, options); + return this; + }, + + // Fetch the default set of models for this collection, resetting the + // collection when they arrive. If `add: true` is passed, appends the + // models to the collection instead of resetting. + fetch:function (options) { + options = options ? _.clone(options) : {}; + if (options.parse === undefined) options.parse = true; + var collection = this; + var success = options.success; + options.success = function (resp, status, xhr) { + collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options); + if (success) success(collection, resp); + }; + options.error = Backbone.wrapError(options.error, collection, options); + return (this.sync || Backbone.sync).call(this, 'read', this, options); + }, + + // Create a new instance of a model in this collection. Add the model to the + // collection immediately, unless `wait: true` is passed, in which case we + // wait for the server to agree. + create:function (model, options) { + var coll = this; + options = options ? _.clone(options) : {}; + model = this._prepareModel(model, options); + if (!model) return false; + if (!options.wait) coll.add(model, options); + var success = options.success; + options.success = function (nextModel, resp, xhr) { + if (options.wait) coll.add(nextModel, options); + if (success) { + success(nextModel, resp); + } else { + nextModel.trigger('sync', model, resp, options); + } + }; + model.save(null, options); + return model; + }, + + // **parse** converts a response into a list of models to be added to the + // collection. The default implementation is just to pass it through. + parse:function (resp, xhr) { + return resp; + }, + + // Proxy to _'s chain. Can't be proxied the same way the rest of the + // underscore methods are proxied because it relies on the underscore + // constructor. + chain:function () { + return _(this.models).chain(); + }, + + // Reset all internal state. Called when the collection is reset. + _reset:function (options) { + this.length = 0; + this.models = []; + this._byId = {}; + this._byCid = {}; + }, + + // Prepare a model or hash of attributes to be added to this collection. + _prepareModel:function (model, options) { + options || (options = {}); + if (!(model instanceof Model)) { + var attrs = model; + options.collection = this; + model = new this.model(attrs, options); + if (!model._validate(model.attributes, options)) model = false; + } else if (!model.collection) { + model.collection = this; + } + return model; + }, + + // Internal method to remove a model's ties to a collection. + _removeReference:function (model) { + if (this == model.collection) { + delete model.collection; + } + model.off('all', this._onModelEvent, this); + }, + + // Internal method called every time a model in the set fires an event. + // Sets need to update their indexes when models change ids. All other + // events simply proxy through. "add" and "remove" events that originate + // in other collections are ignored. + _onModelEvent:function (event, model, collection, options) { + if ((event == 'add' || event == 'remove') && collection != this) return; + if (event == 'destroy') { + this.remove(model, options); + } + if (model && event === 'change:' + model.idAttribute) { + delete this._byId[model.previous(model.idAttribute)]; + this._byId[model.id] = model; + } + this.trigger.apply(this, arguments); + } + + }); + + // Underscore methods that we want to implement on the Collection. + var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find', + 'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', + 'include', 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex', + 'toArray', 'size', 'first', 'initial', 'rest', 'last', 'without', 'indexOf', + 'shuffle', 'lastIndexOf', 'isEmpty', 'groupBy']; + + // Mix in each Underscore method as a proxy to `Collection#models`. + _.each(methods, function (method) { + Collection.prototype[method] = function () { + return _[method].apply(_, [this.models].concat(_.toArray(arguments))); + }; + }); + + // Backbone.Router + // ------------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + var Router = Backbone.Router = function (options) { + options || (options = {}); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var namedParam = /:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Router.prototype, Events, { + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize:function () { + }, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route:function (route, name, callback) { + Backbone.history || (Backbone.history = new History); + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + if (!callback) callback = this[name]; + Backbone.history.route(route, _.bind(function (fragment) { + var args = this._extractParameters(route, fragment); + callback && callback.apply(this, args); + this.trigger.apply(this, ['route:' + name].concat(args)); + Backbone.history.trigger('route', this, name, args); + }, this)); + return this; + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate:function (fragment, options) { + Backbone.history.navigate(fragment, options); + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes:function () { + if (!this.routes) return; + var routes = []; + for (var route in this.routes) { + routes.unshift([route, this.routes[route]]); + } + for (var i = 0, l = routes.length; i < l; i++) { + this.route(routes[i][0], routes[i][1], this[routes[i][1]]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp:function (route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(namedParam, '([^\/]+)') + .replace(splatParam, '(.*?)'); + return new RegExp('^' + route + '$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted parameters. + _extractParameters:function (route, fragment) { + return route.exec(fragment).slice(1); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on URL fragments. If the + // browser does not support `onhashchange`, falls back to polling. + var History = Backbone.History = function () { + this.handlers = []; + _.bindAll(this, 'checkUrl'); + }; + + // Cached regex for cleaning leading hashes and slashes . + var routeStripper = /^[#\/]/; + + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Has the history handling already been started? + History.started = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(History.prototype, Events, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval:50, + + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash:function (windowOverride) { + var loc = windowOverride ? windowOverride.location : window.location; + var match = loc.href.match(/#(.*)$/); + return match ? match[1] : ''; + }, + + // Get the cross-browser normalized URL fragment, either from the URL, + // the hash, or the override. + getFragment:function (fragment, forcePushState) { + if (fragment == null) { + if (this._hasPushState || forcePushState) { + fragment = window.location.pathname; + var search = window.location.search; + if (search) fragment += search; + } else { + fragment = this.getHash(); + } + } + if (!fragment.indexOf(this.options.root)) fragment = fragment.substr(this.options.root.length); + return fragment.replace(routeStripper, ''); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start:function (options) { + if (History.started) throw new Error("Backbone.history has already been started"); + History.started = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + this.options = _.extend({}, {root:'/'}, this.options, options); + this._wantsHashChange = this.options.hashChange !== false; + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.options.pushState && window.history && window.history.pushState); + var fragment = this.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); + + if (oldIE) { + this.iframe = $('' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader:function (inst, drawMonth, drawYear, minDate, maxDate, secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
'; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ''; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if (!inst.yearshtml) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function (value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += ''; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '
'; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate:function (inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax:function (inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange:function (inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths:function (inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate:function (inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth:function (year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth:function (year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth:function (inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange:function (inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig:function (inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff:shortYearCutoff, + dayNamesShort:this._get(inst, 'dayNamesShort'), dayNames:this._get(inst, 'dayNames'), + monthNamesShort:this._get(inst, 'monthNamesShort'), monthNames:this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate:function (inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } + }); + + /* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ + function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.bind('mouseout', function (event) { + var elem = $(event.target).closest(selector); + if (!elem.length) { + return; + } + elem.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover"); + }) + .bind('mouseover', function (event) { + var elem = $(event.target).closest(selector); + if ($.datepicker._isDisabledDatepicker(instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || + !elem.length) { + return; + } + elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + elem.addClass('ui-state-hover'); + if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); + if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); + }); + } + + /* jQuery extend now ignores nulls! */ + function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; + } + + ; + + /* Determine whether an object is an array. */ + function isArray(a) { + return (a && (($.browser.safari && typeof a == 'object' && a.length) || + (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); + } + + ; + + /* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ + $.fn.datepicker = function (options) { + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if (!this.length) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find('body').append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function () { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); + }; + + $.datepicker = new Datepicker(); // singleton instance + $.datepicker.initialized = false; + $.datepicker.uuid = new Date().getTime(); + $.datepicker.version = "1.8.18"; + + // Workaround for #4055 + // Add another global to avoid noConflict issues with inline event handlers + window['DP_jQuery_' + dpuuid] = $; + + })(); + +})); diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.draggable.js b/app/js/libs/bui/jquery-ui/jquery.ui.draggable.js new file mode 100644 index 0000000..2a5fbf1 --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.draggable.js @@ -0,0 +1,840 @@ +/*! + * jQuery UI Draggable @VERSION + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery', 'jqueryUICore', 'jqueryUIWidget', 'jqueryUIMouse'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + (function (undefined) { + + $.widget("ui.draggable", $.ui.mouse, { + version:"@VERSION", + widgetEventPrefix:"drag", + options:{ + addClasses:true, + appendTo:"parent", + axis:false, + connectToSortable:false, + containment:false, + cursor:"auto", + cursorAt:false, + grid:false, + handle:false, + helper:"original", + iframeFix:false, + opacity:false, + refreshPositions:false, + revert:false, + revertDuration:500, + scope:"default", + scroll:true, + scrollSensitivity:20, + scrollSpeed:20, + snap:false, + snapMode:"both", + snapTolerance:20, + stack:false, + zIndex:false + }, + _create:function () { + + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; + + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); + + this._mouseInit(); + + }, + + destroy:function () { + if (!this.element.data('draggable')) return; + this.element + .removeData("draggable") + .unbind(".draggable") + .removeClass("ui-draggable" + + " ui-draggable-dragging" + + " ui-draggable-disabled"); + this._mouseDestroy(); + + return this; + }, + + _mouseCapture:function (event) { + + var o = this.options; + + // among others, prevent a drag on a resizable-handle + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; + + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; + + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function () { + $('
') + .css({ + width:this.offsetWidth + "px", height:this.offsetHeight + "px", + position:"absolute", opacity:"0.001", zIndex:1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + + return true; + + }, + + _mouseStart:function (event) { + + var o = this.options; + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + //If ddmanager is used for droppables, set the global draggable + if ($.ui.ddmanager) + $.ui.ddmanager.current = this; + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.positionAbs = this.element.offset(); + this.offset = { + top:this.offset.top - this.margins.top, + left:this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click:{ //Where the click happened, relative to the element + left:event.pageX - this.offset.left, + top:event.pageY - this.offset.top + }, + parent:this._getParentOffset(), + relative:this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this.position = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Set a containment if given in the options + if (o.containment) + this._setContainment(); + + //Trigger event + callbacks + if (this._trigger("start", event) === false) { + this._clear(); + return false; + } + + //Recache the helper size + this._cacheHelperProportions(); + + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.helper.addClass("ui-draggable-dragging"); + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) + if ($.ui.ddmanager) $.ui.ddmanager.dragStart(this, event); + + return true; + }, + + _mouseDrag:function (event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + if (this._trigger('drag', event, ui) === false) { + this._mouseUp({}); + return false; + } + this.position = ui.position; + } + + if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left + 'px'; + if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top + 'px'; + if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + return false; + }, + + _mouseStop:function (event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if (this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + //if the original element is removed, don't bother to continue + if ((!this.element[0] || !this.element[0].parentNode) && this.options.helper === "original") + return false; + + if ((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var that = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function () { + if (that._trigger("stop", event) !== false) { + that._clear(); + } + }); + } else { + if (this._trigger("stop", event) !== false) { + this._clear(); + } + } + + return false; + }, + + _mouseUp:function (event) { + if (this.options.iframeFix === true) { + $("div.ui-draggable-iframeFix").each(function () { + this.parentNode.removeChild(this); + }); //Remove frame helpers + } + + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) + if ($.ui.ddmanager) $.ui.ddmanager.dragStop(this, event); + + return $.ui.mouse.prototype._mouseUp.call(this, event); + }, + + cancel:function () { + + if (this.helper.is(".ui-draggable-dragging")) { + this._mouseUp({}); + } else { + this._clear(); + } + + return this; + + }, + + _getHandle:function (event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function () { + if (this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper:function (event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); + + if (!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if (helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper:function (obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left:+obj[0], top:+obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset:function () { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if (this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if ((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top:0, left:0 }; + + return { + top:po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), + left:po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) + }; + + }, + + _getRelativeOffset:function () { + + if (this.cssPosition == "relative") { + var p = this.element.position(); + return { + top:p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(), + left:p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top:0, left:0 }; + } + + }, + + _cacheMargins:function () { + this.margins = { + left:(parseInt(this.element.css("marginLeft"), 10) || 0), + top:(parseInt(this.element.css("marginTop"), 10) || 0), + right:(parseInt(this.element.css("marginRight"), 10) || 0), + bottom:(parseInt(this.element.css("marginBottom"), 10) || 0) + }; + }, + + _cacheHelperProportions:function () { + this.helperProportions = { + width:this.helper.outerWidth(), + height:this.helper.outerHeight() + }; + }, + + _setContainment:function () { + + var o = this.options; + if (o.containment == 'parent') o.containment = this.helper[0].parentNode; + if (o.containment == 'document' || o.containment == 'window') this.containment = [ + o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, + (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if (!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var c = $(o.containment); + var ce = c[0]; + if (!ce) return; + var co = c.offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0), + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0), + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom + ]; + this.relative_container = c; + + } else if (o.containment.constructor == Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo:function (d, pos) { + + if (!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top:( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left:( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition:function (event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if (this.originalPosition) { //If we are not dragging yet, we won't check for options + var containment; + if (this.containment) { + if (this.relative_container) { + var co = this.relative_container.offset(); + containment = [ this.containment[0] + co.left, + this.containment[1] + co.top, + this.containment[2] + co.left, + this.containment[3] + co.top ]; + } + else { + containment = this.containment; + } + + if (event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; + if (event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; + if (event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; + if (event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; + } + + if (o.grid) { + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; + pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; + pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top:( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left:( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear:function () { + this.helper.removeClass("ui-draggable-dragging"); + if (this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger:function (type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if (type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins:{}, + + _uiHash:function (event) { + return { + helper:this.helper, + position:this.position, + originalPosition:this.originalPosition, + offset:this.positionAbs + }; + } + + }); + + $.ui.plugin.add("draggable", "connectToSortable", { + start:function (event, ui) { + + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item:inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function () { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance:sortable, + shouldRevert:sortable.options.revert + }); + sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop:function (event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item:inst.element }); + + $.each(inst.sortables, function () { + if (this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if (this.shouldRevert) this.instance.options.revert = true; + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if (inst.options.helper == 'original') + this.instance.currentItem.css({ top:'auto', left:'auto' }); + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag:function (event, ui) { + + var inst = $(this).data("draggable"), that = this; + + var checkPos = function (o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; + + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; + + $.each(inst.sortables, function (i) { + + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if (this.instance._intersectsWith(this.instance.containerCache)) { + + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if (!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function () { + return ui.helper[0]; + }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if (this.instance.currentItem) this.instance._mouseDrag(event); + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if (this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if (this.instance.placeholder) this.instance.placeholder.remove(); + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + } + ; + + }); + + } + }); + + $.ui.plugin.add("draggable", "cursor", { + start:function (event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop:function (event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } + }); + + $.ui.plugin.add("draggable", "opacity", { + start:function (event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if (t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); + }, + stop:function (event, ui) { + var o = $(this).data('draggable').options; + if (o._opacity) $(ui.helper).css('opacity', o._opacity); + } + }); + + $.ui.plugin.add("draggable", "scroll", { + start:function (event, ui) { + var i = $(this).data("draggable"); + if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag:function (event, ui) { + + var i = $(this).data("draggable"), o = i.options, scrolled = false; + + if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + + if (!o.axis || o.axis != 'x') { + if ((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if (!o.axis || o.axis != 'y') { + if ((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if (!o.axis || o.axis != 'x') { + if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if (!o.axis || o.axis != 'y') { + if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); + + } + }); + + $.ui.plugin.add("draggable", "snap", { + start:function (event, ui) { + + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function () { + var $t = $(this); + var $o = $t.offset(); + if (this != i.element[0]) i.snapElements.push({ + item:this, + width:$t.outerWidth(), height:$t.outerHeight(), + top:$o.top, left:$o.left + }); + }); + + }, + drag:function (event, ui) { + + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; + + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (var i = inst.snapElements.length - 1; i >= 0; i--) { + + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if (!((l - d < x1 && x1 < r + d && t - d < y1 && y1 < b + d) || (l - d < x1 && x1 < r + d && t - d < y2 && y2 < b + d) || (l - d < x2 && x2 < r + d && t - d < y1 && y1 < b + d) || (l - d < x2 && x2 < r + d && t - d < y2 && y2 < b + d))) { + if (inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem:inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if (o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if (ts) ui.position.top = inst._convertPositionTo("relative", { top:t - inst.helperProportions.height, left:0 }).top - inst.margins.top; + if (bs) ui.position.top = inst._convertPositionTo("relative", { top:b, left:0 }).top - inst.margins.top; + if (ls) ui.position.left = inst._convertPositionTo("relative", { top:0, left:l - inst.helperProportions.width }).left - inst.margins.left; + if (rs) ui.position.left = inst._convertPositionTo("relative", { top:0, left:r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if (o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if (ts) ui.position.top = inst._convertPositionTo("relative", { top:t, left:0 }).top - inst.margins.top; + if (bs) ui.position.top = inst._convertPositionTo("relative", { top:b - inst.helperProportions.height, left:0 }).top - inst.margins.top; + if (ls) ui.position.left = inst._convertPositionTo("relative", { top:0, left:l }).left - inst.margins.left; + if (rs) ui.position.left = inst._convertPositionTo("relative", { top:0, left:r - inst.helperProportions.width }).left - inst.margins.left; + } + + if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem:inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + } + ; + + } + }); + + $.ui.plugin.add("draggable", "stack", { + start:function (event, ui) { + + var o = $(this).data("draggable").options; + + var group = $.makeArray($(o.stack)).sort(function (a, b) { + return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0); + }); + if (!group.length) { + return; + } + + var min = parseInt(group[0].style.zIndex) || 0; + $(group).each(function (i) { + this.style.zIndex = min + i; + }); + + this[0].style.zIndex = min + group.length; + + } + }); + + $.ui.plugin.add("draggable", "zIndex", { + start:function (event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if (t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop:function (event, ui) { + var o = $(this).data("draggable").options; + if (o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } + }); + + })(); + +})); \ No newline at end of file diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.droppable.js b/app/js/libs/bui/jquery-ui/jquery.ui.droppable.js new file mode 100644 index 0000000..2fffbfa --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.droppable.js @@ -0,0 +1,322 @@ +/* + * jQuery UI Droppable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Droppables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery', 'jqueryUICore', 'jqueryUIWidget', 'jqueryUIMouse'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + (function (undefined) { + + + $.widget("ui.droppable", { + widgetEventPrefix:"drop", + options:{ + accept:'*', + activeClass:false, + addClasses:true, + greedy:false, + hoverClass:false, + scope:'default', + tolerance:'intersect' + }, + _create:function () { + + var o = this.options, accept = o.accept; + this.isover = 0; + this.isout = 1; + + this.accept = $.isFunction(accept) ? accept : function (d) { + return d.is(accept); + }; + + //Store the droppable's proportions + this.proportions = { width:this.element[0].offsetWidth, height:this.element[0].offsetHeight }; + + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; + $.ui.ddmanager.droppables[o.scope].push(this); + + (o.addClasses && this.element.addClass("ui-droppable")); + + }, + + destroy:function () { + var drop = $.ui.ddmanager.droppables[this.options.scope]; + for (var i = 0; i < drop.length; i++) + if (drop[i] == this) + drop.splice(i, 1); + + this.element + .removeClass("ui-droppable ui-droppable-disabled") + .removeData("droppable") + .unbind(".droppable"); + + return this; + }, + + _setOption:function (key, value) { + + if (key == 'accept') { + this.accept = $.isFunction(value) ? value : function (d) { + return d.is(value); + }; + } + $.Widget.prototype._setOption.apply(this, arguments); + }, + + _activate:function (event) { + var draggable = $.ui.ddmanager.current; + if (this.options.activeClass) this.element.addClass(this.options.activeClass); + (draggable && this._trigger('activate', event, this.ui(draggable))); + }, + + _deactivate:function (event) { + var draggable = $.ui.ddmanager.current; + if (this.options.activeClass) this.element.removeClass(this.options.activeClass); + (draggable && this._trigger('deactivate', event, this.ui(draggable))); + }, + + _over:function (event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) { + if (this.options.hoverClass) this.element.addClass(this.options.hoverClass); + this._trigger('over', event, this.ui(draggable)); + } + + }, + + _out:function (event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) { + if (this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('out', event, this.ui(draggable)); + } + + }, + + _drop:function (event, custom) { + + var draggable = custom || $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element + + var childrenIntersection = false; + this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function () { + var inst = $.data(this, 'droppable'); + if ( + inst.options.greedy + && !inst.options.disabled + && inst.options.scope == draggable.options.scope + && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) + && $.ui.intersect(draggable, $.extend(inst, { offset:inst.element.offset() }), inst.options.tolerance) + ) { + childrenIntersection = true; + return false; + } + }); + if (childrenIntersection) return false; + + if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) { + if (this.options.activeClass) this.element.removeClass(this.options.activeClass); + if (this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('drop', event, this.ui(draggable)); + return this.element; + } + + return false; + + }, + + ui:function (c) { + return { + draggable:(c.currentItem || c.element), + helper:c.helper, + position:c.position, + offset:c.positionAbs + }; + } + + }); + + $.extend($.ui.droppable, { + version:"1.8.18" + }); + + $.ui.intersect = function (draggable, droppable, toleranceMode) { + + if (!droppable.offset) return false; + + var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; + var l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; + + switch (toleranceMode) { + case 'fit': + return (l <= x1 && x2 <= r + && t <= y1 && y2 <= b); + break; + case 'intersect': + return (l < x1 + (draggable.helperProportions.width / 2) // Right Half + && x2 - (draggable.helperProportions.width / 2) < r // Left Half + && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half + && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + break; + case 'pointer': + var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), + isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); + return isOver; + break; + case 'touch': + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + break; + default: + return false; + break; + } + + }; + + /* + This manager tracks offsets of draggables and droppables + */ + $.ui.ddmanager = { + current:null, + droppables:{ 'default':[] }, + prepareOffsets:function (t, event) { + + var m = $.ui.ddmanager.droppables[t.options.scope] || []; + var type = event ? event.type : null; // workaround for #2317 + var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + + droppablesLoop: for (var i = 0; i < m.length; i++) { + + if (m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0], (t.currentItem || t.element)))) continue; //No disabled and non-accepted + for (var j = 0; j < list.length; j++) { + if (list[j] == m[i].element[0]) { + m[i].proportions.height = 0; + continue droppablesLoop; + } + } + ; //Filter out elements in the current dragged item + m[i].visible = m[i].element.css("display") != "none"; + if (!m[i].visible) continue; //If the element is not visible, continue + + if (type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables + + m[i].offset = m[i].element.offset(); + m[i].proportions = { width:m[i].element[0].offsetWidth, height:m[i].element[0].offsetHeight }; + + } + + }, + drop:function (draggable, event) { + + var dropped = false; + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function () { + + if (!this.options) return; + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) + dropped = this._drop.call(this, event) || dropped; + + if (!this.options.disabled && this.visible && this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) { + this.isout = 1; + this.isover = 0; + this._deactivate.call(this, event); + } + + }); + return dropped; + + }, + dragStart:function (draggable, event) { + //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) + draggable.element.parents(":not(body,html)").bind("scroll.droppable", function () { + if (!draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + }); + }, + drag:function (draggable, event) { + + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if (draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + + //Run through all droppables and check their positions based on specific tolerance options + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function () { + + if (this.options.disabled || this.greedyChild || !this.visible) return; + var intersects = $.ui.intersect(draggable, this, this.options.tolerance); + + var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); + if (!c) return; + + var parentInstance; + if (this.options.greedy) { + var parent = this.element.parents(':data(droppable):eq(0)'); + if (parent.length) { + parentInstance = $.data(parent[0], 'droppable'); + parentInstance.greedyChild = (c == 'isover' ? 1 : 0); + } + } + + // we just moved into a greedy child + if (parentInstance && c == 'isover') { + parentInstance['isover'] = 0; + parentInstance['isout'] = 1; + parentInstance._out.call(parentInstance, event); + } + + this[c] = 1; + this[c == 'isout' ? 'isover' : 'isout'] = 0; + this[c == "isover" ? "_over" : "_out"].call(this, event); + + // we just moved out of a greedy child + if (parentInstance && c == 'isout') { + parentInstance['isout'] = 0; + parentInstance['isover'] = 1; + parentInstance._over.call(parentInstance, event); + } + }); + + }, + dragStop:function (draggable, event) { + draggable.element.parents(":not(body,html)").unbind("scroll.droppable"); + //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) + if (!draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + } + }; + + })(); + +})); \ No newline at end of file diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.mouse.js b/app/js/libs/bui/jquery-ui/jquery.ui.mouse.js new file mode 100644 index 0000000..cac051c --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.mouse.js @@ -0,0 +1,182 @@ +/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery', 'jqueryUIWidget'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + (function (undefined) { + + var mouseHandled = false; + $(document).mouseup(function (e) { + mouseHandled = false; + }); + + $.widget("ui.mouse", { + options:{ + cancel:':input,option', + distance:1, + delay:0 + }, + _mouseInit:function () { + var self = this; + + this.element + .bind('mousedown.' + this.widgetName, function (event) { + return self._mouseDown(event); + }) + .bind('click.' + this.widgetName, function (event) { + if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { + $.removeData(event.target, self.widgetName + '.preventClickEvent'); + event.stopImmediatePropagation(); + return false; + } + }); + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy:function () { + this.element.unbind('.' + this.widgetName); + }, + + _mouseDown:function (event) { + // don't let more than one widget handle mouseStart + if (mouseHandled) { + return + } + ; + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var self = this, + btnIsLeft = (event.which == 1), + // event.target.nodeName works around a bug in IE 8 with + // disabled inputs (#7620) + elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function () { + self.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // Click event may never have fired (Gecko & Opera) + if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { + $.removeData(event.target, this.widgetName + '.preventClickEvent'); + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function (event) { + return self._mouseMove(event); + }; + this._mouseUpDelegate = function (event) { + return self._mouseUp(event); + }; + $(document) + .bind('mousemove.' + this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.' + this.widgetName, this._mouseUpDelegate); + + event.preventDefault(); + + mouseHandled = true; + return true; + }, + + _mouseMove:function (event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp:function (event) { + $(document) + .unbind('mousemove.' + this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.' + this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + + if (event.target == this._mouseDownEvent.target) { + $.data(event.target, this.widgetName + '.preventClickEvent', true); + } + + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet:function (event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet:function (event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart:function (event) { + }, + _mouseDrag:function (event) { + }, + _mouseStop:function (event) { + }, + _mouseCapture:function (event) { + return true; + } + }); + + })(); + +})); diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.position.js b/app/js/libs/bui/jquery-ui/jquery.ui.position.js new file mode 100644 index 0000000..af25a05 --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.position.js @@ -0,0 +1,313 @@ +/* + * jQuery UI Position 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */ + +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + (function (undefined) { + + $.ui = $.ui || {}; + + var horizontalPositions = /left|center|right/, + verticalPositions = /top|center|bottom/, + center = "center", + support = {}, + _position = $.fn.position, + _offset = $.fn.offset; + + $.fn.position = function (options) { + if (!options || !options.of) { + return _position.apply(this, arguments); + } + + // make a copy, we don't want to modify arguments + options = $.extend({}, options); + + var target = $(options.of), + targetElem = target[0], + collision = ( options.collision || "flip" ).split(" "), + offset = options.offset ? options.offset.split(" ") : [ 0, 0 ], + targetWidth, + targetHeight, + basePosition; + + if (targetElem.nodeType === 9) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top:0, left:0 }; + // TODO: use $.isWindow() in 1.9 + } else if (targetElem.setTimeout) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top:target.scrollTop(), left:target.scrollLeft() }; + } else if (targetElem.preventDefault) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + basePosition = { top:options.of.pageY, left:options.of.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + basePosition = target.offset(); + } + + // force my and at to have valid horizontal and veritcal positions + // if a value is missing or invalid, it will be converted to center + $.each([ "my", "at" ], function () { + var pos = ( options[this] || "" ).split(" "); + if (pos.length === 1) { + pos = horizontalPositions.test(pos[0]) ? + pos.concat([center]) : + verticalPositions.test(pos[0]) ? + [ center ].concat(pos) : + [ center, center ]; + } + pos[ 0 ] = horizontalPositions.test(pos[0]) ? pos[ 0 ] : center; + pos[ 1 ] = verticalPositions.test(pos[1]) ? pos[ 1 ] : center; + options[ this ] = pos; + }); + + // normalize collision option + if (collision.length === 1) { + collision[ 1 ] = collision[ 0 ]; + } + + // normalize offset option + offset[ 0 ] = parseInt(offset[0], 10) || 0; + if (offset.length === 1) { + offset[ 1 ] = offset[ 0 ]; + } + offset[ 1 ] = parseInt(offset[1], 10) || 0; + + if (options.at[0] === "right") { + basePosition.left += targetWidth; + } else if (options.at[0] === center) { + basePosition.left += targetWidth / 2; + } + + if (options.at[1] === "bottom") { + basePosition.top += targetHeight; + } else if (options.at[1] === center) { + basePosition.top += targetHeight / 2; + } + + basePosition.left += offset[ 0 ]; + basePosition.top += offset[ 1 ]; + + return this.each(function () { + var elem = $(this), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseInt($.curCSS(this, "marginLeft", true)) || 0, + marginTop = parseInt($.curCSS(this, "marginTop", true)) || 0, + collisionWidth = elemWidth + marginLeft + + ( parseInt($.curCSS(this, "marginRight", true)) || 0 ), + collisionHeight = elemHeight + marginTop + + ( parseInt($.curCSS(this, "marginBottom", true)) || 0 ), + position = $.extend({}, basePosition), + collisionPosition; + + if (options.my[0] === "right") { + position.left -= elemWidth; + } else if (options.my[0] === center) { + position.left -= elemWidth / 2; + } + + if (options.my[1] === "bottom") { + position.top -= elemHeight; + } else if (options.my[1] === center) { + position.top -= elemHeight / 2; + } + + // prevent fractions if jQuery version doesn't support them (see #5280) + if (!support.fractions) { + position.left = Math.round(position.left); + position.top = Math.round(position.top); + } + + collisionPosition = { + left:position.left - marginLeft, + top:position.top - marginTop + }; + + $.each([ "left", "top" ], function (i, dir) { + if ($.ui.position[ collision[i] ]) { + $.ui.position[ collision[i] ][ dir ](position, { + targetWidth:targetWidth, + targetHeight:targetHeight, + elemWidth:elemWidth, + elemHeight:elemHeight, + collisionPosition:collisionPosition, + collisionWidth:collisionWidth, + collisionHeight:collisionHeight, + offset:offset, + my:options.my, + at:options.at + }); + } + }); + + if ($.fn.bgiframe) { + elem.bgiframe(); + } + elem.offset($.extend(position, { using:options.using })); + }); + }; + + $.ui.position = { + fit:{ + left:function (position, data) { + var win = $(window), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); + position.left = over > 0 ? position.left - over : Math.max(position.left - data.collisionPosition.left, position.left); + }, + top:function (position, data) { + var win = $(window), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); + position.top = over > 0 ? position.top - over : Math.max(position.top - data.collisionPosition.top, position.top); + } + }, + + flip:{ + left:function (position, data) { + if (data.at[0] === center) { + return; + } + var win = $(window), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + -data.targetWidth, + offset = -2 * data.offset[ 0 ]; + position.left += data.collisionPosition.left < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + }, + top:function (position, data) { + if (data.at[1] === center) { + return; + } + var win = $(window), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), + myOffset = data.my[ 1 ] === "top" ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + -data.targetHeight, + offset = -2 * data.offset[ 1 ]; + position.top += data.collisionPosition.top < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + } + } + }; + + // offset setter from jQuery 1.4 + if (!$.offset.setOffset) { + $.offset.setOffset = function (elem, options) { + // set position first, in-case top/left are set even on static elem + if (/static/.test($.curCSS(elem, "position"))) { + elem.style.position = "relative"; + } + var curElem = $(elem), + curOffset = curElem.offset(), + curTop = parseInt($.curCSS(elem, "top", true), 10) || 0, + curLeft = parseInt($.curCSS(elem, "left", true), 10) || 0, + props = { + top:(options.top - curOffset.top) + curTop, + left:(options.left - curOffset.left) + curLeft + }; + + if ('using' in options) { + options.using.call(elem, props); + } else { + curElem.css(props); + } + }; + + $.fn.offset = function (options) { + var elem = this[ 0 ]; + if (!elem || !elem.ownerDocument) { + return null; + } + if (options) { + return this.each(function () { + $.offset.setOffset(this, options); + }); + } + return _offset.call(this); + }; + } + + // fraction support test (older versions of jQuery don't support fractions) + (function () { + var body = document.getElementsByTagName("body")[ 0 ], + div = document.createElement("div"), + testElement, testElementParent, testElementStyle, offset, offsetTotal; + + //Create a "fake body" for testing based on method used in jQuery.support + testElement = document.createElement(body ? "div" : "body"); + testElementStyle = { + visibility:"hidden", + width:0, + height:0, + border:0, + margin:0, + background:"none" + }; + if (body) { + $.extend(testElementStyle, { + position:"absolute", + left:"-1000px", + top:"-1000px" + }); + } + for (var i in testElementStyle) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild(div); + testElementParent = body || document.documentElement; + testElementParent.insertBefore(testElement, testElementParent.firstChild); + + div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;"; + + offset = $(div).offset(function (_, offset) { + return offset; + }).offset(); + + testElement.innerHTML = ""; + testElementParent.removeChild(testElement); + + offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 ); + support.fractions = offsetTotal > 21 && offsetTotal < 22; + })(); + + }()); + +})); diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.slider.js b/app/js/libs/bui/jquery-ui/jquery.ui.slider.js new file mode 100644 index 0000000..d56beb0 --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.slider.js @@ -0,0 +1,669 @@ +/*! + * jQuery UI Slider 1.8.20 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery', 'jqueryUICore', 'jqueryUIMouse', 'jqueryUIWidget'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($, undefined) { + +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) + var numPages = 5; + + $.widget("ui.slider", $.ui.mouse, { + + widgetEventPrefix:"slide", + + options:{ + animate:false, + distance:0, + max:100, + min:0, + orientation:"horizontal", + range:false, + step:1, + value:0, + values:null + }, + + _create:function () { + var self = this, + o = this.options, + existingHandles = this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"), + handle = "", + handleCount = ( o.values && o.values.length ) || 1, + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass("ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" )); + + this.range = $([]); + + if (o.range) { + if (o.range === true) { + if (!o.values) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if (o.values.length && o.values.length !== 2) { + o.values = [ o.values[0], o.values[0] ]; + } + } + + this.range = $("
") + .appendTo(this.element) + .addClass("ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" )); + } + + for (var i = existingHandles.length; i < handleCount; i += 1) { + handles.push(handle); + } + + this.handles = existingHandles.add($(handles.join("")).appendTo(self.element)); + + this.handle = this.handles.eq(0); + + this.handles.add(this.range).filter("a") + .click(function (event) { + event.preventDefault(); + }) + .hover(function () { + if (!o.disabled) { + $(this).addClass("ui-state-hover"); + } + }, function () { + $(this).removeClass("ui-state-hover"); + }) + .focus(function () { + if (!o.disabled) { + $(".ui-slider .ui-state-focus").removeClass("ui-state-focus"); + $(this).addClass("ui-state-focus"); + } else { + $(this).blur(); + } + }) + .blur(function () { + $(this).removeClass("ui-state-focus"); + }); + + this.handles.each(function (i) { + $(this).data("index.ui-slider-handle", i); + }); + + this.handles + .keydown(function (event) { + var index = $(this).data("index.ui-slider-handle"), + allowed, + curVal, + newVal, + step; + + if (self.options.disabled) { + return; + } + + switch (event.keyCode) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + event.preventDefault(); + if (!self._keySliding) { + self._keySliding = true; + $(this).addClass("ui-state-active"); + allowed = self._start(event, index); + if (allowed === false) { + return; + } + } + break; + } + + step = self.options.step; + if (self.options.values && self.options.values.length) { + curVal = newVal = self.values(index); + } else { + curVal = newVal = self.value(); + } + + switch (event.keyCode) { + case $.ui.keyCode.HOME: + newVal = self._valueMin(); + break; + case $.ui.keyCode.END: + newVal = self._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = self._trimAlignValue(curVal + ( (self._valueMax() - self._valueMin()) / numPages )); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = self._trimAlignValue(curVal - ( (self._valueMax() - self._valueMin()) / numPages )); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if (curVal === self._valueMax()) { + return; + } + newVal = self._trimAlignValue(curVal + step); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if (curVal === self._valueMin()) { + return; + } + newVal = self._trimAlignValue(curVal - step); + break; + } + + self._slide(event, index, newVal); + }) + .keyup(function (event) { + var index = $(this).data("index.ui-slider-handle"); + + if (self._keySliding) { + self._keySliding = false; + self._stop(event, index); + self._change(event, index); + $(this).removeClass("ui-state-active"); + } + + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + destroy:function () { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass("ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all") + .removeData("slider") + .unbind(".slider"); + + this._mouseDestroy(); + + return this; + }, + + _mouseCapture:function (event) { + var o = this.options, + position, + normValue, + distance, + closestHandle, + self, + index, + allowed, + offset, + mouseOverHandle; + + if (o.disabled) { + return false; + } + + this.elementSize = { + width:this.element.outerWidth(), + height:this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x:event.pageX, y:event.pageY }; + normValue = this._normValueFromMouse(position); + distance = this._valueMax() - this._valueMin() + 1; + self = this; + this.handles.each(function (i) { + var thisDistance = Math.abs(normValue - self.values(i)); + if (distance > thisDistance) { + distance = thisDistance; + closestHandle = $(this); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if (o.range === true && this.values(1) === o.min) { + index += 1; + closestHandle = $(this.handles[index]); + } + + allowed = this._start(event, index); + if (allowed === false) { + return false; + } + this._mouseSliding = true; + + self._handleIndex = index; + + closestHandle + .addClass("ui-state-active") + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$(event.target).parents().andSelf().is(".ui-slider-handle"); + this._clickOffset = mouseOverHandle ? { left:0, top:0 } : { + left:event.pageX - offset.left - ( closestHandle.width() / 2 ), + top:event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt(closestHandle.css("borderTopWidth"), 10) || 0 ) - + ( parseInt(closestHandle.css("borderBottomWidth"), 10) || 0) + + ( parseInt(closestHandle.css("marginTop"), 10) || 0) + }; + + if (!this.handles.hasClass("ui-state-hover")) { + this._slide(event, index, normValue); + } + this._animateOff = true; + return true; + }, + + _mouseStart:function (event) { + return true; + }, + + _mouseDrag:function (event) { + var position = { x:event.pageX, y:event.pageY }, + normValue = this._normValueFromMouse(position); + + this._slide(event, this._handleIndex, normValue); + + return false; + }, + + _mouseStop:function (event) { + this.handles.removeClass("ui-state-active"); + this._mouseSliding = false; + + this._stop(event, this._handleIndex); + this._change(event, this._handleIndex); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation:function () { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse:function (position) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if (this.orientation === "horizontal") { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + } + + percentMouse = ( pixelMouse / pixelTotal ); + if (percentMouse > 1) { + percentMouse = 1; + } + if (percentMouse < 0) { + percentMouse = 0; + } + if (this.orientation === "vertical") { + percentMouse = 1 - percentMouse; + } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue(valueMouse); + }, + + _start:function (event, index) { + var uiHash = { + handle:this.handles[ index ], + value:this.value() + }; + if (this.options.values && this.options.values.length) { + uiHash.value = this.values(index); + uiHash.values = this.values(); + } + return this._trigger("start", event, uiHash); + }, + + _slide:function (event, index, newVal) { + var otherVal, + newValues, + allowed; + + if (this.options.values && this.options.values.length) { + otherVal = this.values(index ? 0 : 1); + + if (( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if (newVal !== this.values(index)) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger("slide", event, { + handle:this.handles[ index ], + value:newVal, + values:newValues + }); + otherVal = this.values(index ? 0 : 1); + if (allowed !== false) { + this.values(index, newVal, true); + } + } + } else { + if (newVal !== this.value()) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger("slide", event, { + handle:this.handles[ index ], + value:newVal + }); + if (allowed !== false) { + this.value(newVal); + } + } + } + }, + + _stop:function (event, index) { + var uiHash = { + handle:this.handles[ index ], + value:this.value() + }; + if (this.options.values && this.options.values.length) { + uiHash.value = this.values(index); + uiHash.values = this.values(); + } + + this._trigger("stop", event, uiHash); + }, + + _change:function (event, index) { + if (!this._keySliding && !this._mouseSliding) { + var uiHash = { + handle:this.handles[ index ], + value:this.value() + }; + if (this.options.values && this.options.values.length) { + uiHash.value = this.values(index); + uiHash.values = this.values(); + } + + this._trigger("change", event, uiHash); + } + }, + + value:function (newValue) { + if (arguments.length) { + this.options.value = this._trimAlignValue(newValue); + this._refreshValue(); + this._change(null, 0); + return; + } + + return this._value(); + }, + + values:function (index, newValue) { + var vals, + newValues, + i; + + if (arguments.length > 1) { + this.options.values[ index ] = this._trimAlignValue(newValue); + this._refreshValue(); + this._change(null, index); + return; + } + + if (arguments.length) { + if ($.isArray(arguments[ 0 ])) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for (i = 0; i < vals.length; i += 1) { + vals[ i ] = this._trimAlignValue(newValues[ i ]); + this._change(null, i); + } + this._refreshValue(); + } else { + if (this.options.values && this.options.values.length) { + return this._values(index); + } else { + return this.value(); + } + } + } else { + return this._values(); + } + }, + + _setOption:function (key, value) { + var i, + valsLength = 0; + + if ($.isArray(this.options.values)) { + valsLength = this.options.values.length; + } + + $.Widget.prototype._setOption.apply(this, arguments); + + switch (key) { + case "disabled": + if (value) { + this.handles.filter(".ui-state-focus").blur(); + this.handles.removeClass("ui-state-hover"); + this.handles.propAttr("disabled", true); + this.element.addClass("ui-disabled"); + } else { + this.handles.propAttr("disabled", false); + this.element.removeClass("ui-disabled"); + } + break; + case "orientation": + this._detectOrientation(); + this.element + .removeClass("ui-slider-horizontal ui-slider-vertical") + .addClass("ui-slider-" + this.orientation); + this._refreshValue(); + break; + case "value": + this._animateOff = true; + this._refreshValue(); + this._change(null, 0); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for (i = 0; i < valsLength; i += 1) { + this._change(null, i); + } + this._animateOff = false; + break; + } + }, + + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value:function () { + var val = this.options.value; + val = this._trimAlignValue(val); + + return val; + }, + + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values:function (index) { + var val, + vals, + i; + + if (arguments.length) { + val = this.options.values[ index ]; + val = this._trimAlignValue(val); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for (i = 0; i < vals.length; i += 1) { + vals[ i ] = this._trimAlignValue(vals[ i ]); + } + + return vals; + } + }, + + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue:function (val) { + if (val <= this._valueMin()) { + return this._valueMin(); + } + if (val >= this._valueMax()) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if (Math.abs(valModStep) * 2 >= step) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat(alignValue.toFixed(5)); + }, + + _valueMin:function () { + return this.options.min; + }, + + _valueMax:function () { + return this.options.max; + }, + + _refreshValue:function () { + var oRange = this.options.range, + o = this.options, + self = this, + animate = ( !this._animateOff ) ? o.animate : false, + valPercent, + _set = {}, + lastValPercent, + value, + valueMin, + valueMax; + + if (this.options.values && this.options.values.length) { + this.handles.each(function (i, j) { + valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $(this).stop(1, 1)[ animate ? "animate" : "css" ](_set, o.animate); + if (self.options.range === true) { + if (self.orientation === "horizontal") { + if (i === 0) { + self.range.stop(1, 1)[ animate ? "animate" : "css" ]({ left:valPercent + "%" }, o.animate); + } + if (i === 1) { + self.range[ animate ? "animate" : "css" ]({ width:( valPercent - lastValPercent ) + "%" }, { queue:false, duration:o.animate }); + } + } else { + if (i === 0) { + self.range.stop(1, 1)[ animate ? "animate" : "css" ]({ bottom:( valPercent ) + "%" }, o.animate); + } + if (i === 1) { + self.range[ animate ? "animate" : "css" ]({ height:( valPercent - lastValPercent ) + "%" }, { queue:false, duration:o.animate }); + } + } + } + lastValPercent = valPercent; + }); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop(1, 1)[ animate ? "animate" : "css" ](_set, o.animate); + + if (oRange === "min" && this.orientation === "horizontal") { + this.range.stop(1, 1)[ animate ? "animate" : "css" ]({ width:valPercent + "%" }, o.animate); + } + if (oRange === "max" && this.orientation === "horizontal") { + this.range[ animate ? "animate" : "css" ]({ width:( 100 - valPercent ) + "%" }, { queue:false, duration:o.animate }); + } + if (oRange === "min" && this.orientation === "vertical") { + this.range.stop(1, 1)[ animate ? "animate" : "css" ]({ height:valPercent + "%" }, o.animate); + } + if (oRange === "max" && this.orientation === "vertical") { + this.range[ animate ? "animate" : "css" ]({ height:( 100 - valPercent ) + "%" }, { queue:false, duration:o.animate }); + } + } + } + + }); + + $.extend($.ui.slider, { + version:"1.8.20" + }); +})); diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.sortable.js b/app/js/libs/bui/jquery-ui/jquery.ui.sortable.js new file mode 100644 index 0000000..4470b93 --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.sortable.js @@ -0,0 +1,1154 @@ +/* + * jQuery UI Sortable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery', 'jqueryUICore', 'jqueryUIWidget', 'jqueryUIMouse'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + (function (undefined) { + + $.widget("ui.sortable", $.ui.mouse, { + widgetEventPrefix:"sort", + ready:false, + options:{ + appendTo:"parent", + axis:false, + connectWith:false, + containment:false, + cursor:'auto', + cursorAt:false, + dropOnEmpty:true, + forcePlaceholderSize:false, + forceHelperSize:false, + grid:false, + handle:false, + helper:"original", + items:'> *', + opacity:false, + placeholder:false, + revert:false, + scroll:true, + scrollSensitivity:20, + scrollSpeed:20, + scope:"default", + tolerance:"intersect", + zIndex:1000 + }, + _create:function () { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are being displayed horizontally + this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + //We're ready to go + this.ready = true + + }, + + destroy:function () { + $.Widget.prototype.destroy.call(this); + this.element + .removeClass("ui-sortable ui-sortable-disabled"); + this._mouseDestroy(); + + for (var i = this.items.length - 1; i >= 0; i--) + this.items[i].item.removeData(this.widgetName + "-item"); + + return this; + }, + + _setOption:function (key, value) { + if (key === "disabled") { + this.options[ key ] = value; + + this.widget() + [ value ? "addClass" : "removeClass"]("ui-sortable-disabled"); + } else { + // Don't call widget base _setOption for disable as it adds ui-state-disabled class + $.Widget.prototype._setOption.apply(this, arguments); + } + }, + + _mouseCapture:function (event, overrideHandle) { + var that = this; + + if (this.reverting) { + return false; + } + + if (this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, self = this, nodes = $(event.target).parents().each(function () { + if ($.data(this, that.widgetName + '-item') == self) { + currentItem = $(this); + return false; + } + }); + if ($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target); + + if (!currentItem) return false; + if (this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function () { + if (this == event.target) validHandle = true; + }); + if (!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart:function (event, overrideHandle, noActivation) { + + var o = this.options, self = this; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top:this.offset.top - this.margins.top, + left:this.offset.left - this.margins.left + }; + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + $.extend(this.offset, { + click:{ //Where the click happened, relative to the element + left:event.pageX - this.offset.left, + top:event.pageY - this.offset.top + }, + parent:this._getParentOffset(), + relative:this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Cache the former DOM position + this.domPosition = { prev:this.currentItem.prev()[0], parent:this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if (this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if (o.containment) + this._setContainment(); + + if (o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); + } + + if (o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } + + if (o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if (this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if (!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if (!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { + this.containers[i]._trigger("activate", event, self._uiHash(this)); + } + } + + //Prepare possible droppables + if ($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag:function (event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if (this.options.scroll) { + var o = this.options, scrolled = false; + if (this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if ((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if ((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + + } + + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left + 'px'; + if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top + 'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + if (itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) + //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop:function (event, noPropagation) { + + if (!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if (this.options.revert) { + var self = this; + var cur = self.placeholder.offset(); + + self.reverting = true; + + $(this.helper).animate({ + left:cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top:cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function () { + self._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel:function () { + + var self = this; + + if (this.dragging) { + + this._mouseUp({ target:null }); + + if (this.options.helper == "original") + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + else + this.currentItem.show(); + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--) { + this.containers[i]._trigger("deactivate", null, self._uiHash(this)); + if (this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, self._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if (this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if (this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper:null, + dragging:false, + reverting:false, + _noFinalSort:null + }); + + if (this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + } + + return this; + + }, + + serialize:function (o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; + o = o || {}; + + $(items).each(function () { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if (res) str.push((o.key || res[1] + '[]') + '=' + (o.key && o.expression ? res[1] : res[2])); + }); + + if (!str.length && o.key) { + str.push(o.key + '='); + } + + return str.join('&'); + + }, + + toArray:function (o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; + o = o || {}; + + items.each(function () { + ret.push($(o.item || this).attr(o.attribute || 'id') || ''); + }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith:function (item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if (this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer:function (item) { + + var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + + }, + + _intersectsWithSides:function (item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height / 2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width / 2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection:function () { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection:function () { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); + }, + + refresh:function (event) { + this._refreshItems(event); + this.refreshPositions(); + return this; + }, + + _connectWith:function () { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; + }, + + _getItemsAsjQuery:function (connected) { + + var self = this; + var items = []; + var queries = []; + var connectWith = this._connectWith(); + + if (connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--) { + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--) { + var inst = $.data(cur[j], this.widgetName); + if (inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); + } + } + ; + } + ; + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options:this.options, item:this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); + + for (var i = queries.length - 1; i >= 0; i--) { + queries[i][0].each(function () { + items.push(this); + }); + } + ; + + return $(items); + + }, + + _removeCurrentsFromItems:function () { + + var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); + + for (var i = 0; i < this.items.length; i++) { + + for (var j = 0; j < list.length; j++) { + if (list[j] == this.items[i].item[0]) + this.items.splice(i, 1); + } + ; + + } + ; + + }, + + _refreshItems:function (event) { + + this.items = []; + this.containers = [this]; + var items = this.items; + var self = this; + var queries = [ + [$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item:this.currentItem }) : $(this.options.items, this.element), this] + ]; + var connectWith = this._connectWith(); + + if (connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down + for (var i = connectWith.length - 1; i >= 0; i--) { + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--) { + var inst = $.data(cur[j], this.widgetName); + if (inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item:this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + } + ; + } + ; + } + + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; + + for (var j = 0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); + + item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) + + items.push({ + item:item, + instance:targetData, + width:0, height:0, + left:0, top:0 + }); + } + ; + } + ; + + }, + + refreshPositions:function (fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if (this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + for (var i = this.items.length - 1; i >= 0; i--) { + var item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if (item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + var p = t.offset(); + item.left = p.left; + item.top = p.top; + } + ; + + if (this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--) { + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + } + ; + } + + return this; + }, + + _createPlaceholder:function (that) { + + var self = that || this, o = self.options; + + if (!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element:function () { + + var el = $(document.createElement(self.currentItem[0].nodeName)) + .addClass(className || self.currentItem[0].className + " ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if (!className) + el.style.visibility = "hidden"; + + return el; + }, + update:function (container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if (className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if (!p.height()) { + p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop') || 0, 10) - parseInt(self.currentItem.css('paddingBottom') || 0, 10)); + } + ; + if (!p.width()) { + p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft') || 0, 10) - parseInt(self.currentItem.css('paddingRight') || 0, 10)); + } + ; + } + }; + } + + //Create the placeholder + self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); + + //Append it after the actual current item + self.currentItem.after(self.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(self, self.placeholder); + + }, + + _contactContainers:function (event) { + + // get innermost container that intersects with item + var innermostContainer = null, innermostIndex = null; + + + for (var i = this.containers.length - 1; i >= 0; i--) { + + // never consider a container that's located within the item itself + if ($.ui.contains(this.currentItem[0], this.containers[i].element[0])) + continue; + + if (this._intersectsWith(this.containers[i].containerCache)) { + + // if we've already found a container and it's more "inner" than this, then continue + if (innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) + continue; + + innermostContainer = this.containers[i]; + innermostIndex = i; + + } else { + // container doesn't intersect. trigger "out" event if necessary + if (this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + // if no intersecting containers found, return + if (!innermostContainer) return; + + // move the item into the container if it's not there already + if (this.containers.length === 1) { + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } else if (this.currentContainer != this.containers[innermostIndex]) { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; + var itemWithLeastDistance = null; + var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; + for (var j = this.items.length - 1; j >= 0; j--) { + if (!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; + var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; + if (Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); + itemWithLeastDistance = this.items[j]; + } + } + + if (!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + return; + + this.currentContainer = this.containers[innermostIndex]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } + + + }, + + _createHelper:function (event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); + + if (!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + + if (helper[0] == this.currentItem[0]) + this._storedCSS = { width:this.currentItem[0].style.width, height:this.currentItem[0].style.height, position:this.currentItem.css("position"), top:this.currentItem.css("top"), left:this.currentItem.css("left") }; + + if (helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if (helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + + return helper; + + }, + + _adjustOffsetFromHelper:function (obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left:+obj[0], top:+obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset:function () { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if (this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if ((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top:0, left:0 }; + + return { + top:po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), + left:po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) + }; + + }, + + _getRelativeOffset:function () { + + if (this.cssPosition == "relative") { + var p = this.currentItem.position(); + return { + top:p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(), + left:p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top:0, left:0 }; + } + + }, + + _cacheMargins:function () { + this.margins = { + left:(parseInt(this.currentItem.css("marginLeft"), 10) || 0), + top:(parseInt(this.currentItem.css("marginTop"), 10) || 0) + }; + }, + + _cacheHelperProportions:function () { + this.helperProportions = { + width:this.helper.outerWidth(), + height:this.helper.outerHeight() + }; + }, + + _setContainment:function () { + + var o = this.options; + if (o.containment == 'parent') o.containment = this.helper[0].parentNode; + if (o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if (!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top, + co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left, + co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo:function (d, pos) { + + if (!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top:( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left:( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition:function (event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if (this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if (this.originalPosition) { //If we are not dragging yet, we won't check for options + + if (this.containment) { + if (event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if (event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if (event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if (event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if (o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top:( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left:( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange:function (event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var self = this, counter = this.counter; + + window.setTimeout(function () { + if (counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + }, 0); + + }, + + _clear:function (event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = [], self = this; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if (!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if (this.helper[0] == this.currentItem[0]) { + for (var i in this._storedCSS) { + if (this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if (this.fromOutside && !noPropagation) delayedTriggers.push(function (event) { + this._trigger("receive", event, this._uiHash(this.fromOutside)); + }); + if ((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function (event) { + this._trigger("update", event, this._uiHash()); + }); //Trigger update callback if the DOM position has changed + if (!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element + if (!noPropagation) delayedTriggers.push(function (event) { + this._trigger("remove", event, this._uiHash()); + }); + for (var i = this.containers.length - 1; i >= 0; i--) { + if ($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { + delayedTriggers.push((function (c) { + return function (event) { + c._trigger("receive", event, this._uiHash(this)); + }; + }).call(this, this.containers[i])); + delayedTriggers.push((function (c) { + return function (event) { + c._trigger("update", event, this._uiHash(this)); + }; + }).call(this, this.containers[i])); + } + } + ; + } + ; + + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--) { + if (!noPropagation) delayedTriggers.push((function (c) { + return function (event) { + c._trigger("deactivate", event, this._uiHash(this)); + }; + }).call(this, this.containers[i])); + if (this.containers[i].containerCache.over) { + delayedTriggers.push((function (c) { + return function (event) { + c._trigger("out", event, this._uiHash(this)); + }; + }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if (this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if (this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity + if (this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + + this.dragging = false; + if (this.cancelHelperRemoval) { + if (!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i = 0; i < delayedTriggers.length; i++) { + delayedTriggers[i].call(this, event); + } + ; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + return false; + } + + if (!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if (this.helper[0] != this.currentItem[0]) this.helper.remove(); + this.helper = null; + + if (!noPropagation) { + for (var i = 0; i < delayedTriggers.length; i++) { + delayedTriggers[i].call(this, event); + } + ; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger:function () { + if ($.Widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash:function (inst) { + var self = inst || this; + return { + helper:self.helper, + placeholder:self.placeholder || $([]), + position:self.position, + originalPosition:self.originalPosition, + offset:self.positionAbs, + item:self.currentItem, + sender:inst ? inst.element : null + }; + } + + }); + + $.extend($.ui.sortable, { + version:"1.8.18" + }); + + })(); + +})); diff --git a/app/js/libs/bui/jquery-ui/jquery.ui.widget.js b/app/js/libs/bui/jquery-ui/jquery.ui.widget.js new file mode 100644 index 0000000..6cc01da --- /dev/null +++ b/app/js/libs/bui/jquery-ui/jquery.ui.widget.js @@ -0,0 +1,288 @@ +/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + (function (undefined) { + + // jQuery 1.4+ + if ($.cleanData) { + var _cleanData = $.cleanData; + $.cleanData = function (elems) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + try { + $(elem).triggerHandler("remove"); + // http://bugs.jquery.com/ticket/8235 + } catch (e) { + } + } + _cleanData(elems); + }; + } else { + var _remove = $.fn.remove; + $.fn.remove = function (selector, keepData) { + return this.each(function () { + if (!keepData) { + if (!selector || $.filter(selector, [ this ]).length) { + $("*", this).add([ this ]).each(function () { + try { + $(this).triggerHandler("remove"); + // http://bugs.jquery.com/ticket/8235 + } catch (e) { + } + }); + } + } + return _remove.call($(this), selector, keepData); + }); + }; + } + + $.widget = function (name, base, prototype) { + var namespace = name.split(".")[ 0 ], + fullName; + name = name.split(".")[ 1 ]; + fullName = namespace + "-" + name; + + if (!prototype) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName ] = function (elem) { + return !!$.data(elem, name); + }; + + $[ namespace ] = $[ namespace ] || {}; + $[ namespace ][ name ] = function (options, element) { + // allow instantiation without initializing for simple inheritance + if (arguments.length) { + this._createWidget(options, element); + } + }; + + var basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + // $.each( basePrototype, function( key, val ) { + // if ( $.isPlainObject(val) ) { + // basePrototype[ key ] = $.extend( {}, val ); + // } + // }); + basePrototype.options = $.extend(true, {}, basePrototype.options); + $[ namespace ][ name ].prototype = $.extend(true, basePrototype, { + namespace:namespace, + widgetName:name, + widgetEventPrefix:$[ namespace ][ name ].prototype.widgetEventPrefix || name, + widgetBaseClass:fullName + }, prototype); + + $.widget.bridge(name, $[ namespace ][ name ]); + }; + + $.widget.bridge = function (name, object) { + $.fn[ name ] = function (options) { + var isMethodCall = typeof options === "string", + args = Array.prototype.slice.call(arguments, 1), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.extend.apply(null, [ true, options ].concat(args)) : + options; + + // prevent calls to internal methods + if (isMethodCall && options.charAt(0) === "_") { + return returnValue; + } + + if (isMethodCall) { + this.each(function () { + var instance = $.data(this, name), + methodValue = instance && $.isFunction(instance[options]) ? + instance[ options ].apply(instance, args) : + instance; + // TODO: add this back in 1.9 and use $.error() (see #5972) + // if ( !instance ) { + // throw "cannot call methods on " + name + " prior to initialization; " + + // "attempted to call method '" + options + "'"; + // } + // if ( !$.isFunction( instance[options] ) ) { + // throw "no such method '" + options + "' for " + name + " widget instance"; + // } + // var methodValue = instance[ options ].apply( instance, args ); + if (methodValue !== instance && methodValue !== undefined) { + returnValue = methodValue; + return false; + } + }); + } else { + this.each(function () { + var instance = $.data(this, name); + if (instance) { + instance.option(options || {})._init(); + } else { + $.data(this, name, new object(options, this)); + } + }); + } + + return returnValue; + }; + }; + + $.Widget = function (options, element) { + // allow instantiation without initializing for simple inheritance + if (arguments.length) { + this._createWidget(options, element); + } + }; + + $.Widget.prototype = { + widgetName:"widget", + widgetEventPrefix:"", + options:{ + disabled:false + }, + _createWidget:function (options, element) { + // $.widget.bridge stores the plugin instance, but we do it anyway + // so that it's stored even before the _create function runs + $.data(element, this.widgetName, this); + this.element = $(element); + this.options = $.extend(true, {}, + this.options, + this._getCreateOptions(), + options); + + var self = this; + this.element.bind("remove." + this.widgetName, function () { + self.destroy(); + }); + + this._create(); + this._trigger("create"); + this._init(); + }, + _getCreateOptions:function () { + return $.metadata && $.metadata.get(this.element[0])[ this.widgetName ]; + }, + _create:function () { + }, + _init:function () { + }, + + destroy:function () { + this.element + .unbind("." + this.widgetName) + .removeData(this.widgetName); + this.widget() + .unbind("." + this.widgetName) + .removeAttr("aria-disabled") + .removeClass( + this.widgetBaseClass + "-disabled " + + "ui-state-disabled"); + }, + + widget:function () { + return this.element; + }, + + option:function (key, value) { + var options = key; + + if (arguments.length === 0) { + // don't return a reference to the internal hash + return $.extend({}, this.options); + } + + if (typeof key === "string") { + if (value === undefined) { + return this.options[ key ]; + } + options = {}; + options[ key ] = value; + } + + this._setOptions(options); + + return this; + }, + _setOptions:function (options) { + var self = this; + $.each(options, function (key, value) { + self._setOption(key, value); + }); + + return this; + }, + _setOption:function (key, value) { + this.options[ key ] = value; + + if (key === "disabled") { + this.widget() + [ value ? "addClass" : "removeClass"]( + this.widgetBaseClass + "-disabled" + " " + + "ui-state-disabled") + .attr("aria-disabled", value); + } + + return this; + }, + + enable:function () { + return this._setOption("disabled", false); + }, + disable:function () { + return this._setOption("disabled", true); + }, + + _trigger:function (type, event, data) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event(event); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if (orig) { + for (prop in orig) { + if (!( prop in event )) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger(event, data); + + return !( $.isFunction(callback) && + callback.call(this.element[0], event, data) === false || + event.isDefaultPrevented() ); + } + }; + + })(); + +})); diff --git a/app/js/libs/bui/redactor/css/docstyle.css b/app/js/libs/bui/redactor/css/docstyle.css new file mode 100755 index 0000000..c2a3015 --- /dev/null +++ b/app/js/libs/bui/redactor/css/docstyle.css @@ -0,0 +1,145 @@ +html { + padding: 0; + margin: 0; +} + +body { + font-family: Helvetica, Arial, Verdana, Tahoma, sans-serif; + font-size: 15px; + margin: 0; + padding: 0; + overflow-x: hidden; + background: #f4f4f4; +} + +#page { + max-width: 900px; + width: 74%; + margin: 20px auto; + padding: 15px 50px; + background: #fff; + border: 1px solid #ddd; +} + +#page:focus { + outline: none; +} + +::selection { + background-color: #333; + color: #fff; + text-shadow: none; +} + +div, +p, +ul, +ol, +table, +dl, +blockquote, +pre, +iframe, +object, +hr { + margin-bottom: 15px; + line-height: 1.5em; +} + +blockquote { + margin-left: 3em; + font-style: italic; + color: #777; +} + +ul, ol { + padding-left: 2em; +} + +ul ul, +ol ol, +ul ol, +ol ul { + border: none; + margin: 2px !important; + padding: 0; + padding-left: 2em; +} + +dl dt { + font-weight: bold; +} + +dd { + margin-left: 1em; +} + +table { + border-collapse: collapse; + font-size: 1em; +} + +table td { + border: 1px solid #ddd; + padding: 5px; +} + +table thead td { + border-bottom: 2px solid #000 !important; + font-weight: bold; +} + +code, pre { + font-family: monospace sans-serif; +} + +code { + background-color: #d8d7d7; +} + +pre { + padding: 1em; + border: 1px dashed #ccc; + background: #f5f5f5; + overflow: auto; +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; +} + +h1, h2, h3, h4, h5 { + font-weight: bold; +} + +h1 { + font-size: 36px; + line-height: 40px; + margin-bottom: 10px; +} + +h2 { + font-size: 30px; + line-height: 36px; + margin-bottom: 15px; +} + +h3 { + font-size: 24px; + line-height: 30px; + margin-bottom: 10px; +} + +h4 { + font-size: 18px; + line-height: 24px; + margin-bottom: 10px; +} + +h4 { + font-size: 1em; + margin-bottom: 10px; +} diff --git a/app/js/libs/bui/redactor/css/redactor.css b/app/js/libs/bui/redactor/css/redactor.css new file mode 100644 index 0000000..3a88bd3 --- /dev/null +++ b/app/js/libs/bui/redactor/css/redactor.css @@ -0,0 +1,468 @@ +.redactor_box { + position: relative; + border: 1px solid #ddd; + line-height: 0; +} + +.redactor_box, .redactor_box textarea { + background-color: #fff; +} + +.redactor_box iframe { + outline: none; + width: 100%; + background: #fff; + display: block; + overflow: auto; +} + +.redactor_box textarea { + font-family: Menlo, Monaco, monospace, sans-serif; + font-size: 13px; + overflow: auto; + resize: none; + margin: 0; + padding: 0; + display: block; + position: relative; + z-index: 1004; + outline: none; + border: none; + width: 100%; +} + +.redactor_box textarea:focus { + outline: none !important; + border: none !important; + box-shadow: none; +} + +/* + Fuulscreen +*/ +body .redactor_box_fullscreen { + border: medium none !important; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + z-index: 2000; +} + +/* + TOOLBAR +*/ +.redactor_toolbar { + position: relative; + left: 0; + top: 0; + margin: 0 !important; + padding: 0 !important; + line-height: 0 !important; + list-style: none; + font-size: 0; + background: #f2f2f2; + background: -moz-linear-gradient(top, #f5f5f5 0%, #ddd 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f5f5f5), color-stop(100%, #ddd)); + background: -webkit-linear-gradient(top, #f5f5f5 0%, #ddd 100%); + background: -o-linear-gradient(top, #f5f5f5 0%, #ddd 100%); + background: -ms-linear-gradient(top, #f5f5f5 0%, #ddd 100%); + background: linear-gradient(top, #f5f5f5 0%, #ddd 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#f5f5f5', endColorstr = '#dddddd', GradientType = 0); + overflow: hidden; + border-bottom: 1px solid #bbb; +} + +.redactor_toolbar li { + float: left !important; + padding: 3px 1px; + padding-right: 0; + list-style-type: none; +} + +.redactor_toolbar li.redactor_separator { + float: left; + height: 34px; + border-left: 1px solid #d7d7d7; + border-right: 1px solid #eee; + padding: 0; + margin: 0 2px 0 3px; +} + +li.redactor_toolbar_right { + float: none; + float: right !important; + padding: 2px 0; + padding-right: 1px !important; +} + +.redactor_toolbar li a, .redactor_toolbar li a span { + width: 25px; + height: 26px; +} + +.redactor_toolbar li a { + border: 1px solid transparent; + *border: 1px solid #eee; + display: block; + line-height: 0; + font-size: 0; + cursor: pointer; + zoom: 1; + text-decoration: none; +} + +.redactor_toolbar li a span { + display: block; + text-indent: -9999px; + background: url(../img/icons.png) no-repeat top left; +} + +.redactor_toolbar li a:hover { + border-color: #98a6ba; + background-color: #dde4ef; +} + +.redactor_toolbar li a:active, .redactor_toolbar li a.act { + border-color: #b5b5b5; + background-color: #e8e8e8; +} + +/* + BUTTONS + step 25px +*/ +body .redactor_toolbar li a.redactor_btn_html span { + background-position: 0; +} + +body .redactor_toolbar li a.redactor_btn_styles span { + background-position: -25px; +} + +body .redactor_toolbar li a.redactor_btn_bold span { + background-position: -50px; +} + +body .redactor_toolbar li a.redactor_btn_italic span { + background-position: -75px; +} + +body .redactor_toolbar li a.redactor_btn_deleted span { + background-position: -550px; +} + +body .redactor_toolbar li a.redactor_btn_insertunorderedlist span { + background-position: -100px; +} + +body .redactor_toolbar li a.redactor_btn_insertorderedlist span { + background-position: -125px; +} + +body .redactor_toolbar li a.redactor_btn_outdent span { + background-position: -150px; +} + +body .redactor_toolbar li a.redactor_btn_indent span { + background-position: -175px; +} + +body .redactor_toolbar li a.redactor_btn_image span { + background-position: -200px; +} + +body .redactor_toolbar li a.redactor_btn_video span { + background-position: -225px; +} + +body .redactor_toolbar li a.redactor_btn_file span { + background-position: -250px; +} + +body .redactor_toolbar li a.redactor_btn_table span { + background-position: -275px; +} + +body .redactor_toolbar li a.redactor_btn_link span { + background-position: -300px; +} + +body .redactor_toolbar li a.redactor_btn_fontcolor span { + background-position: -325px; +} + +body .redactor_toolbar li a.redactor_btn_backcolor span { + background-position: -350px; +} + +body .redactor_toolbar li a.redactor_btn_justifyleft span { + background-position: -375px; +} + +body .redactor_toolbar li a.redactor_btn_justifycenter span { + background-position: -400px; +} + +body .redactor_toolbar li a.redactor_btn_justifyright span { + background-position: -425px; +} + +body .redactor_toolbar li a.redactor_btn_justify span { + background-position: -450px; +} + +body .redactor_toolbar li a.redactor_btn_horizontalrule span { + background-position: -475px; +} + +body .redactor_toolbar li a.redactor_btn_fullscreen span { + background-position: -500px; +} + +body .redactor_toolbar li a.redactor_btn_normalscreen span { + background-position: -525px !important; +} + +/* + RESIZER +*/ +.redactor_resizer { + background-color: #f5f5f5; + padding-top: 2px; + line-height: 4px; + font-size: 12px; + color: #ddd; + text-align: center; + text-shadow: 0 -1px 0 #aaa; + cursor: s-resize; +} + +/* + DROPDOWN +*/ +.redactor_dropdown { + top: 28px; + left: 0; + z-index: 2004; + position: absolute; + width: 200px; + background-color: #fff; + border: 1px solid #ccc; + font-size: 13px; + -webkit-box-shadow: 0 2px 4px #ccc; + -moz-box-shadow: 0 2px 4px #ccc; + box-shadow: 0 2px 4px #ccc; + line-height: 21px; + padding: 10px; +} + +.redactor_separator_drop { + border-top: 1px solid #ddd;; + padding: 0 !important; + line-height: 0; + font-size: 0; +} + +.redactor_dropdown a { + display: block; + color: #000; + padding: 3px 5px; + text-decoration: none; +} + +.redactor_dropdown a:hover { + color: #444 !important; + text-decoration: none; + background-color: #dde4ef; +} + +/* ColorPicker */ +.redactor_color_link { + padding: 0 !important; + width: 15px !important; + height: 15px !important; + float: left !important; + border: 2px solid #fff !important; + font-size: 0; +} + +.redactor_color_none { + font-size: 11px; +} + +/* MODAL */ +#redactor_modal_overlay { + position: fixed; + margin: auto; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 50000; + + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; + filter: alpha(opacity = 80); + opacity: 0.80; + + background-color: #fff !important; +} + +#redactor_modal { + background-color: #fff; + padding: 0; + position: fixed; + top: 50%; + left: 50%; + + box-shadow: 0px 5px 20px #999; + -webkit-box-shadow: 0 5px 20px #999; + -moz-box-shadow: 0 5px 20px #999; + + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + + z-index: 50001; + font-family: Helvetica, Arial, Verdana, Tahoma, sans-serif; + font-size: 12px !important; + color: #000; +} + +#redactor_modal_header { + padding: 15px; + font-size: 18px; + + border-radius: 8px 8px 0 0; + + font-weight: bold; + background-color: #f6f6f6; + border-bottom: 1px solid #ddd; +} + +#redactor_modal_inner { + padding: 15px 30px 20px 30px; +} + +#redactor_modal_close { + position: absolute; + right: 0px; + top: 11px; + font-size: 24px; + width: 30px; + height: 30px; + color: #999; + cursor: pointer; +} + +#redactor_modal_close:hover { + color: #000; +} + +#redactor_modal_footer { + overflow: hidden; + padding-top: 20px; +} + +#redactor_modal label { + margin: 10px 0 0 0 !important; + padding: 0 !important; + float: none !important; + display: block !important; +} + +#redactor_btn_modal_close { + color: #777; + font-size: 11px !important; +} + +.redactor_input { + width: 99%; + font-size: 14px; +} + +#redactor_image_box { + height: 270px; + overflow: auto; + margin-bottom: 10px; +} + +#redactor_image_box img { + margin-right: 10px; + margin-bottom: 10px; + cursor: pointer; +} + +#redactor_tabs { + margin-bottom: 18px; +} + +#redactor_tabs a { + display: inline-block; + border: 1px solid #ddd; + padding: 4px 14px; + font-size: 12px; + text-decoration: none; + color: #000; + line-height: 1; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; +} + +#redactor_tabs a:hover, #redactor_tabs a.redactor_tabs_act { + background-color: #eee; + color: #777 !important; + text-decoration: none !important; +} + +.redactor_btns_box { + float: right; + padding: 6px 16px; + background-color: #eee; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +/* Drag and Drop Area */ +.redactor_droparea { + position: relative; + width: 100%; + margin: auto; + margin-bottom: 5px; +} + +.redactor_droparea .redactor_dropareabox { + z-index: 1; + position: relative; + text-align: center; + width: 99%; + padding: 60px 0; + border: 2px dashed #bbb; +} + +.redactor_droparea .redactor_dropareabox, .redactor_dropalternative { + color: #777; + font-size: 12px; +} + +.redactor_dropalternative { + margin: 4px 0 2px 0; +} + +.redactor_dropareabox.hover { + background: #efe3b8; + border-color: #aaa; +} + +.redactor_dropareabox.error { + background: #f7e5e5; + border-color: #dcc3c3; +} + +.redactor_dropareabox.drop { + background: #f4f4ee; + border-color: #e0e5d6; +} diff --git a/app/js/libs/bui/redactor/css/style.css b/app/js/libs/bui/redactor/css/style.css new file mode 100755 index 0000000..02d9978 --- /dev/null +++ b/app/js/libs/bui/redactor/css/style.css @@ -0,0 +1,141 @@ +html { + padding: 0; + margin: 0; +} + +body { + font-family: Helvetica, Arial, Verdana, Tahoma, sans-serif; + font-size: 15px; + margin: 0; + padding: 0; + overflow-x: hidden; + background: #fff; +} + +#page { + margin: 20px; + background: #fff; +} + +#page:focus { + outline: none; +} + +::selection { + background-color: #333; + color: #fff; + text-shadow: none; +} + +div, +p, +ul, +ol, +table, +dl, +blockquote, +pre, +iframe, +object, +hr { + margin-bottom: 15px; + line-height: 1.5em; +} + +blockquote { + margin-left: 3em; + font-style: italic; + color: #777; +} + +ul, ol { + padding-left: 2em; +} + +ul ul, +ol ol, +ul ol, +ol ul { + border: none; + margin: 2px !important; + padding: 0; + padding-left: 2em; +} + +dl dt { + font-weight: bold; +} + +dd { + margin-left: 1em; +} + +table { + border-collapse: collapse; + font-size: 1em; +} + +table td { + border: 1px solid #ddd; + padding: 5px; +} + +table thead td { + border-bottom: 2px solid #000 !important; + font-weight: bold; +} + +code, pre { + font-family: monospace sans-serif; +} + +code { + background-color: #d8d7d7; +} + +pre { + padding: 1em; + border: 1px dashed #ccc; + background: #f5f5f5; + overflow: auto; +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; +} + +h1, h2, h3, h4, h5 { + font-weight: bold; +} + +h1 { + font-size: 36px; + line-height: 40px; + margin-bottom: 10px; +} + +h2 { + font-size: 30px; + line-height: 36px; + margin-bottom: 15px; +} + +h3 { + font-size: 24px; + line-height: 30px; + margin-bottom: 10px; +} + +h4 { + font-size: 18px; + line-height: 24px; + margin-bottom: 10px; +} + +h4 { + font-size: 1em; + margin-bottom: 10px; +} diff --git a/app/js/libs/bui/redactor/css/wym.css b/app/js/libs/bui/redactor/css/wym.css new file mode 100755 index 0000000..006dd55 --- /dev/null +++ b/app/js/libs/bui/redactor/css/wym.css @@ -0,0 +1,155 @@ +body { + font-family: Helvetica, Arial, Verdana, Tahoma, sans-serif; + font-size: 15px; + margin: 0; + padding: 0; + overflow-x: hidden; + background-color: #f8f8f8; +} + +#page { + margin: 20px; + background: #f8f8f8; + border: none; + padding: 0; +} + +#page:focus { + outline: none; +} + +div, +p, +ul, +ol, +table, +dl, +pre, +h1, +h2, +h3, +h4, +h5, +blockquote { + background-color: #fff; + border: 1px solid #ebebeb; + padding: 10px; + margin: 10px 0; +} + +p ul, +p ol { + margin: 0; + padding: 0; + border: none; +} + +div, +p, +ul, +ol, +table, +dl, +blockquote, +pre, +iframe, +object, +hr { + margin-bottom: 15px; + line-height: 1.5em; +} + +blockquote { + margin-left: 3em; + font-style: italic; + color: #777; +} + +div { + background-color: #fff; + border: 1px dashed #ebebeb; +} + +ul, ol { + padding-left: 2em !important; +} + +ul ul, +ol ol, +ul ol, +ol ul { + border: none; + margin: 2px !important; + padding: 0; + padding-left: 2em; +} + +dl dt { + font-weight: bold; +} + +dd { + margin-left: 1em; +} + +table { + border-collapse: collapse; + font-size: 1em; +} + +table td { + border: 1px solid #ddd; + padding: 5px; +} + +table thead td { + border-bottom: 2px solid #000 !important; + font-weight: bold; +} + +code, pre { + font-family: monospace sans-serif; +} + +code { + background-color: #d8d7d7; +} + +pre { + padding: 1em; + border: 1px dashed #ccc; + background: #f5f5f5; + overflow: auto; +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; +} + +h1, h2, h3, h4, h5 { + font-weight: bold; + margin-bottom: 10px; +} + +h1 { + font-size: 36px; +} + +h2 { + font-size: 30px; +} + +h3 { + font-size: 24px; +} + +h4 { + font-size: 18px; +} + +h4 { + font-size: 1em; +} diff --git a/app/js/libs/bui/redactor/img/icons.png b/app/js/libs/bui/redactor/img/icons.png new file mode 100644 index 0000000..8862469 Binary files /dev/null and b/app/js/libs/bui/redactor/img/icons.png differ diff --git a/app/js/libs/bui/redactor/langs/bg.js b/app/js/libs/bui/redactor/langs/bg.js new file mode 100644 index 0000000..caf6b91 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/bg.js @@ -0,0 +1,75 @@ +var RLANG = { + html:'HTML', + video:'Видео', + image:'Изображение', + table:'Таблица', + link:'Връзка', + link_insert:'Вкарай връзка ...', + unlink:'Премахни връзка', + styles:'Стилове', + paragraph:'Параграф', + quote:'Цитат', + code:'Код', + header1:'Заглавие 1', + header2:'Заглавие 2', + header3:'Заглавие 3', + header4:'Заглавие 4', + format:'Форматиране', + bold:'Удебели', + italic:'Наклони', + superscript:'Горен индекс', + strikethrough:'Зачеркни', + fontcolor:'Цвят на текста', + backcolor:'Цвят на фона', + removeformat:'Премахни форматирането', + cleanstyles:'Изчисти стиловете', + lists:'Списъци', + unorderedlist:'Неподреден списък', + orderedlist:'Подреден списък', + outdent:'Вкарай навътре', + indent:'Изкарай навън', + redo:'Повтори', + undo:'Отмени', + cut:'Изрежи', + cancel:'Отказ', + insert:'Вкарай', + save:'Запази', + _delete:'Премахни', + insert_table:'Вкарай таблица', + insert_row_above:'Добави ред отгоре', + insert_row_below:'Добави ред отдолу', + insert_column_left:'Добави колона отляво', + insert_column_right:'Добави колона отдясно', + delete_column:'Премахни колоната', + delete_row:'Премахни реда', + delete_table:'Премахни таблицата', + Rows:'Редове', + Columns:'Колони', + add_head:'Добави заглавен ред', + delete_head:'Премахни заглавен ред', + title:'Заглавие', + image_view:'Виж изображението', + image_position:'Позиция', + left:'ляво', + right:'дясно', + image_web_link:'Уеб връзка', + text:'Текст', + mailto:'Имейл', + web:'Адрес', + video_html_code:'Код за вграждане на видео', + file:'Файл', + upload:'Качи', + download:'Свали', + choose:'Избор', + or_choose:'Или избери', + drop_file_here:'Провлачете файлове тук', + align_left:'Подравни в ляво', + align_center:'Центрирай', + align_right:'Подравни в дясно', + align_justify:'Подравни двустранно', + horizontalrule:'Хоризонтална линия', + fullscreen:'Цял екран', + deleted:'Зачеркни', + none:'Няма', + anchor:'Връзка' +}; diff --git a/app/js/libs/bui/redactor/langs/by.js b/app/js/libs/bui/redactor/langs/by.js new file mode 100644 index 0000000..ecf504c --- /dev/null +++ b/app/js/libs/bui/redactor/langs/by.js @@ -0,0 +1,72 @@ +var RLANG = { + html:'Код', + video:'Відэа', + image:'Малюнак', + table:'Табліца', + link:'Спасылка', + link_insert:'Уставіць спасылку ...', + unlink:'Выдаліць спасылку', + styles:'Стылі', + paragraph:'Звычайны тэкст', + quote:'Цытата', + code:'Код', + header1:'Загаловак 1', + header2:'Загаловак 2', + format:'Фармат', + bold:'Паўтлусты', + italic:'Нахільны', + superscript:'Надрадковы', + strikethrough:'Закрэслены', + fontcolor:'Колер тэксту', + backcolor:'Заліванне тэксту', + removeformat:'Выдаліць фармат', + cleanstyles:'Выдаліць стылі MS Word', + lists:'Спісы', + unorderedlist:'Звычайны спіс', + orderedlist:'Нумараваны спіс', + outdent:'Паменьшыць водступ', + indent:'Павялічыць водступ', + redo:'Паўтор', + undo:'Адмена', + cut:'Кат / Урэзка', + cancel:'Адмяніць', + insert:'Уставіць', + save:'Захаваць', + _delete:'Выдаліць', + insert_table:'Уставіць табліцу', + insert_row_above:'Дадаць радок зверху', + insert_row_below:'Дадаць радок знізу', + insert_column_left:'Дадаць слупок злева', + insert_column_right:'Дадаць слупок справа', + delete_column:'Выдаліць слупок', + delete_row:'Выдаліць радок', + delete_table:'Выдаліць табліцу', + Rows:'Радкі', + Columns:'Стаўбцы', + add_head:'Дадаць загаловак', + delete_head:'Выдаліць загаловак', + title:'Падказка', + image_view:'Запампаваць малюнак', + image_position:'Абцяканне тэкстам', + none:'Няма', + left:'Злева', + right:'Справа', + image_web_link:'Спасылка на малюнак', + text:'Тэкст', + mailto:'Эл. пошта ', + web:'URL', + video_html_code:'Код відэа роліка', + file:'Файл', + upload:'Загрузіць', + download:'Запампаваць', + choose:'Выбраць', + or_choose:'Ці іншае', + drop_file_here:'Перацягніце файл сюды', + align_left:'Па левым краі', + align_center:'Па цэнтры', + align_right:'Па правым краі', + align_justify:'Выраўнаваць тэкст па шырыні', + horizontalrule:'Гарызантальная лінейка', + fullscreen:'Ва ўвесь экран', + deleted:'Закрэслены' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/cs.js b/app/js/libs/bui/redactor/langs/cs.js new file mode 100755 index 0000000..5f7d358 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/cs.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Obrázek', + table:'Tabulka', + link:'Odkaz', + link_insert:'Vložit odkaz ...', + unlink:'Odstranit odkaz', + styles:'Styly', + paragraph:'Odstavec', + quote:'Citace', + code:'Kód', + header1:'Nadpis 1', + header2:'Nadpis 2', + header3:'Nadpis 3', + header4:'Nadpis 4', + format:'Formát', + bold:'Tučné', + italic:'Kurzíva', + superscript:'Horní index', + strikethrough:'Přeškrtnuté', + fontcolor:'Barva písma', + backcolor:'Barva pozadí', + removeformat:'Odstranit formátování', + cleanstyles:'Odstranit styly', + lists:'Seznamy', + unorderedlist:'Seznam s odrážkami', + orderedlist:'Číslovaný seznam', + outdent:'Zmenšit odsazení', + indent:'Zvětšit odsazení', + redo:'Vpřed', + undo:'Zpět', + cut:'Vyjmout', + cancel:'Zrušit', + insert:'Vložit', + save:'Uložit', + _delete:'Smazat', + insert_table:'Vložit tabulku', + insert_row_above:'Přidat řádek nahoru', + insert_row_below:'Přidat řádek dolu', + insert_column_left:'Přidat sloupec vlevo', + insert_column_right:'Přidat sloupec vpravo', + delete_column:'Smazat sloupec', + delete_row:'Smazat řádek', + delete_table:'Smazat tabulku', + Rows:'Řádky', + Columns:'Sloupce', + add_head:'Přidat záhlaví', + delete_head:'Smazat záhlaví', + title:'Titulek', + image_view:'Zobrazit obrázek', + image_position:'Pozice', + none:'žádný', + left:'vlevo', + right:'vpravo', + image_web_link:'Odkaz na obrázek', + text:'Text', + mailto:'Email', + web:'URL', + video_html_code:'Kód pro vložení videa na stránku', + file:'Soubor', + upload:'Nahrát', + download:'Stáhnout', + choose:'Vybrat', + or_choose:'nebo', + drop_file_here:'Přetáhněte soubor zde', + align_left:'Zarovnat vlevo', + align_center:'Zarovnat na střed', + align_right:'Zarovnat vpravo', + align_justify:'Zarovnat do bloku', + horizontalrule:'Vodorovná čára', + fullscreen:'Celá obrazovka', + deleted:'Přeškrtnuté', + none:'Žádná', + anchor:'Záložka' +}; diff --git a/app/js/libs/bui/redactor/langs/de.js b/app/js/libs/bui/redactor/langs/de.js new file mode 100755 index 0000000..f19a371 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/de.js @@ -0,0 +1,75 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Bilder', + table:'Tabelle', + link:'Link', + link_insert:'Link einfügen ...', + unlink:'Link entfernen', + styles:'Styles', + paragraph:'Absatz', + quote:'Zitat', + code:'Code', + header1:'Kopfzeile 1', + header2:'Kopfzeile 2', + header3:'Kopfzeile 3', + header4:'Kopfzeile 4', + format:'Format', + bold:'Fett', + italic:'Kursiv', + superscript:'Hochgestellt', + strikethrough:'Strikethrough', + fontcolor:'Schriftfarbe', + backcolor:'Texthervorhebungsfarbe', + removeformat:'Formatierung löschen', + cleanstyles:'Styles säubern', + lists:'Lists', + unorderedlist:'Aufzählungszeichen', + orderedlist:'Nummerierung', + outdent:'Einzug verkleinern', + indent:'Einzug vergrößern', + redo:'Wiederholen', + undo:'Rückgängig', + cut:'Ausschneiden', + cancel:'Abbrechen', + insert:'Einfügen', + save:'Speichern', + _delete:'Löschen', + insert_table:'Tabelle einfügen', + insert_row_above:'Zeilen oberhalb einfügen', + insert_row_below:'Zeilen unterhalb einfügen', + insert_column_left:'Spalten links einfügen', + insert_column_right:'Spalten rechts einfügen', + delete_column:'Spalten löschen', + delete_row:'Zeilen löschen', + delete_table:'Tabelle löschen', + Rows:'Zeilen', + Columns:'Spalten', + add_head:'Titel einfügen', + delete_head:'Titel entfernen', + title:'Title', + image_view:'Bider', + image_position:'Textumbruch', + none:'Keine', + left:'Links', + right:'Rechts', + image_web_link:'Bilder Link', + text:'Text', + mailto:'Email', + web:'URL', + video_html_code:'Video embed code', + file:'Datei', + upload:'laden', + download:'Download', + choose:'Auswählen', + or_choose:'Oder, wählen Sie', + drop_file_here:'Ziehen Sie eine Datei hier', + align_left:'Linksbündig', + align_center:'Mitte', + align_right:'Rechtsbündig', + align_justify:'Setzt den Text der Breite', + horizontalrule:'Horizontale Linie', + fullscreen:'Vollbild', + deleted:'Durchgestrichen', + anchor:'Anker' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/en.js b/app/js/libs/bui/redactor/langs/en.js new file mode 100644 index 0000000..652833c --- /dev/null +++ b/app/js/libs/bui/redactor/langs/en.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Image', + table:'Table', + link:'Link', + link_insert:'Insert link ...', + unlink:'Unlink', + styles:'Styles', + paragraph:'Paragraph', + quote:'Quote', + code:'Code', + header1:'Header 1', + header2:'Header 2', + header3:'Header 3', + header4:'Header 4', + format:'Format', + bold:'Bold', + italic:'Italic', + superscript:'Superscript', + strikethrough:'Strikethrough', + fontcolor:'Font color', + backcolor:'Back color', + removeformat:'Remove format', + cleanstyles:'Clean styles', + lists:'Lists', + unorderedlist:'Unordered list', + orderedlist:'Ordered list', + outdent:'Outdent', + indent:'Indent', + redo:'Redo', + undo:'Undo', + cut:'Cut', + cancel:'Cancel', + insert:'Insert', + save:'Save', + _delete:'Delete', + insert_table:'Insert table', + insert_row_above:'Add row above', + insert_row_below:'Add row below', + insert_column_left:'Add column left', + insert_column_right:'Add column right', + delete_column:'Delete column', + delete_row:'Delete row', + delete_table:'Delete table', + Rows:'Rows', + Columns:'Columns', + add_head:'Add head', + delete_head:'Delete head', + title:'Title', + image_view:'View image', + image_position:'Position', + none:'none', + left:'left', + right:'right', + image_web_link:'Image web link', + text:'Text', + mailto:'Email', + web:'URL', + video_html_code:'Video embed code', + file:'File', + upload:'Upload', + download:'Download', + choose:'Choose', + or_choose:'Or choose', + drop_file_here:'Drop file here', + align_left:'Align left', + align_center:'Align center', + align_right:'Align right', + align_justify:'Justify', + horizontalrule:'Horizontal rule', + fullscreen:'Fullscreen', + deleted:'Deleted', + none:'None', + anchor:'Anchor' +}; diff --git a/app/js/libs/bui/redactor/langs/es.js b/app/js/libs/bui/redactor/langs/es.js new file mode 100644 index 0000000..4dbf216 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/es.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Imagen', + table:'Tabla', + link:'Enlace', + link_insert:'Insertar enlace ...', + unlink:'Desenlazar', + styles:'Estilos', + paragraph:'Párrafo', + quote:'Comillas', + code:'Código', + header1:'Cabecera 1', + header2:'Cabecera 2', + header3:'Cabecera 3', + header4:'Cabecera 4', + format:'Formato', + bold:'Negrita', + italic:'Itálica', + superscript:'Superindice', + strikethrough:'Tachado', + fontcolor:'Color fuente', + backcolor:'Color fondo', + removeformat:'Elimar formato', + cleanstyles:'Limpiar estilos', + lists:'Listas', + unorderedlist:'Lista sin orden', + orderedlist:'Lista ordenada', + outdent:'Disminuir sangrado', + indent:'Sangrar', + redo:'Rehacer', + undo:'Deshacer', + cut:'Cortar', + cancel:'Cancelar', + insert:'Añadir', + save:'Guardar', + _delete:'Borrar', + insert_table:'Añadir tabla', + insert_row_above:'Añadir fila arriba', + insert_row_below:'Añadir fila debajo', + insert_column_left:'Añadir columna a la izquierda', + insert_column_right:'Añadir column a la derecha', + delete_column:'Borrar columna', + delete_row:'Borrar fila', + delete_table:'Borrar tabla', + Rows:'Filas', + Columns:'Columnas', + add_head:'Añadir cabecera', + delete_head:'Borrar cabecera', + title:'Título', + image_view:'Ver imagen', + image_position:'Posición', + none:'ninguna', + left:'izquierda', + right:'derecha', + image_web_link:'Enlace de imagen web', + text:'Texto', + mailto:'Email', + web:'URL', + video_html_code:'Código embebido del video', + file:'Fichero', + upload:'Cargar', + download:'Descargar', + choose:'Seleccionar', + or_choose:'O seleccionar', + drop_file_here:'Soltar el fichero aquí', + align_left:'Alinear a la izquierda', + align_center:'Alinear al centro', + align_right:'Alinear a la derecha', + align_justify:'Justificar', + horizontalrule:'Trazo horizontal', + fullscreen:'Pantalla completa', + deleted:'Borrado', + none:'Ninguno', + anchor:'Anclaje o anchor' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/fr.js b/app/js/libs/bui/redactor/langs/fr.js new file mode 100644 index 0000000..d3bb033 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/fr.js @@ -0,0 +1,74 @@ +var RLANG = { + html:'Code HTML', + video:'Vidéo', + image:'Image', + table:'Tableau', + link:'Lien URL', + link_insert:'Insérer un lien', + unlink:'Nétoyer le lien', + styles:'Styles', + paragraph:'Paragraphe', + quote:'Citation', + code:'Code', + header1:'Titre 1', + header2:'Titre 2', + header3:'Titre 3', + header4:'Titre 4', + format:'Format', + bold:'Gras', + italic:'Italique', + superscript:'Diacritique', + strikethrough:'Rayé', + fontcolor:'Couleur du texte', + backcolor:'Couleur du fond de ligne', + removeformat:'Nétoyer le format', + lists:'Listes', + unorderedlist:'Liste à puce', + orderedlist:'Liste numérotée', + outdent:'Diminuer l\'alinéa', + indent:'Augmenter l\'alinéa', + redo:'Refaire', + undo:'Défaire', + cut:'Couper', + cancel:'Annuler', + insert:'Insérer', + save:'Sauvegarder', + _delete:'Supprimer', + insert_table:'Insérer le tableau', + insert_row_above:'Ajouter une ligne au dessus', + insert_row_below:'Ajouter une ligne en dessous', + insert_column_left:'Ajouter une colonne à gauche', + insert_column_right:'Ajouter une colonne à droite', + delete_column:'Supprimer la colonne', + delete_row:'Supprimer la ligne', + delete_table:'Supprimer le tableau', + Rows:'Lignes ', + Columns:'Colonnes', + add_head:'Ajouter un titre', + delete_head:'Supprimer le titre', + title:'Titre', + image_view:'Voir l\'image', + image_position:'Position de l\'image', + none:'aucun', + left:'à gauche', + right:'à droite', + image_web_link:'lien de l’image', + text:'Texte', + mailto:'Envoyer à ', + web:'URL', + video_html_code:'Code HTML de la vidéo', + file:'Fichier', + upload:'Envoyer', + download:'Télécharger', + choose:'Choisir', + or_choose:'ou', + drop_file_here:'Glissez-déposez le fichier ici', + align_left:'Aligenr à gauche', + align_center:'Aligner au centre', + align_right:'Aligner à droite', + align_justify:'Justifier', + horizontalrule:'Ligne horizontale', + fullscreen:'Plein écran', + deleted:'Supprimer', + none:'aucun' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/hu.js b/app/js/libs/bui/redactor/langs/hu.js new file mode 100644 index 0000000..4ac3428 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/hu.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Videó', + image:'Kép', + table:'Tábla', + link:'Link', + link_insert:'Link beszúrás ...', + unlink:'Link megszüntetés', + styles:'Stílusok', + paragraph:'Bekezdés', + quote:'Idézet', + code:'Kód', + header1:'Címsor 1', + header2:'Címsor 2', + header3:'Címsor 3', + header4:'Címsor 4', + format:'Formátum', + bold:'Félkövér', + italic:'Dőlt', + superscript:'Felső index', + strikethrough:'Áthúzott', + fontcolor:'Szöveg szine', + backcolor:'Szöveg hátterének szine', + removeformat:'Formátum eltávolítása', + cleanstyles:'Stilusok törlése', + lists:'Listák', + unorderedlist:'Nem számozott lista', + orderedlist:'Számozott lista', + outdent:'Outdent', + indent:'Indent', + redo:'Újra', + undo:'Visszavonás', + cut:'Kivágás', + cancel:'Mégsem', + insert:'Beszurás', + save:'Mentés', + _delete:'Törlés', + insert_table:'Táblázat beszúrása', + insert_row_above:'Sor beszúrása az aktuális sor fölé', + insert_row_below:'Sor beszúrása ez alá', + insert_column_left:'Oszlop beszúrása ettöl balra', + insert_column_right:'Oszlop hozzáadása ettöl jobbra', + delete_column:'Oszlop törlése', + delete_row:'Sor törlése', + delete_table:'Táblázat törlése', + Rows:'Sorok', + Columns:'Oszlopok', + add_head:'Fejrész hozzáadása', + delete_head:'Fejrész törlése', + title:'Felira', + image_view:'Kép megnézése', + image_position:'Pozició', + none:'nincs', + left:'bal', + right:'jobb', + image_web_link:'Link a képre', + text:'Szöveg', + mailto:'Email', + web:'URL', + video_html_code:'Videó embed code', + file:'File', + upload:'Feltöltés', + download:'Letöltés', + choose:'Válassz', + or_choose:'Vagy válassz', + drop_file_here:'Ide dobd a file-t', + align_left:'Balra igazítás', + align_center:'Középre igazítás', + align_right:'Jobbra igazítás', + align_justify:'Sorkizárt', + horizontalrule:'Horizontális vonal', + fullscreen:'Teljes képernyős', + deleted:'Törölt', + none:'Nincs', + anchor:'Horgony' +}; diff --git a/app/js/libs/bui/redactor/langs/it.js b/app/js/libs/bui/redactor/langs/it.js new file mode 100755 index 0000000..6a56fa1 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/it.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Immagine', + table:'Tabella', + link:'Collegamento', + link_insert:'Inserisci un collegamento ...', + unlink:'Rimuovi il collegamento', + styles:'Stili', + paragraph:'Paragrafo', + quote:'Quote', + code:'Codice', + header1:'H1', + header2:'H2', + header3:'H3', + header4:'H4', + format:'Formatta', + bold:'Grassetto', + italic:'Corsivo', + superscript:'Superscript', + strikethrough:'Strikethrough', + fontcolor:'Colore del font', + backcolor:'Colore di sfondo', + removeformat:'Rimuovi formattazione', + cleanstyles:'Ripulisci stili', + lists:'Elenco', + unorderedlist:'Elenco puntato', + orderedlist:'Elenco numerato', + outdent:'Outdent', + indent:'Indent', + redo:'Ripeti', + undo:'Annulla', + cut:'Taglia', + cancel:'Cancella', + insert:'Inserisci', + save:'Salva', + _delete:'rimuovi', + insert_table:'Inserisci tabella', + insert_row_above:'Inserisci una riga sopra', + insert_row_below:'Inserisci una riga sotto', + insert_column_left:'Aggiungi una colonna a sinistra', + insert_column_right:'Aggiungi una colonna a destra', + delete_column:'Cancella colonna', + delete_row:'Cancella riga', + delete_table:'Cancella tabella', + Rows:'Righe', + Columns:'Colonne', + add_head:'Aggiungi head', + delete_head:'Cancella head', + title:'Titolo', + image_view:'Visualizza immagine', + image_position:'Posizione', + none:'Nessun', + left:'Sinistra', + right:'Destra', + image_web_link:'URL immagine', + text:'Testo', + mailto:'Email', + web:'URL', + video_html_code:'Embed code filmato', + file:'File', + upload:'Upload', + download:'Download', + choose:'Scegli', + or_choose:'O Scegli', + drop_file_here:'Trascina il file qui', + align_left:'Allinea a sinistra', + align_center:'Allinea al centro', + align_right:'Allinea a destra', + align_justify:'Giustifica', + horizontalrule:'Orizzonatale', + fullscreen:'Schermo intero', + deleted:'Cancellato', + none:'Nessun', + anchor:'Ancora' +}; diff --git a/app/js/libs/bui/redactor/langs/ja.js b/app/js/libs/bui/redactor/langs/ja.js new file mode 100644 index 0000000..b85b1a1 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/ja.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'ビデオ', + image:'イメージ', + table:'テーブル', + link:'リンク', + link_insert:'リンクの挿入 ...', + unlink:'リンクを外す', + styles:'スタイル', + paragraph:'段落', + quote:'引用', + code:'コード', + header1:'ヘッダー 1', + header2:'ヘッダー 2', + header3:'ヘッダー 3', + header4:'ヘッダー 4', + format:'フォーマット', + bold:'太字', + italic:'イタリック', + superscript:'上付き文字', + strikethrough:'取り消し線', + fontcolor:'フォント色', + backcolor:'背景色', + removeformat:'フォーマットの解除', + cleanstyles:'スタイルのクリヤー', + lists:'リスト', + unorderedlist:'番号なしリスト', + orderedlist:'番号つきリスト', + outdent:'字上げ(逆インデント)', + indent:'字下げ(インデント)', + redo:'再実行', + undo:'元に戻す', + cut:'カット', + cancel:'キャンセル', + insert:'挿入', + save:'保存', + _delete:'削除', + insert_table:'テーブルの挿入', + insert_row_above:'列を上に追加', + insert_row_below:'列を下に追加', + insert_column_left:'行を左に追加', + insert_column_right:'行を右に追加', + delete_column:'行を削除', + delete_row:'列を削除', + delete_table:'テーブルを削除', + Rows:'列', + Columns:'行', + add_head:'テーブルヘッダの追加', + delete_head:'テーブルヘッダの削除', + title:'タイトル', + image_view:'イメージを見る', + image_position:'イメージの位置', + none:'無し', + left:'左', + right:'右', + image_web_link:'イメージへのリンク', + text:'テキスト', + mailto:'メール', + web:'URL', + video_html_code:'ビデオ埋め込みコード', + file:'ファイル', + upload:'アップロード', + download:'ダウンロード', + choose:'選択', + or_choose:'または選択', + drop_file_here:'ファイルをここにドロップ', + align_left:'左揃え', + align_center:'中央揃え', + align_right:'右揃え', + align_justify:'均等割り付け', + horizontalrule:'水平線', + fullscreen:'全画面', + deleted:'打消し', + none:'無し', + anchor:'アンカー' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/lv.js b/app/js/libs/bui/redactor/langs/lv.js new file mode 100644 index 0000000..32a02b7 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/lv.js @@ -0,0 +1,74 @@ +var RLANG = { + html:'HTML кods', + video:'Video', + image:'Attēls', + table:'Tabula', + link:'Saite', + link_insert:'Iekļaut saiti ...', + unlink:'Noņemt saiti', + styles:'Stili', + paragraph:'Vienkāršs teksts', + quote:'Citāts', + code:'Kods', + header1:'Virsraksts 1', + header2:'Virsraksts 2', + header3:'Virsraksts 3', + header4:'Virsraksts 4', + format:'Formāts', + bold:'Pustrekns', + italic:'Slīps', + superscript:'Augšraksts', + strikethrough:'Nosvītrots', + fontcolor:'Teksta krāsa', + backcolor:'Fona krāsa', + removeformat:'Noņemt stilus', + cleanstyles:'Noņemt stilus MS Word', + lists:'Saraksti', + unorderedlist:'Parasts saraksts', + orderedlist:'Numurēts saraksts', + outdent:'Samazināt atkāpi', + indent:'Palielināt atkāpi', + redo:'Atatsaukt', + undo:'Atsaukt', + cut:'Izgriezt', + cancel:'Atcelt', + insert:'Iespraust', + save:'Saglabāt', + _delete:'Dzēst', + insert_table:'Iespraust tabulu', + insert_row_above:'Pievienot rindu no augšas', + insert_row_below:'Pievienot rindu no apakšas', + insert_column_left:'Pievienot stabiņu no kreisās puses', + insert_column_right:'Pievienot stabiņu no labās puses', + delete_column:'Dzēst stabiņu', + delete_row:'Dzēst rindu', + delete_table:'Dzēst tabulu', + Rows:'Rindas', + Columns:'Stabiņi', + add_head:'Pievienot virsrakstu', + delete_head:'Dzēst virsrakstu', + title:'Uzvedne', + image_view:'Apskatīt attēlu', + image_position:'Аttēla apliece', + none:'nav', + left:'pa kreisi', + right:'pa labi', + image_web_link:'vai saite uz attēlu', + text:'Teksts', + mailto:'E-pasts', + web:'URL', + video_html_code:'Videoklipu kods', + file:'Fails', + upload:'Augšupielāde', + download:'Lejupielāde', + choose:'Izvēlieties', + or_choose:'Vai izvēlieties', + drop_file_here:'Vilkt failu uz šejieni', + align_left:'Izlīdzināt pa labi', + align_center:'Izlīdzināt pa kreisi', + align_right:'Izlīdzināt pret centru', + align_justify:'Izlīdzināt malas', + horizontalrule:'Horizontāla līnija', + fullscreen:'Pa visu ekrānu', + none:'None' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/nl.js b/app/js/libs/bui/redactor/langs/nl.js new file mode 100644 index 0000000..25af72a --- /dev/null +++ b/app/js/libs/bui/redactor/langs/nl.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Afbeelding', + table:'Tabel', + link:'Link', + link_insert:'Link invoegen...', + unlink:'Link ontkoppelen', + styles:'Stijlen', + paragraph:'Paragraaf', + quote:'Citaat', + code:'Code', + header1:'Kop 1', + header2:'Kop 2', + header3:'Kop 3', + header4:'Kop 4', + format:'Format', + bold:'Vet', + italic:'Cursief', + superscript:'Superscript', + strikethrough:'Doorstrepen', + fontcolor:'Tekstkleur', + backcolor:'Achtergrondkleur', + removeformat:'Verwijder formattering', + cleanstyles:'Stijlen opschonen', + lists:'Lijsten', + unorderedlist:'Ongeordende lijst', + orderedlist:'Geordende lijst', + outdent:'Uitspringen', + indent:'Inspringen', + redo:'Opnieuw maken', + undo:'Ongedaan maken', + cut:'Knippen', + cancel:'Annuleren', + insert:'Invoegen', + save:'Opslaan', + _delete:'Verwijderen', + insert_table:'Tabel invoegen', + insert_row_above:'Rij hierboven invoegen', + insert_row_below:'Rij hieronder invoegen', + insert_column_left:'Kolom links toevoegen', + insert_column_right:'Kolom rechts toevoegen', + delete_column:'Verwijder kolom', + delete_row:'Verwijder rij', + delete_table:'Verwijder tabel', + Rows:'Rijen', + Columns:'Kolommen', + add_head:'Titel toevoegen', + delete_head:'Titel verwijderen', + title:'Titel', + image_view:'Toon afbeelding', + image_position:'Positie', + none:'geen', + left:'links', + right:'rechts', + image_web_link:'Afbeelding link', + text:'Tekst', + mailto:'Email', + web:'URL', + video_html_code:'Video embed code', + file:'Bestand', + upload:'Uploaden', + download:'Downloaden', + choose:'Kies', + or_choose:'Of kies', + drop_file_here:'Sleep bestand hier', + align_left:'Links uitlijnen', + align_center:'Centreren', + align_right:'Rechts uitlijnen', + align_justify:'Uitvullen', + horizontalrule:'Horizontale lijn', + fullscreen:'Volledig scherm', + deleted:'Verwijderd', + none:'Geen', + anchor:'Anker' +}; diff --git a/app/js/libs/bui/redactor/langs/pl.js b/app/js/libs/bui/redactor/langs/pl.js new file mode 100644 index 0000000..e2d910a --- /dev/null +++ b/app/js/libs/bui/redactor/langs/pl.js @@ -0,0 +1,75 @@ +var RLANG = { + html:'Źródło', + video:'Wideo', + image:'Obrazek', + table:'Tabela', + link:'Link', + link_insert:'Wstaw link ...', + unlink:'Usuń link', + styles:'Style', + paragraph:'Zwykły tekst', + quote:'Cytat', + code:'Kod źródłowy', + header1:'Nagłówek 1', + header2:'Nagłówek 2', + header3:'Nagłówek 3', + header4:'Nagłówek 4', + format:'Format', + bold:'Pogrubiony', + italic:'Pochylony', + superscript:'Indeks górny', + strikethrough:'Przekreślenie', + fontcolor:'Kolor tekstu', + backcolor:'Kolor tła', + removeformat:'Wyczyść formatowanie', + cleanstyles:'Wyczyść style MS Word', + lists:'Wypunktowanie i numeracja', + unorderedlist:'Wypunktowanie', + orderedlist:'Numeracja', + outdent:'Zwiększ wcięcie', + indent:'Zmniejsz wcięcie', + redo:'Ponów', + undo:'Cofnij', + cut:'Wytnij', + cancel:'Anuluj', + insert:'Wstaw', + save:'Zachowaj', + _delete:'Usuń', + insert_table:'Wstaw tabele', + insert_row_above:'Dodaj wiersz na górze', + insert_row_below:'Dodaj wiersz na dole', + insert_column_left:'Dodaj kolumnę po lewej', + insert_column_right:'Dodaj kolumnę po prawej', + delete_column:'Usuń kolumnę', + delete_row:'Usuń wiersz', + delete_table:'Usuń tabele', + Rows:'Wiersze', + Columns:'Kolumny', + add_head:'Dodaj nagłówek', + delete_head:'Usuń nagłówek', + title:'Wskazówka', + image_view:'Pokaż obrazek', + image_position:'Obramowanie', + none:'nie ma', + left:'od lewej', + right:'od prawej', + image_web_link:'albo link do obrazku', + text:'Tekst', + mailto:'Poczta e-mail', + web:'URL', + video_html_code:'Kod źródłowy pliku wideo', + file:'Plik', + upload:'Wgraj na serwer', + download:'Pobierz', + choose:'Choose', + or_choose:'Or choose', + drop_file_here:'Drop file here', + align_left:'Align left', + align_center:'Align center', + align_right:'Align right', + align_justify:'Justify', + horizontalrule:'Horizontal rule', + fullscreen:'Fullscreen', + deleted:'Deleted', + none:'None' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/pt_br.js b/app/js/libs/bui/redactor/langs/pt_br.js new file mode 100644 index 0000000..b3387b0 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/pt_br.js @@ -0,0 +1,81 @@ +var RLANG = { + html:'Ver HTML', + video:'Vídeo', + image:'Imagem', + table:'Tabela', + link:'Link', + link_insert:'Inserir link...', + unlink:'Remover link', + styles:'Estilos', + paragraph:'Parágrafo', + quote:'Citação', + code:'Código', + header1:'Título 1', + header2:'Título 2', + header3:'Título 3', + header4:'Título 4', + format:'Formato', + bold:'Negrito', + italic:'Itálico', + superscript:'Sobrescrito', + strikethrough:'Taxado', + fontcolor:'Cor da fonte', + backcolor:'Cor do fundo', + removeformat:'Remover formato', + cleanstyles:'Limpar estilos', + lists:'Listas', + unorderedlist:'Lista não ordenada', + orderedlist:'Lista ordenada', + outdent:'Remover identação', + indent:'Identar', + redo:'Refazer', + undo:'Voltar', + cut:'Inserir divisão', + cancel:'Cancelar', + insert:'Inserir', + save:'Salvar', + _delete:'Remover', + insert_table:'Inserir tabela', + add_cell:'Adicionar coluna', + delete_cell:'Remover coluna', + add_row:'Adicionar linha', + delete_row:'Remover linha', + thead:'Cabeçalho', + delete_table:'Remover tabela', + insert_row_above:'Adicionar linha acima', + insert_row_below:'Adicionar linha abaixo', + insert_column_left:'Adicionar coluna à esquerda', + insert_column_right:'Adicionar coluna da direita', + delete_column:'Remover Coluna', + delete_row:'Remover linha', + delete_table:'Remover tabela', + Rows:'Linhas', + Columns:'Colunas', + add_head:'Adicionar cabeçalho', + delete_head:'Remover cabeçalho', + title:'Título', + image_view:'Visualizar imagem', + image_position:'Posição', + none:'nenhum', + left:'esquerda', + right:'direita', + image_web_link:'link para uma imagem', + text:'Texto', + mailto:'Email', + web:'URL', + video_html_code:'Video embed code', + file:'Arquivo', + upload:'Upload', + download:'Download', + choose:'Escolha', + or_choose:'Ou escolha', + drop_file_here:'Arraste um arquivo até aqui', + align_left:'Alinhar a esquerda', + align_center:'Centralizar', + align_right:'Alinhar a direita', + align_justify:'Justificar', + horizontalrule:'Linha horizontal', + fullscreen:'Tela cheia', + deleted:'Removido', + none:'Nenhum' +}; diff --git a/app/js/libs/bui/redactor/langs/ru.js b/app/js/libs/bui/redactor/langs/ru.js new file mode 100644 index 0000000..15b4c51 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/ru.js @@ -0,0 +1,75 @@ +var RLANG = { + html:'Код', + video:'Видео', + image:'Изображение', + table:'Таблица', + link:'Ссылка', + link_insert:'Вставить ссылку ...', + unlink:'Удалить ссылку', + styles:'Стили', + paragraph:'Обычный текст', + quote:'Цитата', + code:'Код', + header1:'Заголовок 1', + header2:'Заголовок 2', + header3:'Заголовок 3', + header4:'Заголовок 4', + format:'Формат', + bold:'Полужирный', + italic:'Наклонный', + superscript:'Надстрочный', + strikethrough:'Зачеркнутый', + fontcolor:'Цвет текста', + backcolor:'Заливка текста', + removeformat:'Удалить формат', + cleanstyles:'Удалить стили MS Word', + lists:'Списки', + unorderedlist:'Обычный список', + orderedlist:'Нумерованный список', + outdent:'Уменьшить отступ', + indent:'Увеличить отступ', + redo:'Повтор', + undo:'Отмена', + cut:'Кат / Врезка', + cancel:'Отменить', + insert:'Вставить', + save:'Сохранить', + _delete:'Удалить', + insert_table:'Вставить таблицу', + insert_row_above:'Добавить строку сверху', + insert_row_below:'Добавить строку снизу', + insert_column_left:'Добавить столбец слева', + insert_column_right:'Добавить столбец справа', + delete_column:'Удалить столбец', + delete_row:'Удалить строку', + delete_table:'Удалить таблицу', + Rows:'Строки', + Columns:'Столбцы', + add_head:'Добавить заголовок', + delete_head:'Удалить заголовок', + title:'Подсказка', + image_view:'Скачать изображение', + image_position:'Обтекание текстом', + left:'слева', + right:'справа', + image_web_link:'Cсылка на изображение', + text:'Текст', + mailto:'Эл. почта', + web:'URL', + video_html_code:'Код видео ролика', + file:'Файл', + upload:'Загрузить', + download:'Скачать', + choose:'Выбрать', + or_choose:'Или выберите', + drop_file_here:'Перетащите файл сюда', + align_left:'По левому краю', + align_center:'По центру', + align_right:'По правому краю', + align_justify:'Выровнять текст по ширине', + horizontalrule:'Горизонтальная линейка', + fullscreen:'Во весь экран', + deleted:'Зачеркнутый', + none:'Нет', + anchor:'Якорь' +}; diff --git a/app/js/libs/bui/redactor/langs/sq.js b/app/js/libs/bui/redactor/langs/sq.js new file mode 100644 index 0000000..5599181 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/sq.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Fotografi', + table:'Tabelë', + link:'Link', + link_insert:'Lidh linq ...', + unlink:'Hiq linkun', + styles:'Stilet', + paragraph:'Paragraf', + quote:'Kuotë', + code:'Kod', + header1:'Header 1', + header2:'Header 2', + header3:'Header 3', + header4:'Header 4', + format:'Formati', + bold:'Te trasha / Bold', + italic:'Kursive / Italic', + superscript:'Superscript', + strikethrough:'Strikethrough', + fontcolor:'Ngjyra e shkronjave', + backcolor:'Ngjyra e mbrapavisë së shkronjave', + removeformat:'Fshije formatin', + cleanstyles:'Pastro stilet', + lists:'Listat', + unorderedlist:'Liste pa renditje', + orderedlist:'Liste me renditje', + outdent:'Outdent', + indent:'Indent', + redo:'Ribëj', + undo:'Zhbëj', + cut:'Cut', + cancel:'Anulo', + insert:'Insert', + save:'Ruaje', + _delete:'Fshije', + insert_table:'Shto tabelë', + insert_row_above:'Shto rresht sipër', + insert_row_below:'Shto rresht përfundi', + insert_column_left:'Shto kolonë majtas', + insert_column_right:'Shto kolonë djathtas', + delete_column:'Fshije kolonën', + delete_row:'Fshije rreshtin', + delete_table:'Fshije tabelën', + Rows:'Rreshta', + Columns:'Kolona', + add_head:'Shto titujt e tabelës', + delete_head:'Fshije titujt e tabelës', + title:'Titulli', + image_view:'Shiko fotografinë', + image_position:'Pozita', + none:'Normale', + left:'Majtas', + right:'Djathtas', + image_web_link:'Linku i fotografisë në internet', + text:'Teksti', + mailto:'Email', + web:'URL', + video_html_code:'Video embed code', + file:'Fajll', + upload:'Ngarko', + download:'Shkarko', + choose:'Zgjedh', + or_choose:'Ose zgjedh', + drop_file_here:'Gjuaje fajllin këtu', + align_left:'Rreshtoje majtas', + align_center:'Rreshtoje në mes', + align_right:'Rreshtoje djathtas', + align_justify:'Rreshtoje të gjithin njejt', + horizontalrule:'Vizë horizontale', + fullscreen:'Pamje e plotë', + deleted:'E fshirë', + none:'None', + anchor:'Anchor' +}; diff --git a/app/js/libs/bui/redactor/langs/tr.js b/app/js/libs/bui/redactor/langs/tr.js new file mode 100644 index 0000000..437bbb9 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/tr.js @@ -0,0 +1,76 @@ +var RLANG = { + html:'HTML', + video:'Video', + image:'Görsel', + table:'Tablo', + link:'Bağlantı', + link_insert:'Bağlantı Ekle ...', + unlink:'Bağlantı Kaldır', + styles:'Stiller', + paragraph:'Paragraf', + quote:'Alıntı', + code:'Kod', + header1:'Başlık 1', + header2:'Başlık 2', + header3:'Başlık 3', + header4:'Başlık 4', + format:'Biçim', + bold:'Kalın', + italic:'Eğik', + superscript:'Üst simge', + strikethrough:'Üstü çizili', + fontcolor:'Yazı rengi', + backcolor:'Arkaplan rengi', + removeformat:'Biçimi kaldır', + cleanstyles:'Stilleri temizle', + lists:'Listeler', + unorderedlist:'Sırasız liste', + orderedlist:'Sıralı liste', + outdent:'Girintiyi azalt', + indent:'Girintiyi artır', + redo:'Yeniden yap', + undo:'Geri al', + cut:'Kes', + cancel:'İptal', + insert:'Ekle', + save:'Kaydet', + _delete:'Sil', + insert_table:'Tablo ekle', + insert_row_above:'Yukarı satır ekle', + insert_row_below:'Alta satır ekle', + insert_column_left:'Sola sütun ekle', + insert_column_right:'Sağa sütun ekle', + delete_column:'Sütun sil', + delete_row:'Satır sil', + delete_table:'Tablo sil', + Rows:'Satırlar', + Columns:'Sütunlar', + add_head:'Başlık ekle', + delete_head:'Başlık sil', + title:'Başlık', + image_view:'Görseli göster', + image_position:'Pozisyon', + none:'hiçbiri', + left:'sol', + right:'sağ', + image_web_link:'Görselin web bağlantısı', + text:'Yazı', + mailto:'E-Posta', + web:'URL', + video_html_code:'Video embed kodu', + file:'Dosya', + upload:'Yükle', + download:'İndir', + choose:'Seç', + or_choose:'Veya seç', + drop_file_here:'Dosyayı buraya bırak', + align_left:'Sola hizala', + align_center:'Ortala', + align_right:'Sağa hizala', + align_justify:'Satır uzunluğuna ayarla', + horizontalrule:'Yatay çizgi', + fullscreen:'Tam ekran', + deleted:'Silindi', + none:'Hiçbiri', + anchor:'Çapa' +}; diff --git a/app/js/libs/bui/redactor/langs/ua.js b/app/js/libs/bui/redactor/langs/ua.js new file mode 100644 index 0000000..db78aab --- /dev/null +++ b/app/js/libs/bui/redactor/langs/ua.js @@ -0,0 +1,75 @@ +var RLANG = { + html:'Код', + video:'Відео', + image:'Зображення', + table:'Таблиця', + link:'Посилання', + link_insert:'Вставити посилання ...', + unlink:'Видалити посилання', + styles:'Стилі', + paragraph:'Звичайний текст', + quote:'Цитата', + code:'Код', + header1:'Заголовок 1', + header2:'Заголовок 2', + header3:'Заголовок 3', + header4:'Заголовок 4', + format:'Формат', + bold:'Жирний', + italic:'Похилий', + superscript:'Надрядковий', + strikethrough:'Закреслений', + fontcolor:'Колір тексту', + backcolor:'Заливка тексту', + removeformat:'Видалити формат', + cleanstyles:'Видалити стилі MS Word', + lists:'Списки', + unorderedlist:'Звичайний список', + orderedlist:'Нумерований список', + outdent:'Зменшити відступ', + indent:'Збільшити відступ', + redo:'Повтор', + undo:'Скасування', + cut:'Кат / Врізка', + cancel:'Скасувати', + insert:'Вставити', + save:'Зберегти', + _delete:'Видалити', + insert_table:'Вставити таблицю', + insert_row_above:'Додати рядок зверху', + insert_row_below:'Додати рядок знизу', + insert_column_left:'Додати стовпець ліворуч', + insert_column_right:'Додати стовпець праворуч', + delete_column:'Видалити стовпець', + delete_row:'Видалити рядок', + delete_table:'Видалити таблицю', + Rows:'Рядки', + Columns:'Стовпці', + add_head:'Додати заголовок', + delete_head:'Видалити заголовок', + title:'Підказка', + image_view:'Завантажити зображення', + image_position:'Обтікання текстом', + none:'ні', + left:'ліворуч', + right:'праворуч', + image_web_link:'Посилання на зображення', + text:'Текст', + mailto:'Ел. пошта', + web:'URL', + video_html_code:'Код відео ролика', + file:'Файл', + upload:'Вивантажити', + download:'Завантажити', + choose:'Выбрать', + or_choose:'Или выберите', + drop_file_here:'Перетащите файл сюда', + align_left:'По левому краю', + align_center:'По центру', + align_right:'По правому краю', + align_justify:'Выровнять текст по ширине', + horizontalrule:'Горизонтальная линейка', + fullscreen:'Во весь экран', + deleted:'Зачеркнутый', + none:'Нет' +}; \ No newline at end of file diff --git a/app/js/libs/bui/redactor/langs/zh_cn.js b/app/js/libs/bui/redactor/langs/zh_cn.js new file mode 100644 index 0000000..660e4f6 --- /dev/null +++ b/app/js/libs/bui/redactor/langs/zh_cn.js @@ -0,0 +1,77 @@ +//@chen1706@gmail.com +var RLANG = { + html:'HTML代码', + video:'视频', + image:'图片', + table:'表格', + link:'链接', + link_insert:'插入链接', + unlink:'取消链接', + styles:'样式', + paragraph:'段落', + quote:'引用', + code:'代码', + header1:'一级标题', + header2:'二级标题', + header3:'三级标题', + header4:'四级标题', + format:'格式', + bold:'粗体', + italic:'斜体', + superscript:'上标', + strikethrough:'删除线', + fontcolor:'字体颜色', + backcolor:'背景颜色', + removeformat:'取消格式', + cleanstyles:'清除样式', + lists:'目录', + unorderedlist:'项目编号', + orderedlist:'数字编号', + outdent:'减少缩进', + indent:'增加缩进', + redo:'重做', + undo:'撤销', + cut:'剪切', + cancel:'取消', + insert:'插入', + save:'保存', + _delete:'删除', + insert_table:'插入表格', + insert_row_above:'在上方插入', + insert_row_below:'在下方插入', + insert_column_left:'在左侧插入', + insert_column_right:'在右侧插入', + delete_column:'删除整列', + delete_row:'删除整行', + delete_table:'删除表格', + Rows:'行', + Columns:'列', + add_head:'添加标题', + delete_head:'删除标题', + title:'标题', + image_view:'查看图片', + image_position:'位置', + none:'无', + left:'左', + right:'右', + image_web_link:'图片网页链接', + text:'文本', + mailto:'邮箱', + web:'网址', + video_html_code:'视频嵌入代码', + file:'文件', + upload:'上传', + download:'下载', + choose:'选择', + or_choose:'或选择', + drop_file_here:'将文件拖拽至此区域', + align_left:'左对齐', + align_center:'居中', + align_right:'右对齐', + align_justify:'两端对齐', + horizontalrule:'水平线', + fullscreen:'全屏', + deleted:'删除', + none:'无', + anchor:'锚点' +}; diff --git a/app/js/libs/bui/redactor/redactor.js b/app/js/libs/bui/redactor/redactor.js new file mode 100644 index 0000000..a6bdb5c --- /dev/null +++ b/app/js/libs/bui/redactor/redactor.js @@ -0,0 +1,2139 @@ +/* + Redactor v7.6.4 + Updated 13.06.2012 + + http://redactorjs.com/ + + Copyright (c) 2009-2012, Imperavi Ltd. + Licensed under Creative Commons Attribution-NonCommercial 3.0 license. + + Usage: $('#content').redactor(); + */ + +var RTOOLBAR = {}; + +(function ($) { + + // Plugin + jQuery.fn.redactor = function (option) { + return this.each(function () { + var $this = $(this); + + var data = $this.data('redactor'); + if (!data) $this.data('redactor', (data = new Redactor(this, option))); + }); + }; + + + // Initialization + var Redactor = function (element, options) { + // Element + this.$el = $(element); + + // Options + this.opts = $.extend({ + + lang:'en', + direction:'ltr', // ltr or rtl + toolbar:'default', + + load:true, + callback:false, // function + keyupCallback:false, // function + + path:false, + css:'style.css', + focus:false, + resize:true, + autoresize:false, + fixed:false, + + autoformat:true, + cleanUp:true, + convertDivs:true, + removeClasses:true, + removeStyles:false, + convertLinks:true, + + handler:false, // false or url + + autosave:false, // false or url + interval:60, // seconds + + imageGetJson:false, // url (ex. /folder/images.json ) or false + + imageUpload:false, // url + imageUploadCallback:false, // function + + fileUpload:false, // url + fileUploadCallback:false, // function + + visual:true, + fullscreen:false, + overlay:true, // modal overlay + + colors:Array( + '#ffffff', '#000000', '#eeece1', '#1f497d', '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', '#f79646', '#ffff00', + '#f2f2f2', '#7f7f7f', '#ddd9c3', '#c6d9f0', '#dbe5f1', '#f2dcdb', '#ebf1dd', '#e5e0ec', '#dbeef3', '#fdeada', '#fff2ca', + '#d8d8d8', '#595959', '#c4bd97', '#8db3e2', '#b8cce4', '#e5b9b7', '#d7e3bc', '#ccc1d9', '#b7dde8', '#fbd5b5', '#ffe694', + '#bfbfbf', '#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#b7dde8', '#fac08f', '#f2c314', + '#a5a5a5', '#262626', '#494429', '#17365d', '#366092', '#953734', '#76923c', '#5f497a', '#92cddc', '#e36c09', '#c09100', + '#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#31859b', '#974806', '#7f6000'), + + // private + allEmptyHtml:'


', + mozillaEmptyHtml:'

 

', + + // modal windows container + modal:{} + + + }, options, this.$el.data()); + + this.dropdowns = []; + + // Init + this.init(); + }; + + // Functionality + Redactor.prototype = { + + // DYNAMICALLY LOAD + _loadFile:function (file, array) { + var item = array[0]; + array.splice(0, 1); + + var callback; + if (typeof(item) == 'function') callback = item; + else callback = $.proxy(function () { + this._loadFile(item, array); + }, this); + + this.dynamicallyLoad(file, callback); + }, + loadFiles:function (array) { + var item = array[0]; + array.splice(0, 1); + + this._loadFile(item, array); + }, + dynamicallyLoad:function (url, callback) { + var head = document.getElementsByTagName("head")[0]; + var script = document.createElement("script"); + script.src = url; + + var done = false; + + script.onload = script.onreadystatechange = function () { + if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) { + done = true; + if (callback) callback(); + script.onload = script.onreadystatechange = null; + } + }; + + head.appendChild(script); + + }, + + // Initialization + init:function () { + // get path to styles + this.getPath(); + + if (this.opts.load) { + // load files + var files = []; + + files.push(this.opts.path + '/langs/' + this.opts.lang + '.js'); + if (this.opts.toolbar !== false) files.push(this.opts.path + '/toolbars/' + this.opts.toolbar + '.js'); + files.push($.proxy(this.start, this)); + + this.loadFiles(files); + } + else this.start(); + + + }, + start:function () { + // setup modals + this.setupModalWindows(); + + // get dimensions + this.height = this.$el.css('height'); + this.width = this.$el.css('width'); + + // construct editor + this.build(); + + // get html + var html = this.$el.val(); + + // preformatter + html = this.preformater(html); + + // conver newlines to p + if (this.opts.autoformat) html = this.paragraphy(html); + + // enable + this.$editor = this.enable(html); + + // focus always on page + $(this.doc).click($.proxy(function (e) { + this.$editor.focus(); + }, this)); + + // cleanup + $(this.doc).on('paste', $.proxy(function (e) { + setTimeout($.proxy(function () { + var marker = Math.floor(Math.random() * 99999); + var marker_text = ''; + if ($.browser.mozilla) marker_text = ' '; + var node = $('' + marker_text + ''); + this.insertNodeAtCaret(node.get(0)); + + this.pasteCleanUp(marker); + + }, this), 200); + + }, this)); + + // keyup + $(this.doc).keyup($.proxy(function (e) { + var key = e.keyCode || e.which; + + // callback as you type + if (typeof this.opts.keyupCallback == 'function') this.opts.keyupCallback(this, e); + + if (this.opts.autoformat) { + // if empty + if (key == 8 || key == 46) return this.formatEmpty(e); + + // new line p + if (key == 13 && !e.shiftKey && !e.ctrlKey && !e.metaKey) return this.formatNewLine(e); + } + //console.log(e); + this.syncCode(); + + }, this)); + + // toolbar + this.buildToolbar(); + + // resizer + if (this.opts.autoresize === false) this.buildResizer(); + else this.observeAutoResize(); + + // shortcuts + this.shortcuts(); + + // autosave + this.autoSave(); + + // observers + this.observeImages(); + + // fullscreen on start + if (this.opts.fullscreen) { + this.opts.fullscreen = false; + this.fullscreen(); + } + + // focus + if (this.opts.focus) this.focus(); + + // fixed + if (this.opts.fixed) { + this.observeScroll(); + $(document).scroll($.proxy(this.observeScroll, this)); + } + + // callback + if (typeof this.opts.callback == 'function') { + this.opts.callback(this); + } + + }, + shortcuts:function () { + $(this.doc).keydown($.proxy(function (e) { + var key = e.keyCode || e.which; + + if (e.ctrlKey) { + if (key == 90) this._shortcuts(e, 'undo'); // Ctrl + z + else if (key == 90 && e.shiftKey) this._shortcuts(e, 'redo'); // Ctrl + Shift + z + else if (key == 77) this._shortcuts(e, 'removeFormat'); // Ctrl + m + else if (key == 66) this._shortcuts(e, 'bold'); // Ctrl + b + else if (key == 73) this._shortcuts(e, 'italic'); // Ctrl + i + else if (key == 74) this._shortcuts(e, 'insertunorderedlist'); // Ctrl + j + else if (key == 75) this._shortcuts(e, 'insertorderedlist'); // Ctrl + k + else if (key == 76) this._shortcuts(e, 'superscript'); // Ctrl + l + } + + if (!e.shiftKey && key == 9) this._shortcuts(e, 'indent'); // Tab + else if (e.shiftKey && key == 9) this._shortcuts(e, 'outdent'); // Shift + tab + + // safari shift key + enter + if ($.browser.webkit && navigator.userAgent.indexOf('Chrome') == -1) { + return this.safariShiftKeyEnter(e, key); + } + + }, this)); + + }, + _shortcuts:function (e, cmd) { + if (e.preventDefault) e.preventDefault(); + this.execCommand(cmd, null); + }, + getPath:function () { + if (this.opts.path !== false) return this.opts.path; + + $('script').each($.proxy(function (i, s) { + if (s.src) { + // Match redactor.js or redactor.min.js, followed by an optional querystring (often used for cache purposes) + var regexp = new RegExp(/\/redactor(\.min)?\.js(\?.*)?/); + if (s.src.match(regexp)) this.opts.path = s.src.replace(regexp, ''); + } + }, this)); + + }, + build:function () { + // container + this.$box = $('
'); + + // frame + this.$frame = $(''); + + // hide textarea + this.$el.css('width', '100%').hide(); + + // append box and frame + this.$box.insertAfter(this.$el).append(this.$frame).append(this.$el); + + }, + write:function (html) { + this.doc.open(); + this.doc.write(html); + this.doc.close(); + }, + enable:function (html) { + this.doc = this.getDoc(this.$frame.get(0)); + + if (this.doc !== null) { + this.write(this.setDoc(html)); + if ($.browser.mozilla) this.doc.execCommand("useCSS", false, true); + return $(this.doc).find('#page'); + } + else return false; + }, + setDoc:function (html) { + var frameHtml = '\n'; + frameHtml += ''; + frameHtml += '
'; + frameHtml += html; + frameHtml += '
'; + return frameHtml; + }, + getDoc:function (frame) { + if (frame.contentDocument) return frame.contentDocument; + else if (frame.contentWindow && frame.contentWindow.document) return frame.contentWindow.document; + else if (frame.document) return frame.document; + else return null; + }, + focus:function () { + this.$editor.focus(); + }, + syncCode:function () { + var html = this.formating(this.$editor.html()); + this.$el.val(html); + }, + + // API functions + setCode:function (html) { + html = this.preformater(html); + + this.$editor.html(html).focus(); + + this.syncCode(); + }, + getCode:function () { + var html = this.$editor ? this.$editor.html() : this.$el.val(); + html = this.reformater(html); + + return html; + }, + insertHtml:function (html) { + this.execCommand('inserthtml', html); + }, + destroy:function () { + var html = this.getCode(); + + this.$box.after(this.$el); + this.$box.remove(); + this.$el.val(html).show(); + + for (var i = 0; i < this.dropdowns.length; i++) { + this.dropdowns[i].remove(); + delete(this.dropdowns[i]); + } + + }, + handler:function () { + $.ajax({ + url:this.opts.handler, + type:'POST', + data:'redactor=' + escape(encodeURIComponent(this.getCode())), + success:$.proxy(function (data) { + this.setCode(data); + this.syncCode(); + + }, this) + }); + + }, + // end API functions + + // OBSERVERS + observeImages:function () { + if ($.browser.mozilla) this.doc.execCommand("enableObjectResizing", false, "false"); + + $(this.doc).find('img').attr('unselectable', 'on').each($.proxy(function (i, s) { + this.resizeImage(s); + + }, this)); + + }, + observeScroll:function () { + var scrolltop = $(document).scrollTop(); + var boxtop = this.$box.offset().top; + + if (scrolltop > boxtop) { + this.fixed = true; + this.$toolbar.css({position:'fixed', width:'100%'}); + } + else { + this.fixed = false; + this.$toolbar.css({position:'relative', width:'auto'}); + } + }, + observeAutoResize:function () { + this.$editor.css({ 'min-height':this.$el.height() + 'px' }); + $(this.doc).find('body').css({ 'overflow':'hidden' }); + this.setAutoSize(false); + $(this.doc).keyup($.proxy(this.setAutoSize, this)); + }, + setAutoSize:function (e) { + var key = false; + if (e !== false) key = e.keyCode || e.which; + + if (e == false || key == 13) this.$frame.height(this.$editor.outerHeight(true) + 30); + else if (key == 8 || key == 46) this.$frame.height(this.$editor.outerHeight(true)); + }, + + + // EXECCOMMAND + execCommand:function (cmd, param) { + if (this.opts.visual && this.doc) { + try { + if ($.browser.msie) this.focus(); + + if (cmd == 'inserthtml' && $.browser.msie) this.doc.selection.createRange().pasteHTML(param); + else if (cmd == 'formatblock' && $.browser.msie) this.doc.execCommand(cmd, false, '<' + param + '>'); + else { + this.doc.execCommand(cmd, false, param); + } + + this.syncCode(); + this.focus(); + } + catch (e) { + } + + } + }, + + // FORMAT NEW LINE + formatNewLine:function (e) { + var parent = this.getParentNode(); + if (parent.nodeName == 'DIV' && parent.id == 'page') { + if (e.preventDefault) e.preventDefault(); + + element = $(this.getCurrentNode()); + if (element.get(0).tagName == 'DIV' && (element.html() == '' || element.html() == '
')) { + newElement = $('

').append(element.clone().get(0).childNodes); + element.replaceWith(newElement); + newElement.html('
'); + this.setFocusNode(newElement.get(0)); + + this.syncCode(); + return false; + } + else this.syncCode(); + + // convert links + if (this.opts.convertLinks) this.$editor.linkify(); + } + else { + this.syncCode(); + return true; + } + }, + + // SAFARI SHIFT KEY + ENTER + safariShiftKeyEnter:function (e, key) { + if (e.shiftKey && key == 13) { + e.preventDefault(); + + var node1 = $('
'); + this.insertNodeAtCaret(node1.get(0)); + this.setFocusNode(node1.get(0)); + + this.syncCode(); + + return false; + } + else return true; + }, + + // FORMAT EMPTY + formatEmpty:function (e) { + var html = $.trim(this.$editor.html()); + + if ($.browser.mozilla) html = html.replace(/
/gi, ''); + + if (html === '') { + if (e.preventDefault) e.preventDefault(); + + var nodehtml = this.opts.allEmptyHtml; + if ($.browser.mozilla) nodehtml = this.opts.mozillaEmptyHtml; + + var node = $(nodehtml).get(0); + this.$editor.html(node); + this.setFocusNode(node); + + this.syncCode(); + return false; + } + else this.syncCode(); + }, + + // PARAGRAPHY + paragraphy:function (str) { + str = $.trim(str); + if (str === '') { + if (!$.browser.mozilla) return this.opts.allEmptyHtml; + else return this.opts.mozillaEmptyHtml; + } + + // convert div to p + if (this.opts.convertDivs) str = str.replace(/([\w\W]*?)<\/div>/gi, '

$2

'); + + // inner functions + var X = function (x, a, b) { + return x.replace(new RegExp(a, 'g'), b); + }; + var R = function (a, b) { + return X(str, a, b); + }; + + // block elements + var blocks = '(table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|style|script|object|input|param|p|h[1-6])'; + + str += '\n'; + + R('
\\s*
', '\n\n'); + R('(<' + blocks + '[^>]*>)', '\n$1'); + R('()', '$1\n\n'); + R('\r\n|\r', '\n'); // newlines + R('\n\n+', '\n\n'); // remove duplicates + R('\n?((.|\n)+?)$', '

$1

\n'); // including one at the end + R('

\\s*?

', ''); // remove empty p + R('

(]*>\\s*)', '$1

'); + R('

([^<]+)\\s*?(]*>)', '

$1

$2'); + R('

\\s*(]*>)\\s*

', '$1'); + R('

(', '$1'); + R('

\\s*(]*>)', '$1'); + R('(]*>)\\s*

', '$1'); + R('(]*>)\\s*
', '$1'); + R('
(\\s*]*>)', '$1'); + + // pre + if (str.indexOf(')((.|\n)*?)', function (m0, m1, m2, m3) { + return X(m1, '\\\\([\'\"\\\\])', '$1') + X(X(X(m3, '

', '\n'), '

|
', ''), '\\\\([\'\"\\\\])', '$1') + ''; + }); + } + + return R('\n

$', '

'); + }, + + // PREPARE FORMATER + preformater:function (html) { + html = html.replace(/
/gi, '
'); + + html = html.replace(/]*>([\w\W]*?)

([\w\W]*?)<\/p>([\w\W]*?)<\/blockquote[^>]*>/gi, '

$1$2
$3
'); + + html = html.replace(/]*>([\w\W]*?)<\/strong[^>]*>/gi, '$1'); + html = html.replace(/]*>([\w\W]*?)<\/em[^>]*>/gi, '$1'); + html = html.replace(/]*>([\w\W]*?)<\/del[^>]*>/gi, '$1'); + + return html; + }, + + // REVERT FORMATER + reformater:function (html) { + html = html.replace(/
/gi, '
'); + + html = html.replace(/]*>([\w\W]*?)<\/b[^>]*>/gi, '$1'); + html = html.replace(/]*>([\w\W]*?)<\/i[^>]*>/gi, '$1'); + html = html.replace(/]*>([\w\W]*?)<\/strike[^>]*>/gi, '$1'); + html = html.replace(/([\w\W]*?)<\/span>/gi, "$2"); + html = html.replace(/([\w\W]*?)<\/span>/gi, "$2"); + html = html.replace(/([\w\W]*?)<\/span>/gi, "$2"); + html = html.replace(/([\w\W]*?)<\/span>/gi, "$2"); + + return html; + }, + + // REMOVE CLASSES AND STYLES + cleanUpClasses:function (html) { + html = html.replace(/\s*class="TOC(.*?)"/gi, ""); + html = html.replace(/\s*class="Heading(.*?)"/gi, ""); + html = html.replace(/\s*class="Body(.*?)"/gi, ""); + + return html; + }, + cleanUpStyles:function (html) { + + html = html.replace(/\s*mso-[^:]+:[^;"]+;?/gi, ""); + html = html.replace(/\s*margin(.*?)pt\s*;/gi, ""); + html = html.replace(/\s*margin(.*?)cm\s*;/gi, ""); + html = html.replace(/\s*text-indent:(.*?)\s*;/gi, ""); + html = html.replace(/\s*line-height:(.*?)\s*;/gi, ""); + html = html.replace(/\s*page-break-before: [^\s;]+;?"/gi, "\""); + html = html.replace(/\s*font-variant: [^\s;]+;?"/gi, "\""); + html = html.replace(/\s*tab-stops:[^;"]*;?/gi, ""); + html = html.replace(/\s*tab-stops:[^"]*/gi, ""); + html = html.replace(/\s*face="[^"]*"/gi, ""); + html = html.replace(/\s*face=[^ >]*/gi, ""); + html = html.replace(/\s*font:(.*?);/gi, ""); + html = html.replace(/\s*font-size:(.*?);/gi, ""); + html = html.replace(/\s*font-weight:(.*?);/gi, ""); + html = html.replace(/\s*font-family:[^;"]*;?/gi, ""); + html = html.replace(/\s\n<\/span>/gi, ''); + + return html; + + }, + cleanUp:function (html) { + // clean comments + html = html.replace(/(<\!\-\-([\w\W]*?)\-\->)/ig, ""); + + if (this.opts.convertDivs) { + html = html.replace(/([\w\W]*?)<\/div>/gi, '$2

'); + } + + // clean dirty + html = html.replace(/ lang="([\w\W]*?)"/gi, ''); + html = html.replace(/([\w\W]*?)<\/a>/gi, ''); + html = html.replace(/\ \ \ /gi, ' '); + html = html.replace(/\ \ /gi, ' '); + html = html.replace(/(.*?)<\/o:p>/gi, ''); + + + // empty style + html = html.replace(/\s*style="\s*"/gi, ''); + + // spans + html = html.replace(/ <\/span>/gi, ''); + html = html.replace(/([\w\W]*?)<\/span>/gi, '$1'); + + return html; + }, + removeTags:function (html) { + return html.replace(/<(?!\s*\/?(code|span|div|label|a|br|p|b|i|del|strike|img|video|audio|iframe|object|embed|param|blockquote|mark|cite|small|ul|ol|li|hr|dl|dt|dd|sup|sub|big|pre|code|figure|figcaption|strong|em|table|tr|td|th|tbody|thead|tfoot|h1|h2|h3|h4|h5|h6)\b)[^>]+>/gi, ""); + }, + + // PASTE CLEANUP + pasteCleanUp:function (marker) { + var html = this.$editor.html(); + + //console.log(html); + + html = this.formating(html); + html = this.cleanUp(html); + + if (this.opts.removeClasses) html = html.replace(/ class="([\w\W]*?)"/gi, ''); + else html = this.cleanUpClasses(html); + + if (this.opts.removeStyles) html = html.replace(/ style="([\w\W]*?)"/gi, ''); + else html = this.cleanUpStyles(html); + + html = this.cleanUp(html); + html = this.formating(html); + + html = html.replace(/([\w\W]*?)<\/b>/gi, "$3"); + + this.$editor.html(html); + + var node = $(this.doc.body).find('#pastemarkerend' + marker).get(0); + this.setFocusNode(node); + + if (!$.browser.mozilla) $(this.doc.body).find('span[rel=pastemarkerend]').not('#pastemarkerend' + marker).remove(); + + this.syncCode(); + this.observeImages(); + + }, + + // TEXTAREA CODE FORMATTING + formating:function (html) { + // lowercase + if ($.browser.msie) { + html = html.replace(/<*(\/ *)?(\w+)>/g, function (w) { + return w.toLowerCase(); + }); + html = html.replace(/style="(.*?)"/g, function (w) { + return w.toLowerCase(); + }); + html = html.replace(/ jQuery(.*?)=\"(.*?)\"/gi, ''); + } + + html = html.replace(/([\w\W]*?)<\/font\>/gi, '$3'); + html = html.replace(/([\w\W]*?)<\/font\>/gi, "$2"); + html = html.replace(/([\w\W]*?)<\/span>/gi, '$1'); + + // mini clean + html = html.replace(/ class="Apple-style-span"/gi, ''); + html = html.replace(/ class="Apple-tab-span"/gi, ''); + html = html.replace(/

/g, '

'); + html = html.replace(/<\/p><\/p>/g, '

'); + html = html.replace(//g, '
'); + html = html.replace(/

 /g, '

'); + html = html.replace(/

    /g, '
      '); + html = html.replace(/

        /g, '
          '); + html = html.replace(/<\/ul><\/p>/g, '
    '); + html = html.replace(/<\/ol><\/p>/g, ''); + html = html.replace(/ <\/p>/gi, ''); + + // remove formatting + html = html.replace(/[\t]*/g, ''); + html = html.replace(/\n\s*\n/g, "\n"); + html = html.replace(/^[\s\n]*/, ''); + html = html.replace(/[\s\n]*$/, ''); + + // empty tags + var etags = ["
    ", "
    \\s*
    ", "\\s*", "\\s*", "
      ", "
        ", "
      1. ", "
        ", "", "\\s*", " ", "

        \\s*

        ", "

         

        ", "

        \\s*
        \\s*

        ", "
        \\s*
        ", "
        \\s*
        \\s*
        "]; + for (var i = 0; i < etags.length; ++i) { + var bbb = etags[i]; + html = html.replace(new RegExp(bbb, 'gi'), ""); + } + + + // add formatting before + var lb = '\r\n'; + var btags = ["", "', '', '
      ', '', '', '', '', '', '', '', '
      ', '
      ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']; + for (var i = 0; i < atags.length; ++i) { + var aaa = atags[i]; + html = html.replace(new RegExp(aaa, 'gi'), aaa + lb); + } + + // indenting + html = html.replace(/
    • /g, "\t"); + + return html; + }, + + // TOGGLE + toggle:function () { + var html; + + if (this.opts.visual) { + this.$frame.hide(); + + html = this.$editor.html(); + html = $.trim(this.formating(html)); + + this.$el.val(html).show().focus(); + + this.setBtnActive('html'); + this.opts.visual = false; + } + else { + this.$el.hide(); + + this.$editor.html(this.$el.val()); + + this.$frame.show(); + + if (this.$editor.html() === '') { + if (!$.browser.mozilla) html = this.opts.allEmptyHtml; + else html = this.opts.mozillaEmptyHtml; + + this.setCode(html); + } + + this.focus(); + + this.setBtnInactive('html'); + this.opts.visual = true; + this.observeImages(); + } + }, + + // AUTOSAVE + autoSave:function () { + if (this.opts.autosave === false) return false; + + setInterval($.proxy(function () { + $.post(this.opts.autosave, { data:this.getCode() }); + + }, this), this.opts.interval * 1000); + }, + + // TOOLBAR + buildToolbar:function () { + if (this.opts.toolbar === false) return false; + + this.$toolbar = $('
        ').addClass('redactor_toolbar'); + this.$box.prepend(this.$toolbar); + + $.each(RTOOLBAR[this.opts.toolbar], $.proxy(function (key, s) { + if (this.opts.fileUpload === false && key == 'file') return true; + + var li = $('
      • '); + + if (key == 'fullscreen') $(li).addClass('redactor_toolbar_right'); + + var a = this.buildButton(key, s); + + // dropdown + if (key == 'backcolor' || key == 'fontcolor' || typeof(s.dropdown) != 'undefined') { + var dropdown = $('
      • ')); + + }, this)); + + $(document).click(this.hdlHideDropDown); + $(this.doc).click(this.hdlHideDropDown); + + }, + buildButton:function (key, s) { + var button = $('
         '); + if (typeof(s.func) == 'undefined') button.click($.proxy(function () { + this.execCommand(s.exec, key); + }, this)); + else if (s.func != 'show') button.click($.proxy(function (e) { + this[s.func](e); + }, this)); + + return button; + }, + buildDropdown:function (dropdown, obj) { + $.each(obj, $.proxy( + function (x, d) { + if (typeof(d.style) == 'undefined') d.style = ''; + + var drop_a; + if (d.name == 'separator') drop_a = $(''); + else { + drop_a = $('' + d.title + ''); + + if (typeof(d.func) == 'undefined') $(drop_a).click($.proxy(function () { + this.execCommand(d.exec, x); + }, this)); + else $(drop_a).click($.proxy(function (e) { + this[d.func](e); + }, this)); + } + + $(dropdown).append(drop_a); + + }, this) + ); + + return dropdown; + + }, + buildColorPicker:function (dropdown, key) { + var mode; + if (key == 'backcolor') { + if ($.browser.msie) mode = 'BackColor'; + else mode = 'hilitecolor'; + } + else mode = 'forecolor'; + + $(dropdown).width(210); + + var len = this.opts.colors.length; + for (var i = 0; i < len; ++i) { + var color = this.opts.colors[i]; + + var swatch = $('').css({ 'backgroundColor':color }); + $(dropdown).append(swatch); + + var _self = this; + $(swatch).click(function () { + if ($.browser.mozilla) { + _self.execCommand('useCSS', false, false); + _self.execCommand(mode, $(this).attr('rel')); + _self.execCommand('useCSS', false, true); + } + else { + _self.execCommand(mode, $(this).attr('rel')); + } + }); + } + + var elnone = $('').html(RLANG.none); + + if (key == 'backcolor') elnone.click($.proxy(this.setBackgroundNone, this)); + else elnone.click($.proxy(this.setColorNone, this)); + + $(dropdown).append(elnone); + + return dropdown; + }, + setBackgroundNone:function () { + $(this.getParentNode()).css('background-color', 'transparent'); + this.syncCode(); + }, + setColorNone:function () { + $(this.getParentNode()).attr('color', '').css('color', ''); + this.syncCode(); + }, + + // DROPDOWNS + showDropDown:function (e, dropdown, key) { + this.hideAllDropDown(); + + this.setBtnActive(key); + this.getBtn(key).addClass('dropact'); + + var left = this.getBtn(key).offset().left; + + + if (this.opts.fixed && this.fixed) { + $(dropdown).css({ position:'fixed', left:left + 'px', top:'30px' }).show(); + } + else { + var top = this.$toolbar.offset().top + 30; + $(dropdown).css({ position:'absolute', left:left + 'px', top:top + 'px' }).show(); + } + + }, + hideAllDropDown:function () { + this.$toolbar.find('a.dropact').removeClass('act').removeClass('dropact'); + $('.redactor_dropdown').hide(); + }, + hideDropDown:function (e, dropdown, key) { + if (!$(e.target).parent().hasClass('dropact')) { + $(dropdown).removeClass('act'); + this.showedDropDown = false; + this.hideAllDropDown(); + } + }, + + // SELECTION AND NODE MANIPULATION + getSelection:function () { + if (this.$frame.get(0).contentWindow.getSelection) return this.$frame.get(0).contentWindow.getSelection(); + else if (this.$frame.get(0).contentWindow.document.selection) return this.$frame.get(0).contentWindow.document.selection.createRange(); + }, + getParentNode:function () { + if (window.getSelection) return this.getSelection().getRangeAt(0).startContainer.parentNode; + else if (document.selection) return this.getSelection().parentElement(); + }, + getCurrentNode:function () { + if (window.getSelection) return this.getSelection().getRangeAt(0).startContainer; + else if (document.selection) return this.getSelection(); + }, + setFocusNode:function (node, toStart) { + var range = this.doc.createRange(); + + var selection = this.getSelection(); + toStart = toStart ? 0 : 1; + + if (selection !== null) { + range.selectNodeContents(node); + selection.addRange(range); + selection.collapse(node, toStart); + } + + this.focus(); + }, + insertNodeAtCaret:function (node) { + if (typeof window.getSelection != "undefined") { + var sel = this.getSelection(); + if (sel.rangeCount) { + var range = sel.getRangeAt(0); + range.collapse(false); + range.insertNode(node); + range = range.cloneRange(); + range.selectNodeContents(node); + range.collapse(false); + sel.removeAllRanges(); + sel.addRange(range); + } + } + else if (typeof document.selection != "undefined" && document.selection.type != "Control") { + var html = (node.nodeType == 1) ? node.outerHTML : node.data; + var id = "marker_" + ("" + Math.random()).slice(2); + html += ''; + var textRange = this.getSelection(); + textRange.collapse(false); + textRange.pasteHTML(html); + var markerSpan = document.getElementById(id); + textRange.moveToElementText(markerSpan); + textRange.select(); + markerSpan.parentNode.removeChild(markerSpan); + } + }, + + // BUTTONS MANIPULATIONS + getBtn:function (key) { + return $(this.$toolbar.find('a.redactor_btn_' + key)); + }, + setBtnActive:function (key) { + this.getBtn(key).addClass('act'); + }, + setBtnInactive:function (key) { + this.getBtn(key).removeClass('act'); + }, + changeBtnIcon:function (key, classname) { + this.getBtn(key).addClass('redactor_btn_' + classname); + }, + removeBtnIcon:function (key, classname) { + this.getBtn(key).removeClass('redactor_btn_' + classname); + }, + removeBtn:function (key) { + this.getBtn(key).remove(); + }, + addBtn:function (key, obj) { + this.$toolbar.append($('
      • ').append(this.buildButton(key, obj))); + }, + + // FULLSCREEN + fullscreen:function () { + var html; + + if (this.opts.fullscreen === false) { + this.changeBtnIcon('fullscreen', 'normalscreen'); + this.setBtnActive('fullscreen'); + this.opts.fullscreen = true; + + this.height = this.$frame.css('height'); + this.width = (this.$box.width() - 2) + 'px'; + + html = this.getCode(); + + this.tmpspan = $(''); + this.$box.addClass('redactor_box_fullscreen').after(this.tmpspan); + + $(document.body).prepend(this.$box).css('overflow', 'hidden'); + + this.$editor = this.enable(html); + + $(this.doc).click($.proxy(this.hideAllDropDown, this)); + // focus always on page + $(this.doc).click($.proxy(function (e) { + this.$editor.focus(); + }, this)); + + this.observeImages(); + this.$box.find('.redactor_resizer').hide(); + + this.fullScreenResize(); + $(window).resize($.proxy(this.fullScreenResize, this)); + $(document).scrollTop(0, 0); + this.focus(); + + } + else { + this.removeBtnIcon('fullscreen', 'normalscreen'); + this.setBtnInactive('fullscreen'); + this.opts.fullscreen = false; + + $(window).unbind('resize', $.proxy(this.fullScreenResize, this)); + $(document.body).css('overflow', ''); + + html = this.getCode(); + + this.$box.removeClass('redactor_box_fullscreen').css('width', 'auto'); + + this.tmpspan.after(this.$box).remove(); + + this.$editor = this.enable(html); + + this.observeImages(); + if (this.opts.autoresize) this.observeAutoResize(); + this.$box.find('.redactor_resizer').show(); + + $(this.doc).click($.proxy(this.hideAllDropDown, this)); + // focus always on page + $(this.doc).click($.proxy(function (e) { + this.$editor.focus(); + }, this)); + + this.syncCode(); + + this.$frame.css('height', this.height); + this.$el.css('height', this.height); + this.focus(); + } + }, + fullScreenResize:function () { + if (this.opts.fullscreen === false) return; + + var hfix = 42; + if (this.opts.air) hfix = 2; + + var height = $(window).height() - hfix; + + this.$box.width($(window).width() - 2); + this.$frame.height(height); + this.$el.height(height); + }, + + // RESIZE + buildResizer:function () { + if (this.opts.resize === false) return false; + + this.$resizer = $('
        '); + this.$box.append(this.$resizer); + + this.$resizer.mousedown($.proxy(this.initResize, this)); + + }, + initResize:function (e) { + if (e.preventDefault) e.preventDefault(); + + this.splitter = e.target; + + if (this.opts.visual) { + this.element_resize = this.$frame; + this.element_resize.get(0).style.visibility = 'hidden'; + this.element_resize_parent = this.$el; + } + else { + this.element_resize = this.$el; + this.element_resize_parent = this.$frame; + } + + this.stopResizeHdl = $.proxy(this.stopResize, this); + this.startResizeHdl = $.proxy(this.startResize, this); + this.resizeHdl = $.proxy(this.resize, this); + + $(document).mousedown(this.startResizeHdl); + $(document).mouseup(this.stopResizeHdl); + $(this.splitter).mouseup(this.stopResizeHdl); + + this.null_point = false; + this.h_new = false; + this.h = this.element_resize.height(); + }, + startResize:function () { + $(document).mousemove(this.resizeHdl); + }, + resize:function (e) { + if (e.preventDefault) e.preventDefault(); + + var y = e.pageY; + if (this.null_point === false) this.null_point = y; + if (this.h_new === false) this.h_new = this.element_resize.height(); + + var s_new = (this.h_new + y - this.null_point) - 10; + + if (s_new <= 30) return true; + + if (s_new >= 0) { + this.element_resize.get(0).style.height = s_new + 'px'; + this.element_resize_parent.get(0).style.height = s_new + 'px'; + } + }, + stopResize:function (e) { + $(document).unbind('mousemove', this.resizeHdl); + $(document).unbind('mousedown', this.startResizeHdl); + $(document).unbind('mouseup', this.stopResizeHdl); + $(this.splitter).unbind('mouseup', this.stopResizeHdl); + + this.element_resize.get(0).style.visibility = 'visible'; + }, + + // RESIZE IMAGES + resizeImage:function (resize) { + var clicked = false; + var clicker = false; + var start_x; + var start_y; + var ratio = $(resize).width() / $(resize).height(); + + var y = 1; + var x = 1; + var min_w = 1; + var min_h = 1; + + $(resize).hover(function () { + $(resize).css('cursor', 'nw-resize'); + }, function () { + $(resize).css('cursor', 'default'); + clicked = false; + }); + + $(resize).mousedown(function (e) { + if (e.preventDefault) e.preventDefault(); + + clicked = true; + clicker = true; + + start_x = Math.round(e.pageX - $(resize).eq(0).offset().left); + start_y = Math.round(e.pageY - $(resize).eq(0).offset().top); + }); + + $(resize).mouseup($.proxy(function (e) { + clicked = false; + this.syncCode(); + }, this)); + + $(resize).click($.proxy(function (e) { + if (clicker) this.imageEdit(e); + + }, this)); + + $(resize).mousemove(function (e) { + if (clicked) { + clicker = false; + + var mouse_x = Math.round(e.pageX - $(this).eq(0).offset().left) - start_x; + var mouse_y = Math.round(e.pageY - $(this).eq(0).offset().top) - start_y; + + var div_h = $(resize).height(); + + var new_h = parseInt(div_h) + mouse_y; + var new_w = new_h * ratio; + + + if (x == 1 || (typeof(x) == "number" && new_w < x && new_w > min_w)) { + $(resize).width(new_w); + } + if (y == 1 || (typeof(y) == "number" && new_h < y && new_h > min_h)) { + $(resize).height(new_h); + } + start_x = Math.round(e.pageX - $(this).eq(0).offset().left); + start_y = Math.round(e.pageY - $(this).eq(0).offset().top); + } + }); + }, + + // TABLE + showTable:function () { + this.modalInit(RLANG.table, 'table', 300, $.proxy(function () { + $('#redactor_table_rows').focus(); + $('#redactor_insert_table_btn').click($.proxy(this.insertTable, this)); + + }, this)); + }, + insertTable:function () { + var rows = $('#redactor_table_rows').val(); + var columns = $('#redactor_table_columns').val(); + + var table_box = $('
        '); + + var tableid = Math.floor(Math.random() * 99999); + var table = $('
        '); + + for (var i = 0; i < rows; i++) { + var row = $(''); + for (var z = 0; z < columns; z++) { + var column = $(' '); + $(row).append(column); + } + $(table).append(row); + } + + $(table_box).append(table); + var html = $(table_box).html(); + + if ($.browser.msie) html += '

        '; + else html += '

         

        '; + + this.execCommand('inserthtml', html); + this.modalClose(); + + this.$table = $(this.doc).find('body').find('#table' + tableid); + this.$table.click($.proxy(this.tableObserver, this)); + }, + tableObserver:function (e) { + this.$table = $(e.target).parents('table'); + + this.$table_tr = this.$table.find('tr'); + this.$table_td = this.$table.find('td'); + + this.$table_td.removeClass('current'); + + this.$tbody = $(e.target).parents('tbody'); + this.$thead = $(this.$table).find('thead'); + + this.$current_td = $(e.target); + this.$current_td.addClass('current'); + + this.$current_tr = $(e.target).parents('tr'); + }, + deleteTable:function () { + $(this.$table).remove(); + this.$table = false; + this.syncCode(); + }, + deleteRow:function () { + $(this.$current_tr).remove(); + this.syncCode(); + }, + deleteColumn:function () { + var index = $(this.$current_td).get(0).cellIndex; + + $(this.$table).find('tr').each(function () { + $(this).find('td').eq(index).remove(); + }); + + this.syncCode(); + }, + addHead:function () { + if ($(this.$table).find('thead').size() !== 0) this.deleteHead(); + else { + var tr = $(this.$table).find('tr').first().clone(); + tr.find('td').html(' '); + this.$thead = $(''); + this.$thead.append(tr); + $(this.$table).prepend(this.$thead); + this.syncCode(); + } + }, + deleteHead:function () { + $(this.$thead).remove(); + this.$thead = false; + this.syncCode(); + }, + insertRowAbove:function () { + this.insertRow('before'); + }, + insertRowBelow:function () { + this.insertRow('after'); + }, + insertColumnLeft:function () { + this.insertColumn('before'); + }, + insertColumnRight:function () { + this.insertColumn('after'); + }, + insertRow:function (type) { + var new_tr = $(this.$current_tr).clone(); + new_tr.find('td').html(' '); + if (type == 'after') $(this.$current_tr).after(new_tr); + else $(this.$current_tr).before(new_tr); + + this.syncCode(); + }, + insertColumn:function (type) { + var index = 0; + + this.$current_td.addClass('current'); + + this.$current_tr.find('td').each(function (i, s) { + if ($(s).hasClass('current')) index = i; + }); + + this.$table_tr.each(function (i, s) { + var current = $(s).find('td').eq(index); + + var td = current.clone(); + td.html(' '); + + if (type == 'after') $(current).after(td); + else $(current).before(td); + + }); + + this.syncCode(); + }, + + // INSERT VIDEO + showVideo:function () { + if ($.browser.msie) this.markerIE(); + + this.modalInit(RLANG.video, 'video', 600, $.proxy(function () { + $('#redactor_insert_video_area').focus(); + $('#redactor_insert_video_btn').click($.proxy(this.insertVideo, this)); + + }, this)); + }, + insertVideo:function () { + var data = $('#redactor_insert_video_area').val(); + data = this.removeTags(data); + + if ($.browser.msie) { + $(this.doc.getElementById('span' + this.spanid)).after(data).remove(); + this.syncCode(); + } + else this.execCommand('inserthtml', data); + + this.modalClose(); + }, + + // INSERT IMAGE + imageEdit:function (e) { + var $el = $(e.target); + var parent = $el.parent(); + + var handler = $.proxy(function () { + $('#redactor_file_alt').val($el.attr('alt')); + $('#redactor_image_edit_src').attr('href', $el.attr('src')); + $('#redactor_form_image_align').val($el.css('float')); + + if ($(parent).get(0).tagName == 'A') $('#redactor_file_link').val($(parent).attr('href')); + + $('#redactor_image_delete_btn').click($.proxy(function () { + this.imageDelete($el); + }, this)); + $('#redactorSaveBtn').click($.proxy(function () { + this.imageSave($el); + }, this)); + + }, this); + + this.modalInit(RLANG.image, 'image_edit', 380, handler); + + }, + imageDelete:function (el) { + $(el).remove(); + this.modalClose(); + this.syncCode(); + }, + imageSave:function (el) { + var parent = $(el).parent(); + + $(el).attr('alt', $('#redactor_file_alt').val()); + + var floating = $('#redactor_form_image_align').val(); + + if (floating == 'left') $(el).css({ 'float':'left', margin:'0 10px 10px 0' }); + else if (floating == 'right') $(el).css({ 'float':'right', margin:'0 0 10px 10px' }); + else $(el).css({ 'float':'none', margin:'0' }); + + // as link + var link = $.trim($('#redactor_file_link').val()); + if (link !== '') { + if ($(parent).get(0).tagName != 'A') { + $(el).replaceWith('' + this.outerHTML(el) + ''); + } + else { + $(parent).attr('href', link); + } + } + + this.modalClose(); + this.observeImages(); + this.syncCode(); + + }, + showImage:function () { + if ($.browser.msie) this.markerIE(); + + var handler = $.proxy(function () { + // json + if (this.opts.imageGetJson !== false) { + $.getJSON(this.opts.imageGetJson, $.proxy(function (data) { + + $.each(data, $.proxy(function (key, val) { + var img = $(''); + $('#redactor_image_box').append(img); + $(img).click($.proxy(this.imageSetThumb, this)); + + }, this)); + + }, this)); + } + else { + $('#redactor_tabs a').eq(1).remove(); + } + + if (this.opts.imageUpload !== false) { + // dragupload + if ($('#redactor_file').size() !== 0) { + $('#redactor_file').dragupload( + { + url:this.opts.imageUpload, + success:$.proxy(this.imageUploadCallback, this) + }); + } + + // ajax upload + this.uploadInit('redactor_file', { auto:true, url:this.opts.imageUpload, success:$.proxy(this.imageUploadCallback, this) }); + } + else { + $('.redactor_tab').hide(); + if (this.opts.imageGetJson === false) { + $('#redactor_tabs').remove(); + $('#redactor_tab3').show(); + } + else { + var tabs = $('#redactor_tabs a'); + tabs.eq(0).remove(); + tabs.eq(1).addClass('redactor_tabs_act'); + $('#redactor_tab2').show(); + } + } + + $('#redactor_upload_btn').click($.proxy(this.imageUploadCallbackLink, this)); + + }, this); + + this.modalInit(RLANG.image, 'image', 570, handler, true); + + }, + imageSetThumb:function (e) { + this._imageSet('', true); + }, + imageUploadCallbackLink:function () { + if ($('#redactor_file_link').val() !== '') { + var data = ''; + this._imageSet(data, true); + } + else this.modalClose(); + }, + imageUploadCallback:function (data) { + this._imageSet(data); + }, + _imageSet:function (json, link) { + if (link !== true) { + var data = $.parseJSON(json); + var html = '

        '; + } + else var html = json; + + this.focus(); + + if ($.browser.msie) { + $(this.doc.getElementById('span' + this.spanid)).after(html).remove(); + this.syncCode(); + } + else { + this.execCommand('inserthtml', html); + } + + // upload image callback + if (link !== true && typeof this.opts.imageUploadCallback == 'function') { + this.opts.imageUploadCallback(this, data); + } + + this.modalClose(); + this.observeImages(); + }, + + // INSERT LINK + showLink:function () { + var handler = $.proxy(function () { + var sel = this.getSelection(); + + if ($.browser.msie) { + var parent = this.getParentNode(); + if (parent.nodeName == 'A') { + this.insert_link_node = $(parent); + var text = this.insert_link_node.text(); + var url = this.insert_link_node.attr('href'); + } + else { + if (this.oldIE()) var text = sel.text; + else var text = sel.toString(); + + var url = ''; + + this.spanid = Math.floor(Math.random() * 99999); + + var html = '' + text + ''; + if (text != '') html = '' + text + ''; + this.execCommand('inserthtml', html); + } + } + else { + if (sel && sel.anchorNode && sel.anchorNode.parentNode.tagName == 'A') { + var url = sel.anchorNode.parentNode.href; + var text = sel.anchorNode.parentNode.text; + if (sel.toString() === '') this.insert_link_node = sel.anchorNode.parentNode; + } + else { + var text = sel.toString(); + var url = ''; + } + } + + $('.redactor_link_text').val(text); + $('#redactor_link_url').val(url).focus(); + + $('#redactor_insert_link_btn').click($.proxy(this.insertLink, this)); + + + }, this); + + this.modalInit(RLANG.link, 'link', 460, handler); + + }, + insertLink:function () { + var tab_selected = $('#redactor_tab_selected').val(); + + var link = '', text = ''; + + if (tab_selected == 1) // url + { + link = $('#redactor_link_url').val(); + text = $('#redactor_link_url_text').val(); + } + else if (tab_selected == 2) // mailto + { + link = 'mailto:' + $('#redactor_link_mailto').val(); + text = $('#redactor_link_mailto_text').val(); + } + else if (tab_selected == 3) // anchor + { + link = '#' + $('#redactor_link_anchor').val(); + text = $('#redactor_link_anchor_text').val(); + } + + this._insertLink('' + text + ' ', $.trim(text), link); + + }, + _insertLink:function (a, text, link) { + if (text != '') { + if (this.insert_link_node) { + $(this.insert_link_node).text(text); + $(this.insert_link_node).attr('href', link); + this.syncCode(); + } + else { + if ($.browser.msie) { + $(this.doc.getElementById('span' + this.spanid)).replaceWith(a); + this.syncCode(); + } + else this.execCommand('inserthtml', a); + } + } + + this.modalClose(); + }, + + // INSERT FILE + showFile:function () { + if ($.browser.msie) this.markerIE(); + + var handler = $.proxy(function () { + var sel = this.getSelection(); + + var text = ''; + if (this.oldIE()) text = sel.text; + else text = sel.toString(); + + $('#redactor_filename').val(text); + + $('#redactor_file').dragupload( + { + url:this.opts.fileUpload, + success:$.proxy(function (data) { + this.fileUploadCallback(data); + }, this) + }); + + this.uploadInit('redactor_file', { auto:true, url:this.opts.fileUpload, success:$.proxy(function (data) { + + this.fileUploadCallback(data); + + }, this)}); + }, this); + + this.modalInit(RLANG.file, 'file', 500, handler); + }, + fileUploadCallback:function (json) { + var data = $.parseJSON(json); + + var text = $('#redactor_filename').val(); + if (text == '') text = data.filename; + var link = '' + text + ''; + + // chrome fix + if ($.browser.webkit && !!window.chrome) link = link + ' '; + + if ($.browser.msie) { + if (text != '') $(this.doc.getElementById('span' + this.spanid)).replaceWith(a); + else $(this.doc.getElementById('span' + this.spanid)).after(link).remove(); + this.syncCode(); + } + else this.execCommand('inserthtml', link); + + // file upload callback + if (typeof this.opts.fileUploadCallback == 'function') { + this.opts.fileUploadCallback(this, data); + } + + this.modalClose(); + }, + + + // MODAL + setupModalWindows:function () { + + this.opts.modal = { + 'file':'
        ' + + '' + + '
        ', + + 'image_edit':'' + + '' + + '' + + '', + 'image':'' + + '
        ' + + '
        ' + + ' ' + + '
        ' + + '", "
      ", "", "", "", "", "", "", "", "
      ", "
      ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]; + for (var g = 0; g < l.length; ++g) { + var d = l[g]; + k = k.replace(new RegExp(d, "gi"), d + e) + } + k = k.replace(/
    • /g, "\t"); + return k + }, toggle:function () { + var d; + if (this.opts.visual) { + this.$frame.hide(); + d = this.$editor.html(); + d = c.trim(this.formating(d)); + this.$el.val(d).show().focus(); + this.setBtnActive("html"); + this.opts.visual = false + } else { + this.$el.hide(); + this.$editor.html(this.$el.val()); + this.$frame.show(); + if (this.$editor.html() === "") { + if (!c.browser.mozilla) { + d = this.opts.allEmptyHtml + } else { + d = this.opts.mozillaEmptyHtml + } + this.setCode(d) + } + this.focus(); + this.setBtnInactive("html"); + this.opts.visual = true; + this.observeImages() + } + }, autoSave:function () { + if (this.opts.autosave === false) { + return false + } + setInterval(c.proxy(function () { + c.post(this.opts.autosave, {data:this.getCode()}) + }, this), this.opts.interval * 1000) + }, buildToolbar:function () { + if (this.opts.toolbar === false) { + return false + } + this.$toolbar = c("
        ").addClass("redactor_toolbar"); + this.$box.prepend(this.$toolbar); + c.each(RTOOLBAR[this.opts.toolbar], c.proxy(function (f, g) { + if (this.opts.fileUpload === false && f == "file") { + return true + } + var d = c("
      • "); + if (f == "fullscreen") { + c(d).addClass("redactor_toolbar_right") + } + var e = this.buildButton(f, g); + if (f == "backcolor" || f == "fontcolor" || typeof(g.dropdown) != "undefined") { + var h = c('
      • ')) + } + }, this)); + c(document).click(this.hdlHideDropDown); + c(this.doc).click(this.hdlHideDropDown) + }, buildButton:function (e, f) { + var d = c('
         '); + if (typeof(f.func) == "undefined") { + d.click(c.proxy(function () { + this.execCommand(f.exec, e) + }, this)) + } else { + if (f.func != "show") { + d.click(c.proxy(function (g) { + this[f.func](g) + }, this)) + } + } + return d + }, buildDropdown:function (e, d) { + c.each(d, c.proxy(function (f, h) { + if (typeof(h.style) == "undefined") { + h.style = "" + } + var g; + if (h.name == "separator") { + g = c('') + } else { + g = c('' + h.title + ""); + if (typeof(h.func) == "undefined") { + c(g).click(c.proxy(function () { + this.execCommand(h.exec, f) + }, this)) + } else { + c(g).click(c.proxy(function (i) { + this[h.func](i) + }, this)) + } + } + c(e).append(g) + }, this)); + return e + }, buildColorPicker:function (m, l) { + var g; + if (l == "backcolor") { + if (c.browser.msie) { + g = "BackColor" + } else { + g = "hilitecolor" + } + } else { + g = "forecolor" + } + c(m).width(210); + var h = this.opts.colors.length; + for (var f = 0; f < h; ++f) { + var d = this.opts.colors[f]; + var k = c('').css({backgroundColor:d}); + c(m).append(k); + var j = this; + c(k).click(function () { + if (c.browser.mozilla) { + j.execCommand("useCSS", false, false); + j.execCommand(g, c(this).attr("rel")); + j.execCommand("useCSS", false, true) + } else { + j.execCommand(g, c(this).attr("rel")) + } + }) + } + var e = c('').html(RLANG.none); + if (l == "backcolor") { + e.click(c.proxy(this.setBackgroundNone, this)) + } else { + e.click(c.proxy(this.setColorNone, this)) + } + c(m).append(e); + return m + }, setBackgroundNone:function () { + c(this.getParentNode()).css("background-color", "transparent"); + this.syncCode() + }, setColorNone:function () { + c(this.getParentNode()).attr("color", "").css("color", ""); + this.syncCode() + }, showDropDown:function (h, i, d) { + this.hideAllDropDown(); + this.setBtnActive(d); + this.getBtn(d).addClass("dropact"); + var g = this.getBtn(d).offset().left; + if (this.opts.fixed && this.fixed) { + c(i).css({position:"fixed", left:g + "px", top:"30px"}).show() + } else { + var f = this.$toolbar.offset().top + 30; + c(i).css({position:"absolute", left:g + "px", top:f + "px"}).show() + } + }, hideAllDropDown:function () { + this.$toolbar.find("a.dropact").removeClass("act").removeClass("dropact"); + c(".redactor_dropdown").hide() + }, hideDropDown:function (f, g, d) { + if (!c(f.target).parent().hasClass("dropact")) { + c(g).removeClass("act"); + this.showedDropDown = false; + this.hideAllDropDown() + } + }, getSelection:function () { + if (this.$frame.get(0).contentWindow.getSelection) { + return this.$frame.get(0).contentWindow.getSelection() + } else { + if (this.$frame.get(0).contentWindow.document.selection) { + return this.$frame.get(0).contentWindow.document.selection.createRange() + } + } + }, getParentNode:function () { + if (window.getSelection) { + return this.getSelection().getRangeAt(0).startContainer.parentNode + } else { + if (document.selection) { + return this.getSelection().parentElement() + } + } + }, getCurrentNode:function () { + if (window.getSelection) { + return this.getSelection().getRangeAt(0).startContainer + } else { + if (document.selection) { + return this.getSelection() + } + } + }, setFocusNode:function (g, e) { + var d = this.doc.createRange(); + var f = this.getSelection(); + e = e ? 0 : 1; + if (f !== null) { + d.selectNodeContents(g); + f.addRange(d); + f.collapse(g, e) + } + this.focus() + }, insertNodeAtCaret:function (h) { + if (typeof window.getSelection != "undefined") { + var i = this.getSelection(); + if (i.rangeCount) { + var e = i.getRangeAt(0); + e.collapse(false); + e.insertNode(h); + e = e.cloneRange(); + e.selectNodeContents(h); + e.collapse(false); + i.removeAllRanges(); + i.addRange(e) + } + } else { + if (typeof document.selection != "undefined" && document.selection.type != "Control") { + var f = (h.nodeType == 1) ? h.outerHTML : h.data; + var j = "marker_" + ("" + Math.random()).slice(2); + f += ''; + var g = this.getSelection(); + g.collapse(false); + g.pasteHTML(f); + var d = document.getElementById(j); + g.moveToElementText(d); + g.select(); + d.parentNode.removeChild(d) + } + } + }, getBtn:function (d) { + return c(this.$toolbar.find("a.redactor_btn_" + d)) + }, setBtnActive:function (d) { + this.getBtn(d).addClass("act") + }, setBtnInactive:function (d) { + this.getBtn(d).removeClass("act") + }, changeBtnIcon:function (d, e) { + this.getBtn(d).addClass("redactor_btn_" + e) + }, removeBtnIcon:function (d, e) { + this.getBtn(d).removeClass("redactor_btn_" + e) + }, removeBtn:function (d) { + this.getBtn(d).remove() + }, addBtn:function (d, e) { + this.$toolbar.append(c("
      • ").append(this.buildButton(d, e))) + }, fullscreen:function () { + var d; + if (this.opts.fullscreen === false) { + this.changeBtnIcon("fullscreen", "normalscreen"); + this.setBtnActive("fullscreen"); + this.opts.fullscreen = true; + this.height = this.$frame.css("height"); + this.width = (this.$box.width() - 2) + "px"; + d = this.getCode(); + this.tmpspan = c(""); + this.$box.addClass("redactor_box_fullscreen").after(this.tmpspan); + c(document.body).prepend(this.$box).css("overflow", "hidden"); + this.$editor = this.enable(d); + c(this.doc).click(c.proxy(this.hideAllDropDown, this)); + c(this.doc).click(c.proxy(function (f) { + this.$editor.focus() + }, this)); + this.observeImages(); + this.$box.find(".redactor_resizer").hide(); + this.fullScreenResize(); + c(window).resize(c.proxy(this.fullScreenResize, this)); + c(document).scrollTop(0, 0); + this.focus() + } else { + this.removeBtnIcon("fullscreen", "normalscreen"); + this.setBtnInactive("fullscreen"); + this.opts.fullscreen = false; + c(window).unbind("resize", c.proxy(this.fullScreenResize, this)); + c(document.body).css("overflow", ""); + d = this.getCode(); + this.$box.removeClass("redactor_box_fullscreen").css("width", "auto"); + this.tmpspan.after(this.$box).remove(); + this.$editor = this.enable(d); + this.observeImages(); + if (this.opts.autoresize) { + this.observeAutoResize() + } + this.$box.find(".redactor_resizer").show(); + c(this.doc).click(c.proxy(this.hideAllDropDown, this)); + c(this.doc).click(c.proxy(function (f) { + this.$editor.focus() + }, this)); + this.syncCode(); + this.$frame.css("height", this.height); + this.$el.css("height", this.height); + this.focus() + } + }, fullScreenResize:function () { + if (this.opts.fullscreen === false) { + return + } + var e = 42; + if (this.opts.air) { + e = 2 + } + var d = c(window).height() - e; + this.$box.width(c(window).width() - 2); + this.$frame.height(d); + this.$el.height(d) + }, buildResizer:function () { + if (this.opts.resize === false) { + return false + } + this.$resizer = c('
        '); + this.$box.append(this.$resizer); + this.$resizer.mousedown(c.proxy(this.initResize, this)) + }, initResize:function (d) { + if (d.preventDefault) { + d.preventDefault() + } + this.splitter = d.target; + if (this.opts.visual) { + this.element_resize = this.$frame; + this.element_resize.get(0).style.visibility = "hidden"; + this.element_resize_parent = this.$el + } else { + this.element_resize = this.$el; + this.element_resize_parent = this.$frame + } + this.stopResizeHdl = c.proxy(this.stopResize, this); + this.startResizeHdl = c.proxy(this.startResize, this); + this.resizeHdl = c.proxy(this.resize, this); + c(document).mousedown(this.startResizeHdl); + c(document).mouseup(this.stopResizeHdl); + c(this.splitter).mouseup(this.stopResizeHdl); + this.null_point = false; + this.h_new = false; + this.h = this.element_resize.height() + }, startResize:function () { + c(document).mousemove(this.resizeHdl) + }, resize:function (f) { + if (f.preventDefault) { + f.preventDefault() + } + var g = f.pageY; + if (this.null_point === false) { + this.null_point = g + } + if (this.h_new === false) { + this.h_new = this.element_resize.height() + } + var d = (this.h_new + g - this.null_point) - 10; + if (d <= 30) { + return true + } + if (d >= 0) { + this.element_resize.get(0).style.height = d + "px"; + this.element_resize_parent.get(0).style.height = d + "px" + } + }, stopResize:function (d) { + c(document).unbind("mousemove", this.resizeHdl); + c(document).unbind("mousedown", this.startResizeHdl); + c(document).unbind("mouseup", this.stopResizeHdl); + c(this.splitter).unbind("mouseup", this.stopResizeHdl); + this.element_resize.get(0).style.visibility = "visible" + }, resizeImage:function (e) { + var h = false; + var d = false; + var m; + var l; + var g = c(e).width() / c(e).height(); + var i = 1; + var j = 1; + var k = 1; + var f = 1; + c(e).hover(function () { + c(e).css("cursor", "nw-resize") + }, function () { + c(e).css("cursor", "default"); + h = false + }); + c(e).mousedown(function (n) { + if (n.preventDefault) { + n.preventDefault() + } + h = true; + d = true; + m = Math.round(n.pageX - c(e).eq(0).offset().left); + l = Math.round(n.pageY - c(e).eq(0).offset().top) + }); + c(e).mouseup(c.proxy(function (n) { + h = false; + this.syncCode() + }, this)); + c(e).click(c.proxy(function (n) { + if (d) { + this.imageEdit(n) + } + }, this)); + c(e).mousemove(function (r) { + if (h) { + d = false; + var o = Math.round(r.pageX - c(this).eq(0).offset().left) - m; + var n = Math.round(r.pageY - c(this).eq(0).offset().top) - l; + var q = c(e).height(); + var s = parseInt(q) + n; + var p = s * g; + if (j == 1 || (typeof(j) == "number" && p < j && p > k)) { + c(e).width(p) + } + if (i == 1 || (typeof(i) == "number" && s < i && s > f)) { + c(e).height(s) + } + m = Math.round(r.pageX - c(this).eq(0).offset().left); + l = Math.round(r.pageY - c(this).eq(0).offset().top) + } + }) + }, showTable:function () { + this.modalInit(RLANG.table, "table", 300, c.proxy(function () { + c("#redactor_table_rows").focus(); + c("#redactor_insert_table_btn").click(c.proxy(this.insertTable, this)) + }, this)) + }, insertTable:function () { + var n = c("#redactor_table_rows").val(); + var g = c("#redactor_table_columns").val(); + var d = c("
        "); + var e = Math.floor(Math.random() * 99999); + var l = c('
        '); + for (var h = 0; h < n; h++) { + var m = c(""); + for (var k = 0; k < g; k++) { + var f = c(" "); + c(m).append(f) + } + c(l).append(m) + } + c(d).append(l); + var j = c(d).html(); + if (c.browser.msie) { + j += "

        " + } else { + j += "

         

        " + } + this.execCommand("inserthtml", j); + this.modalClose(); + this.$table = c(this.doc).find("body").find("#table" + e); + this.$table.click(c.proxy(this.tableObserver, this)) + }, tableObserver:function (d) { + this.$table = c(d.target).parents("table"); + this.$table_tr = this.$table.find("tr"); + this.$table_td = this.$table.find("td"); + this.$table_td.removeClass("current"); + this.$tbody = c(d.target).parents("tbody"); + this.$thead = c(this.$table).find("thead"); + this.$current_td = c(d.target); + this.$current_td.addClass("current"); + this.$current_tr = c(d.target).parents("tr") + }, deleteTable:function () { + c(this.$table).remove(); + this.$table = false; + this.syncCode() + }, deleteRow:function () { + c(this.$current_tr).remove(); + this.syncCode() + }, deleteColumn:function () { + var d = c(this.$current_td).get(0).cellIndex; + c(this.$table).find("tr").each(function () { + c(this).find("td").eq(d).remove() + }); + this.syncCode() + }, addHead:function () { + if (c(this.$table).find("thead").size() !== 0) { + this.deleteHead() + } else { + var d = c(this.$table).find("tr").first().clone(); + d.find("td").html(" "); + this.$thead = c(""); + this.$thead.append(d); + c(this.$table).prepend(this.$thead); + this.syncCode() + } + }, deleteHead:function () { + c(this.$thead).remove(); + this.$thead = false; + this.syncCode() + }, insertRowAbove:function () { + this.insertRow("before") + }, insertRowBelow:function () { + this.insertRow("after") + }, insertColumnLeft:function () { + this.insertColumn("before") + }, insertColumnRight:function () { + this.insertColumn("after") + }, insertRow:function (d) { + var e = c(this.$current_tr).clone(); + e.find("td").html(" "); + if (d == "after") { + c(this.$current_tr).after(e) + } else { + c(this.$current_tr).before(e) + } + this.syncCode() + }, insertColumn:function (e) { + var d = 0; + this.$current_td.addClass("current"); + this.$current_tr.find("td").each(function (f, g) { + if (c(g).hasClass("current")) { + d = f + } + }); + this.$table_tr.each(function (f, g) { + var h = c(g).find("td").eq(d); + var j = h.clone(); + j.html(" "); + if (e == "after") { + c(h).after(j) + } else { + c(h).before(j) + } + }); + this.syncCode() + }, showVideo:function () { + if (c.browser.msie) { + this.markerIE() + } + this.modalInit(RLANG.video, "video", 600, c.proxy(function () { + c("#redactor_insert_video_area").focus(); + c("#redactor_insert_video_btn").click(c.proxy(this.insertVideo, this)) + }, this)) + }, insertVideo:function () { + var d = c("#redactor_insert_video_area").val(); + d = this.removeTags(d); + if (c.browser.msie) { + c(this.doc.getElementById("span" + this.spanid)).after(d).remove(); + this.syncCode() + } else { + this.execCommand("inserthtml", d) + } + this.modalClose() + }, imageEdit:function (h) { + var d = c(h.target); + var g = d.parent(); + var f = c.proxy(function () { + c("#redactor_file_alt").val(d.attr("alt")); + c("#redactor_image_edit_src").attr("href", d.attr("src")); + c("#redactor_form_image_align").val(d.css("float")); + if (c(g).get(0).tagName == "A") { + c("#redactor_file_link").val(c(g).attr("href")) + } + c("#redactor_image_delete_btn").click(c.proxy(function () { + this.imageDelete(d) + }, this)); + c("#redactorSaveBtn").click(c.proxy(function () { + this.imageSave(d) + }, this)) + }, this); + this.modalInit(RLANG.image, "image_edit", 380, f) + }, imageDelete:function (d) { + c(d).remove(); + this.modalClose(); + this.syncCode() + }, imageSave:function (e) { + var d = c(e).parent(); + c(e).attr("alt", c("#redactor_file_alt").val()); + var g = c("#redactor_form_image_align").val(); + if (g == "left") { + c(e).css({"float":"left", margin:"0 10px 10px 0"}) + } else { + if (g == "right") { + c(e).css({"float":"right", margin:"0 0 10px 10px"}) + } else { + c(e).css({"float":"none", margin:"0"}) + } + } + var f = c.trim(c("#redactor_file_link").val()); + if (f !== "") { + if (c(d).get(0).tagName != "A") { + c(e).replaceWith('' + this.outerHTML(e) + "") + } else { + c(d).attr("href", f) + } + } + this.modalClose(); + this.observeImages(); + this.syncCode() + }, showImage:function () { + if (c.browser.msie) { + this.markerIE() + } + var d = c.proxy(function () { + if (this.opts.imageGetJson !== false) { + c.getJSON(this.opts.imageGetJson, c.proxy(function (f) { + c.each(f, c.proxy(function (h, i) { + var g = c(''); + c("#redactor_image_box").append(g); + c(g).click(c.proxy(this.imageSetThumb, this)) + }, this)) + }, this)) + } else { + c("#redactor_tabs a").eq(1).remove() + } + if (this.opts.imageUpload !== false) { + if (c("#redactor_file").size() !== 0) { + c("#redactor_file").dragupload({url:this.opts.imageUpload, success:c.proxy(this.imageUploadCallback, this)}) + } + this.uploadInit("redactor_file", {auto:true, url:this.opts.imageUpload, success:c.proxy(this.imageUploadCallback, this)}) + } else { + c(".redactor_tab").hide(); + if (this.opts.imageGetJson === false) { + c("#redactor_tabs").remove(); + c("#redactor_tab3").show() + } else { + var e = c("#redactor_tabs a"); + e.eq(0).remove(); + e.eq(1).addClass("redactor_tabs_act"); + c("#redactor_tab2").show() + } + } + c("#redactor_upload_btn").click(c.proxy(this.imageUploadCallbackLink, this)) + }, this); + this.modalInit(RLANG.image, "image", 570, d, true) + }, imageSetThumb:function (d) { + this._imageSet('', true) + }, imageUploadCallbackLink:function () { + if (c("#redactor_file_link").val() !== "") { + var d = ''; + this._imageSet(d, true) + } else { + this.modalClose() + } + }, imageUploadCallback:function (d) { + this._imageSet(d) + }, _imageSet:function (e, f) { + if (f !== true) { + var g = c.parseJSON(e); + var d = '

        ' + } else { + var d = e + } + this.focus(); + if (c.browser.msie) { + c(this.doc.getElementById("span" + this.spanid)).after(d).remove(); + this.syncCode() + } else { + this.execCommand("inserthtml", d) + } + if (f !== true && typeof this.opts.imageUploadCallback == "function") { + this.opts.imageUploadCallback(this, g) + } + this.modalClose(); + this.observeImages() + }, showLink:function () { + var d = c.proxy(function () { + var h = this.getSelection(); + if (c.browser.msie) { + var g = this.getParentNode(); + if (g.nodeName == "A") { + this.insert_link_node = c(g); + var i = this.insert_link_node.text(); + var e = this.insert_link_node.attr("href") + } else { + if (this.oldIE()) { + var i = h.text + } else { + var i = h.toString() + } + var e = ""; + this.spanid = Math.floor(Math.random() * 99999); + var f = '' + i + ""; + if (i != "") { + f = '' + i + "" + } + this.execCommand("inserthtml", f) + } + } else { + if (h && h.anchorNode && h.anchorNode.parentNode.tagName == "A") { + var e = h.anchorNode.parentNode.href; + var i = h.anchorNode.parentNode.text; + if (h.toString() === "") { + this.insert_link_node = h.anchorNode.parentNode + } + } else { + var i = h.toString(); + var e = "" + } + } + c(".redactor_link_text").val(i); + c("#redactor_link_url").val(e).focus(); + c("#redactor_insert_link_btn").click(c.proxy(this.insertLink, this)) + }, this); + this.modalInit(RLANG.link, "link", 460, d) + }, insertLink:function () { + var e = c("#redactor_tab_selected").val(); + var d = "", f = ""; + if (e == 1) { + d = c("#redactor_link_url").val(); + f = c("#redactor_link_url_text").val() + } else { + if (e == 2) { + d = "mailto:" + c("#redactor_link_mailto").val(); + f = c("#redactor_link_mailto_text").val() + } else { + if (e == 3) { + d = "#" + c("#redactor_link_anchor").val(); + f = c("#redactor_link_anchor_text").val() + } + } + } + this._insertLink('' + f + " ", c.trim(f), d) + }, _insertLink:function (d, f, e) { + if (f != "") { + if (this.insert_link_node) { + c(this.insert_link_node).text(f); + c(this.insert_link_node).attr("href", e); + this.syncCode() + } else { + if (c.browser.msie) { + c(this.doc.getElementById("span" + this.spanid)).replaceWith(d); + this.syncCode() + } else { + this.execCommand("inserthtml", d) + } + } + } + this.modalClose() + }, showFile:function () { + if (c.browser.msie) { + this.markerIE() + } + var d = c.proxy(function () { + var e = this.getSelection(); + var f = ""; + if (this.oldIE()) { + f = e.text + } else { + f = e.toString() + } + c("#redactor_filename").val(f); + c("#redactor_file").dragupload({url:this.opts.fileUpload, success:c.proxy(function (g) { + this.fileUploadCallback(g) + }, this)}); + this.uploadInit("redactor_file", {auto:true, url:this.opts.fileUpload, success:c.proxy(function (g) { + this.fileUploadCallback(g) + }, this)}) + }, this); + this.modalInit(RLANG.file, "file", 500, d) + }, fileUploadCallback:function (d) { + var f = c.parseJSON(d); + var g = c("#redactor_filename").val(); + if (g == "") { + g = f.filename + } + var e = '' + g + ""; + if (c.browser.webkit && !!window.chrome) { + e = e + " " + } + if (c.browser.msie) { + if (g != "") { + c(this.doc.getElementById("span" + this.spanid)).replaceWith(a) + } else { + c(this.doc.getElementById("span" + this.spanid)).after(e).remove() + } + this.syncCode() + } else { + this.execCommand("inserthtml", e) + } + if (typeof this.opts.fileUploadCallback == "function") { + this.opts.fileUploadCallback(this, f) + } + this.modalClose() + }, setupModalWindows:function () { + this.opts.modal = {file:'
        ', image_edit:"", image:'