([\w\W]*?)<\/span>/gi, '');
+
+ html = html.replace(/ /gi, ' ');
+
+ // special characters
+ html = html.replace(/&/gi, '&');
+ html = html.replace(/\u2122/gi, '™');
+ html = html.replace(/\u00a9/gi, '©');
+ html = html.replace(/\u2026/gi, '…');
+ html = html.replace(/\u2014/gi, '—');
+ html = html.replace(/\u2010/gi, '‐');
+
+ html = this.cleanReConvertProtected(html);
+
+ return html;
+ },
+
+
+
+ // BUILD
+ buildStart: function()
+ {
+ // content
+ this.content = '';
+
+ // container
+ this.$box = $('
');
+
+ // textarea test
+ if (this.$source[0].tagName === 'TEXTAREA') this.opts.textareamode = true;
// mobile
if (this.opts.mobile === false && this.isMobile())
{
- this.build(true);
+ this.buildMobile();
+ }
+ else
+ {
+ // get the content at the start
+ this.buildContent();
+
+ if (this.opts.iframe)
+ {
+ // build as iframe
+ this.opts.autoresize = false;
+ this.iframeStart();
+ }
+ else if (this.opts.textareamode) this.buildFromTextarea();
+ else this.buildFromElement();
+
+ // options and final setup
+ if (!this.opts.iframe)
+ {
+ this.buildOptions();
+ this.buildAfter();
+ }
+ }
+ },
+ buildMobile: function()
+ {
+ if (!this.opts.textareamode)
+ {
+ this.$editor = this.$source;
+ this.$editor.hide();
+ this.$source = this.buildCodearea(this.$editor);
+ this.$source.val(this.content);
+ }
+
+ this.$box.insertAfter(this.$source).append(this.$source);
+ },
+ buildContent: function()
+ {
+ if (this.opts.textareamode) this.content = $.trim(this.$source.val());
+ else this.content = $.trim(this.$source.html());
+ },
+ buildFromTextarea: function()
+ {
+ this.$editor = $('
');
+ this.$box.insertAfter(this.$source).append(this.$editor).append(this.$source);
+
+ // enable
+ this.buildAddClasses(this.$editor);
+ this.buildEnable();
+ },
+ buildFromElement: function()
+ {
+ this.$editor = this.$source;
+ this.$source = this.buildCodearea(this.$editor);
+ this.$box.insertAfter(this.$editor).append(this.$editor).append(this.$source);
+
+ // enable
+ this.buildEnable();
+ },
+ buildCodearea: function($source)
+ {
+ return $('').attr('name', $source.attr('id')).css('height', this.sourceHeight);
+ },
+ buildAddClasses: function(el)
+ {
+ // append textarea classes to editable layer
+ $.each(this.$source.get(0).className.split(/\s+/), function(i,s)
+ {
+ el.addClass('redactor_' + s);
+ });
+ },
+ buildEnable: function()
+ {
+ this.$editor.addClass('redactor_editor').attr({ 'contenteditable': true, 'dir': this.opts.direction });
+ this.$source.attr('dir', this.opts.direction).hide();
+
+ // set code
+ this.set(this.content, true, false);
+ },
+ buildOptions: function()
+ {
+ var $source = this.$editor;
+ if (this.opts.iframe) $source = this.$frame;
+
+ // options
+ if (this.opts.tabindex) $source.attr('tabindex', this.opts.tabindex);
+
+ if (this.opts.minHeight) $source.css('min-height', this.opts.minHeight + 'px');
+ // FF fix bug with line-height rendering
+ else if (this.browser('mozilla') && this.opts.linebreaks)
+ {
+ this.$editor.css('min-height', '45px');
+ }
+ // FF fix bug with line-height rendering
+ if (this.browser('mozilla') && this.opts.linebreaks)
+ {
+ this.$editor.css('padding-bottom', '10px');
+ }
+
+
+ if (this.opts.maxHeight)
+ {
+ this.opts.autoresize = false;
+ this.sourceHeight = this.opts.maxHeight;
+ }
+ if (this.opts.wym) this.$editor.addClass('redactor_editor_wym');
+ if (this.opts.typewriter) this.$editor.addClass('redactor-editor-typewriter');
+ if (!this.opts.autoresize) $source.css('height', this.sourceHeight);
+
+ },
+ buildAfter: function()
+ {
+ this.start = false;
+
+ // load toolbar
+ if (this.opts.toolbar)
+ {
+ this.opts.toolbar = this.toolbarInit(this.opts.curLang);
+ this.toolbarBuild();
+ }
+
+ // modal templates
+ this.modalTemplatesInit();
+
+ // plugins
+ this.buildPlugins();
+
+ // enter, tab, etc.
+ this.buildBindKeyboard();
+
+ // autosave
+ if (this.opts.autosave) this.autosave();
+
+ // observers
+ setTimeout($.proxy(this.observeStart, this), 4);
+
+ // FF fix
+ if (this.browser('mozilla'))
+ {
+ try {
+ this.document.execCommand('enableObjectResizing', false, false);
+ this.document.execCommand('enableInlineTableEditing', false, false);
+ } catch (e) {}
+ }
+
+ // focus
+ if (this.opts.focus) setTimeout($.proxy(this.focus, this), 100);
+
+ // code mode
+ if (!this.opts.visual)
+ {
+ setTimeout($.proxy(function()
+ {
+ this.opts.visual = true;
+ this.toggle(false);
+
+ }, this), 200);
+ }
+
+ // init callback
+ this.callback('init');
+ },
+ buildBindKeyboard: function()
+ {
+ this.dblEnter = 0;
+
+ if (this.opts.dragUpload && (this.opts.imageUpload !== false || this.opts.s3 !== false))
+ {
+ this.$editor.on('drop.redactor', $.proxy(this.buildEventDrop, this));
+ }
+
+ this.$editor.on('click.redactor', $.proxy(function()
+ {
+ this.selectall = false;
+
+ }, this));
+
+ this.$editor.on('input.redactor', $.proxy(this.sync, this));
+ this.$editor.on('paste.redactor', $.proxy(this.buildEventPaste, this));
+ this.$editor.on('keydown.redactor', $.proxy(this.buildEventKeydown, this));
+ this.$editor.on('keyup.redactor', $.proxy(this.buildEventKeyup, this));
+
+ // textarea callback
+ if ($.isFunction(this.opts.textareaKeydownCallback))
+ {
+ this.$source.on('keydown.redactor-textarea', $.proxy(this.opts.textareaKeydownCallback, this));
+ }
+
+ // focus callback
+ if ($.isFunction(this.opts.focusCallback))
+ {
+ this.$editor.on('focus.redactor', $.proxy(this.opts.focusCallback, this));
+ }
+
+ var clickedElement;
+ $(document).mousedown(function(e) {
+ clickedElement = $(e.target);
+ });
+
+ // blur callback
+ this.$editor.on('blur.redactor', $.proxy(function(e)
+ {
+ if (!$(clickedElement).hasClass('redactor_toolbar') && $(clickedElement).parents('.redactor_toolbar').size() == 0)
+ {
+ this.selectall = false;
+ if ($.isFunction(this.opts.blurCallback)) this.callback('blur', e);
+ }
+ }, this));
+
+ },
+ buildEventDrop: function(e)
+ {
+ e = e.originalEvent || e;
+
+ if (window.FormData === undefined || !e.dataTransfer) return true;
+
+ var length = e.dataTransfer.files.length;
+ if (length == 0) return true;
+
+ e.preventDefault();
+
+ var file = e.dataTransfer.files[0];
+
+ if (this.opts.dnbImageTypes !== false && this.opts.dnbImageTypes.indexOf(file.type) == -1)
+ {
+ return true;
+ }
+
+ this.bufferSet();
+
+ this.showProgressBar();
+
+ if (this.opts.s3 === false)
+ {
+ this.dragUploadAjax(this.opts.imageUpload, file, true, e, this.opts.imageUploadParam);
+ }
+ else
+ {
+ this.s3uploadFile(file);
+ }
+
+
+ },
+ buildEventPaste: function(e)
+ {
+ var oldsafari = false;
+ if (this.browser('webkit') && navigator.userAgent.indexOf('Chrome') === -1)
+ {
+ var arr = this.browser('version').split('.');
+ if (arr[0] < 536) oldsafari = true;
+ }
+
+ if (oldsafari) return true;
+
+ // paste except opera (not webkit)
+ if (this.browser('opera')) return true;
+
+ // clipboard upload
+ if (this.opts.clipboardUpload && this.buildEventClipboardUpload(e)) return true;
+
+ if (this.opts.cleanup)
+ {
+ this.rtePaste = true;
+
+ this.selectionSave();
+
+ if (!this.selectall)
+ {
+ if (this.opts.autoresize === true && this.fullscreen !== true)
+ {
+ this.$editor.height(this.$editor.height());
+ this.saveScroll = this.document.body.scrollTop;
+ }
+ else
+ {
+ this.saveScroll = this.$editor.scrollTop();
+ }
+ }
+
+ var frag = this.extractContent();
+
+ setTimeout($.proxy(function()
+ {
+ var pastedFrag = this.extractContent();
+ this.$editor.append(frag);
+
+ this.selectionRestore();
+
+ var html = this.getFragmentHtml(pastedFrag);
+ this.pasteClean(html);
+
+ if (this.opts.autoresize === true && this.fullscreen !== true) this.$editor.css('height', 'auto');
+
+ }, this), 1);
+ }
+ },
+ buildEventClipboardUpload: function(e)
+ {
+ var event = e.originalEvent || e;
+ this.clipboardFilePaste = false;
+
+
+ if (typeof(event.clipboardData) === 'undefined') return false;
+ if (event.clipboardData.items)
+ {
+ var file = event.clipboardData.items[0].getAsFile();
+ if (file !== null)
+ {
+ this.bufferSet();
+ this.clipboardFilePaste = true;
+
+ var reader = new FileReader();
+ reader.onload = $.proxy(this.pasteClipboardUpload, this);
+ reader.readAsDataURL(file);
+
+ return true;
+ }
+ }
+
+ return false;
+
+ },
+ buildEventKeydown: function(e)
+ {
+ if (this.rtePaste) return false;
+
+ var key = e.which;
+ var ctrl = e.ctrlKey || e.metaKey;
+ var parent = this.getParent();
+ var current = this.getCurrent();
+ var block = this.getBlock();
+ var pre = false;
+
+ this.callback('keydown', e);
+
+ /*
+ firefox cmd+left/Cmd+right browser back/forward fix -
+ http://joshrhoderick.wordpress.com/2010/05/05/how-firefoxs-command-key-bug-kills-usability-on-the-mac/
+ */
+ if (this.browser('mozilla') && "modify" in window.getSelection())
+ {
+ if ((ctrl) && (e.keyCode===37 || e.keyCode===39))
+ {
+ var selection = this.getSelection();
+ var lineOrWord = (e.metaKey ? "line" : "word");
+ if (e.keyCode===37)
+ {
+ selection.modify("extend","left",lineOrWord);
+ if (!e.shiftKey)
+ {
+ selection.collapseToStart();
+ }
+ }
+ if (e.keyCode===39)
+ {
+ selection.modify("extend","right",lineOrWord);
+ if (!e.shiftKey)
+ {
+ selection.collapseToEnd();
+ }
+ }
+
+ e.preventDefault();
+ }
+ }
+
+
+ this.imageResizeHide(false);
+
+ // pre & down
+ if ((parent && $(parent).get(0).tagName === 'PRE') || (current && $(current).get(0).tagName === 'PRE'))
+ {
+ pre = true;
+ if (key === this.keyCode.DOWN) this.insertAfterLastElement(block);
+ }
+
+ // down
+ if (key === this.keyCode.DOWN)
+ {
+ if (parent && $(parent)[0].tagName === 'BLOCKQUOTE') this.insertAfterLastElement(parent);
+ if (current && $(current)[0].tagName === 'BLOCKQUOTE') this.insertAfterLastElement(current);
+
+ if (parent && $(parent)[0].tagName === 'P' && $(parent).parent()[0].tagName == 'BLOCKQUOTE')
+ {
+ this.insertAfterLastElement(parent, $(parent).parent()[0]);
+ }
+ if (current && $(current)[0].tagName === 'P' && parent && $(parent)[0].tagName == 'BLOCKQUOTE')
+ {
+ this.insertAfterLastElement(current, parent);
+ }
+ }
+
+ // shortcuts setup
+ this.shortcuts(e, key);
+
+ // buffer setup
+ if (ctrl && key === 90 && !e.shiftKey && !e.altKey) // z key
+ {
+ e.preventDefault();
+ if (this.opts.buffer.length) this.bufferUndo();
+ else this.document.execCommand('undo', false, false);
+ return;
+ }
+ // undo
+ else if (ctrl && key === 90 && e.shiftKey && !e.altKey)
+ {
+ e.preventDefault();
+ if (this.opts.rebuffer.length != 0) this.bufferRedo();
+ else this.document.execCommand('redo', false, false);
+ return;
+ }
+
+ // space
+ if (key == 32)
+ {
+ this.bufferSet();
+ }
+
+ // select all
+ if (ctrl && key === 65)
+ {
+ this.bufferSet();
+ this.selectall = true;
+ }
+ else if (key != this.keyCode.LEFT_WIN && !ctrl)
+ {
+ this.selectall = false;
+ }
+
+ // enter
+ if (key == this.keyCode.ENTER && !e.shiftKey && !e.ctrlKey && !e.metaKey)
+ {
+ // remove selected content on enter
+ var range = this.getRange();
+ if (range && range.collapsed === false)
+ {
+ sel = this.getSelection();
+ if (sel.rangeCount)
+ {
+ range.deleteContents();
+ }
+ }
+
+ // In ie, opera in the tables are created paragraphs, fix it.
+ if (this.browser('msie') && (parent.nodeType == 1 && (parent.tagName == 'TD' || parent.tagName == 'TH')))
+ {
+ e.preventDefault();
+ this.bufferSet();
+ this.insertNode(document.createElement('br'));
+ this.callback('enter', e);
+ return false;
+ }
+
+ // blockquote exit
+ if (block && (block.tagName == 'BLOCKQUOTE' || $(block).parent()[0].tagName == 'BLOCKQUOTE'))
+ {
+ if (this.isEndOfElement())
+ {
+ if (this.dblEnter == 1)
+ {
+ var element;
+ var last;
+ if (block.tagName == 'BLOCKQUOTE')
+ {
+ last = 'br';
+ element = block;
+ }
+ else
+ {
+ last = 'p';
+ element = $(block).parent()[0];
+ }
+
+ e.preventDefault();
+ this.insertingAfterLastElement(element);
+ this.dblEnter = 0;
+
+ if (last == 'p')
+ {
+ $(block).parent().find('p').last().remove();
+ }
+ else
+ {
+ var tmp = $.trim($(block).html());
+ $(block).html(tmp.replace(/ $/i, ''));
+ }
+
+ return;
+ }
+ else this.dblEnter++;
+ }
+ else this.dblEnter++;
+ }
+
+ // pre
+ if (pre === true)
+ {
+ return this.buildEventKeydownPre(e, current);
+ }
+ else
+ {
+ if (!this.opts.linebreaks)
+ {
+ // lists exit
+ if (block && block.tagName == 'LI')
+ {
+ var listCurrent = this.getBlock();
+ if (listCurrent !== false || listCurrent.tagName === 'LI')
+ {
+ var listText = $.trim($(block).text());
+ var listCurrentText = $.trim($(listCurrent).text());
+ if (listText == ''
+ && listCurrentText == ''
+ && $(listCurrent).next('li').size() == 0
+ && $(listCurrent).parents('li').size() == 0)
+ {
+ this.bufferSet();
+
+ var $list = $(listCurrent).closest('ol, ul');
+ $(listCurrent).remove();
+ var node = $('' + this.opts.invisibleSpace + '
');
+ $list.after(node);
+ this.selectionStart(node);
+
+ this.sync();
+ this.callback('enter', e);
+ return false;
+ }
+ }
+
+ }
+
+ // replace div to p
+ if (block && this.opts.rBlockTest.test(block.tagName))
+ {
+ // hit enter
+ this.bufferSet();
+
+ setTimeout($.proxy(function()
+ {
+ var blockElem = this.getBlock();
+ if (blockElem.tagName === 'DIV' && !$(blockElem).hasClass('redactor_editor'))
+ {
+ var node = $('' + this.opts.invisibleSpace + '
');
+ $(blockElem).replaceWith(node);
+ this.selectionStart(node);
+ }
+
+ }, this), 1);
+ }
+ else if (block === false)
+ {
+ // hit enter
+ this.bufferSet();
+ var node = $('' + this.opts.invisibleSpace + '
');
+ this.insertNode(node[0]);
+ this.selectionStart(node);
+ this.callback('enter', e);
+ return false;
+ }
+
+ }
+
+ if (this.opts.linebreaks)
+ {
+ // replace div to br
+ if (block && this.opts.rBlockTest.test(block.tagName))
+ {
+ // hit enter
+ this.bufferSet();
+
+ setTimeout($.proxy(function()
+ {
+ var blockElem = this.getBlock();
+ if ((blockElem.tagName === 'DIV' || blockElem.tagName === 'P') && !$(blockElem).hasClass('redactor_editor'))
+ {
+ this.replaceLineBreak(blockElem);
+ }
+
+ }, this), 1);
+ }
+ else
+ {
+ return this.buildEventKeydownInsertLineBreak(e);
+ }
+ }
+
+ // blockquote, figcaption
+ if (block.tagName == 'BLOCKQUOTE' || block.tagName == 'FIGCAPTION')
+ {
+ return this.buildEventKeydownInsertLineBreak(e);
+ }
+
+ }
+
+ this.callback('enter', e);
+ }
+ else if (key === this.keyCode.ENTER && (e.ctrlKey || e.shiftKey)) // Shift+Enter or Ctrl+Enter
+ {
+ this.bufferSet();
+
+ e.preventDefault();
+ this.insertLineBreak();
+ }
+
+ // tab (cmd + [)
+ if ((key === this.keyCode.TAB || e.metaKey && key === 219) && this.opts.shortcuts)
+ {
+ return this.buildEventKeydownTab(e, pre, key);
+ }
+
+ // delete zero-width space before the removing
+ if (key === this.keyCode.BACKSPACE) this.buildEventKeydownBackspace(e, current, parent);
+
+ },
+ buildEventKeydownPre: function(e, current)
+ {
+ e.preventDefault();
+ this.bufferSet();
+ var html = $(current).parent().text();
+ this.insertNode(document.createTextNode('\n'));
+ if (html.search(/\s$/) == -1)
+ {
+ this.insertNode(document.createTextNode('\n'));
+ }
+
+ this.sync();
+ this.callback('enter', e);
+ return false;
+ },
+ buildEventKeydownTab: function(e, pre, key)
+ {
+ if (!this.opts.tabFocus) return true;
+ if (this.isEmpty(this.get()) && this.opts.tabSpaces === false) return true;
+
+ e.preventDefault();
+
+ if (pre === true && !e.shiftKey)
+ {
+ this.bufferSet();
+ this.insertNode(document.createTextNode('\t'));
+ this.sync();
+ return false;
+
+ }
+ else if (this.opts.tabSpaces !== false)
+ {
+ this.bufferSet();
+ this.insertNode(document.createTextNode(Array(this.opts.tabSpaces + 1).join('\u00a0')));
+ this.sync();
+ return false;
+ }
+ else
+ {
+ if (!e.shiftKey) this.indentingIndent();
+ else this.indentingOutdent();
+ }
+
+ return false;
+ },
+ buildEventKeydownBackspace: function(e, current, parent)
+ {
+ // remove empty list in table
+ if (parent && current && parent.parentNode.tagName == 'TD'
+ && parent.tagName == 'UL' && current.tagName == 'LI' && $(parent).children('li').size() == 1)
+ {
+ var text = $(current).text().replace(/[\u200B-\u200D\uFEFF]/g, '');
+ if (text == '')
+ {
+ var node = parent.parentNode;
+ $(parent).remove();
+ this.selectionStart(node);
+ this.sync();
+ return false;
+ }
+ }
+
+ if (typeof current.tagName !== 'undefined' && /^(H[1-6])$/i.test(current.tagName))
+ {
+ var node;
+ if (this.opts.linebreaks === false) node = $('' + this.opts.invisibleSpace + '
');
+ else node = $(' ' + this.opts.invisibleSpace);
+
+ $(current).replaceWith(node);
+ this.selectionStart(node);
+ this.sync();
+ }
+
+ if (typeof current.nodeValue !== 'undefined' && current.nodeValue !== null)
+ {
+ if (current.remove && current.nodeType === 3 && current.nodeValue.match(/[^\u200B]/g) == null)
+ {
+ $(current).prev().remove();
+ this.sync();
+ }
+ }
+ },
+ buildEventKeydownInsertLineBreak: function(e)
+ {
+ this.bufferSet();
+ e.preventDefault();
+ this.insertLineBreak();
+ this.callback('enter', e);
+ return;
+ },
+ buildEventKeyup: function(e)
+ {
+ if (this.rtePaste) return false;
+
+ var key = e.which;
+ var parent = this.getParent();
+ var current = this.getCurrent();
+
+ // replace to p before / after the table or body
+ if (!this.opts.linebreaks && current.nodeType == 3 && (parent == false || parent.tagName == 'BODY'))
+ {
+ var node = $('').append($(current).clone());
+ $(current).replaceWith(node);
+ var next = $(node).next();
+ if (typeof(next[0]) !== 'undefined' && next[0].tagName == 'BR')
+ {
+ next.remove();
+ }
+
+ this.selectionEnd(node);
+ }
+
+ // convert links
+ if ((this.opts.convertLinks || this.opts.convertImageLinks || this.opts.convertVideoLinks) && key === this.keyCode.ENTER)
+ {
+ this.buildEventKeyupConverters();
+ }
+
+ // if empty
+ if (key === this.keyCode.DELETE || key === this.keyCode.BACKSPACE)
+ {
+ return this.formatEmpty(e);
+ }
+
+ this.callback('keyup', e);
+ this.sync(e);
+ },
+ buildEventKeyupConverters: function()
+ {
+ this.formatLinkify(this.opts.linkProtocol, this.opts.convertLinks, this.opts.convertImageLinks, this.opts.convertVideoLinks, this.opts.linkSize);
+
+ setTimeout($.proxy(function()
+ {
+ if (this.opts.convertImageLinks) this.observeImages();
+ if (this.opts.observeLinks) this.observeLinks();
+ }, this), 5);
+ },
+ buildPlugins: function()
+ {
+ if (!this.opts.plugins ) return;
+
+ $.each(this.opts.plugins, $.proxy(function(i, s)
+ {
+ if (RedactorPlugins[s])
+ {
+ $.extend(this, RedactorPlugins[s]);
+ if ($.isFunction( RedactorPlugins[ s ].init)) this.init();
+ }
+
+ }, this ));
+ },
+
+ // IFRAME
+ iframeStart: function()
+ {
+ this.iframeCreate();
+
+ if (this.opts.textareamode) this.iframeAppend(this.$source);
+ else
+ {
+ this.$sourceOld = this.$source.hide();
+ this.$source = this.buildCodearea(this.$sourceOld);
+ this.iframeAppend(this.$sourceOld);
+ }
+ },
+ iframeAppend: function(el)
+ {
+ this.$source.attr('dir', this.opts.direction).hide();
+ this.$box.insertAfter(el).append(this.$frame).append(this.$source);
+ },
+ iframeCreate: function()
+ {
+ this.$frame = $('').one('load', $.proxy(function()
+ {
+ if (this.opts.fullpage)
+ {
+ this.iframePage();
+
+ if (this.content === '') this.content = this.opts.invisibleSpace;
+
+ this.$frame.contents()[0].write(this.content);
+ this.$frame.contents()[0].close();
+
+ var timer = setInterval($.proxy(function()
+ {
+ if (this.$frame.contents().find('body').html())
+ {
+ clearInterval(timer);
+ this.iframeLoad();
+ }
+
+ }, this), 0);
+ }
+ else this.iframeLoad();
+
+ }, this));
+ },
+ iframeDoc: function()
+ {
+ return this.$frame[0].contentWindow.document;
+ },
+ iframePage: function()
+ {
+ var doc = this.iframeDoc();
+ if (doc.documentElement) doc.removeChild(doc.documentElement);
+
+ return doc;
+ },
+ iframeAddCss: function(css)
+ {
+ css = css || this.opts.css;
+
+ if (this.isString(css))
+ {
+ this.$frame.contents().find('head').append(' ');
+ }
+
+ if ($.isArray(css))
+ {
+ $.each(css, $.proxy(function(i, url)
+ {
+ this.iframeAddCss(url);
+
+ }, this));
+ }
+ },
+ iframeLoad: function()
+ {
+ this.$editor = this.$frame.contents().find('body').attr({ 'contenteditable': true, 'dir': this.opts.direction });
+
+ // set document & window
+ if (this.$editor[0])
+ {
+ this.document = this.$editor[0].ownerDocument;
+ this.window = this.document.defaultView || window;
+ }
+
+ // iframe css
+ this.iframeAddCss();
+
+ if (this.opts.fullpage)
+ {
+ this.setFullpageOnInit(this.$source.val());
+ }
+ else this.set(this.content, true, false);
+
+ this.buildOptions();
+ this.buildAfter();
+ },
+
+ // PLACEHOLDER
+ placeholderInit: function()
+ {
+ if (this.opts.placeholder !== false)
+ {
+ this.placeholderText = this.opts.placeholder;
+ this.opts.placeholder = true;
+ }
+ else
+ {
+ if (typeof this.$element.attr('placeholder') == 'undefined' || this.$element.attr('placeholder') == '')
+ {
+ this.opts.placeholder = false;
+ }
+ else
+ {
+ this.placeholderText = this.$element.attr('placeholder');
+ this.opts.placeholder = true;
+ }
+ }
+ },
+ placeholderStart: function(html)
+ {
+ if (this.opts.placeholder === false)
+ {
return false;
}
- // iframe
+ if (this.isEmpty(html))
+ {
+ this.opts.focus = false;
+ this.placeholderOnFocus();
+ this.placeholderOnBlur();
+
+ return this.placeholderGet();
+ }
+ else
+ {
+ this.placeholderOnBlur();
+ }
+
+ return false;
+ },
+ placeholderOnFocus: function()
+ {
+ this.$editor.on('focus.redactor_placeholder', $.proxy(this.placeholderFocus, this));
+ },
+ placeholderOnBlur: function()
+ {
+ this.$editor.on('blur.redactor_placeholder', $.proxy(this.placeholderBlur, this));
+ },
+ placeholderGet: function()
+ {
+ var ph = $('').data('redactor', 'verified')
+ .attr('contenteditable', false).text(this.placeholderText);
+
+ if (this.opts.linebreaks === false)
+ {
+ return $('').append(ph);
+ }
+ else return ph;
+ },
+ placeholderBlur: function()
+ {
+ var html = this.get();
+ if (this.isEmpty(html))
+ {
+ this.placeholderOnFocus();
+ this.$editor.html(this.placeholderGet());
+ }
+ },
+ placeholderFocus: function()
+ {
+ this.$editor.find('span.redactor_placeholder').remove();
+
+ var html = '';
+ if (this.opts.linebreaks === false)
+ {
+ html = this.opts.emptyHtml;
+ }
+
+ this.$editor.off('focus.redactor_placeholder');
+ this.$editor.html(html);
+
+ if (this.opts.linebreaks === false)
+ {
+ // place the cursor inside emptyHtml
+ this.selectionStart(this.$editor.children()[0]);
+ }
+ else
+ {
+ this.focus();
+ }
+
+ this.sync();
+ },
+ placeholderRemoveFromEditor: function()
+ {
+ this.$editor.find('span.redactor_placeholder').remove();
+ this.$editor.off('focus.redactor_placeholder');
+ },
+ placeholderRemoveFromCode: function(html)
+ {
+ return html.replace(/(.*?)<\/span>/i, '');
+ },
+
+ // SHORTCUTS
+ shortcuts: function(e, key)
+ {
+
+ // disable browser's hot keys for bold and italic
+ if (!this.opts.shortcuts)
+ {
+ if ((e.ctrlKey || e.metaKey) && (key === 66 || key === 73))
+ {
+ e.preventDefault();
+ }
+
+ return false;
+ }
+
+ $.each(this.opts.shortcuts, $.proxy(function(str, command)
+ {
+ var keys = str.split(',');
+ for (var i in keys)
+ {
+ if (typeof keys[i] === 'string')
+ {
+ this.shortcutsHandler(e, $.trim(keys[i]), $.proxy(function()
+ {
+ eval(command);
+ }, this));
+ }
+
+ }
+
+ }, this));
+
+
+ },
+ shortcutsHandler: function(e, keys, origHandler)
+ {
+ // based on https://github.com/jeresig/jquery.hotkeys
+ var hotkeysSpecialKeys =
+ {
+ 8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
+ 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
+ 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
+ 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
+ 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
+ 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
+ 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
+ 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'"
+ };
+
+
+ var hotkeysShiftNums =
+ {
+ "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
+ "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
+ ".": ">", "/": "?", "\\": "|"
+ };
+
+ keys = keys.toLowerCase().split(" ");
+ var special = hotkeysSpecialKeys[e.keyCode],
+ character = String.fromCharCode( e.which ).toLowerCase(),
+ modif = "", possible = {};
+
+ $.each([ "alt", "ctrl", "meta", "shift"], function(index, specialKey)
+ {
+ if (e[specialKey + 'Key'] && special !== specialKey)
+ {
+ modif += specialKey + '+';
+ }
+ });
+
+
+ if (special)
+ {
+ possible[modif + special] = true;
+ }
+
+ if (character)
+ {
+ possible[modif + character] = true;
+ possible[modif + hotkeysShiftNums[character]] = true;
+
+ // "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
+ if (modif === "shift+")
+ {
+ possible[hotkeysShiftNums[character]] = true;
+ }
+ }
+
+ for (var i = 0, l = keys.length; i < l; i++)
+ {
+ if (possible[keys[i]])
+ {
+ e.preventDefault();
+ return origHandler.apply(this, arguments);
+ }
+ }
+ },
+
+ // FOCUS
+ focus: function()
+ {
+ if (!this.browser('opera'))
+ {
+ this.window.setTimeout($.proxy(this.focusSet, this, true), 1);
+ }
+ else
+ {
+ this.$editor.focus();
+ }
+ },
+ focusWithSaveScroll: function()
+ {
+ if (this.browser('msie'))
+ {
+ var top = this.document.documentElement.scrollTop;
+ }
+
+ this.$editor.focus();
+
+ if (this.browser('msie'))
+ {
+ this.document.documentElement.scrollTop = top;
+ }
+ },
+ focusEnd: function()
+ {
+ if (!this.browser('mozilla'))
+ {
+ this.focusSet();
+ }
+ else
+ {
+ if (this.opts.linebreaks === false)
+ {
+ var last = this.$editor.children().last();
+
+ this.$editor.focus();
+ this.selectionEnd(last);
+ }
+ else
+ {
+ this.focusSet();
+ }
+ }
+ },
+ focusSet: function(collapse, element)
+ {
+ this.$editor.focus();
+
+ if (typeof element == 'undefined')
+ {
+ element = this.$editor[0];
+ }
+
+ var range = this.getRange();
+ range.selectNodeContents(element);
+
+ // collapse - controls the position of focus: the beginning (true), at the end (false).
+ range.collapse(collapse || false);
+
+ var sel = this.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ },
+
+ // TOGGLE
+ toggle: function(direct)
+ {
+ if (this.opts.visual) this.toggleCode(direct);
+ else this.toggleVisual();
+ },
+ toggleVisual: function()
+ {
+ var html = this.$source.hide().val();;
+ if (typeof this.modified !== 'undefined')
+ {
+ var modified = this.modified.replace(/\n/g, '');
+
+ var thtml = html.replace(/\n/g, '');
+ thtml = this.cleanRemoveSpaces(thtml, false);
+
+ this.modified = this.cleanRemoveSpaces(modified, false) !== thtml;
+ }
+
+ if (this.modified)
+ {
+ // don't remove the iframe even if cleared all.
+ if (this.opts.fullpage && html === '')
+ {
+ this.setFullpageOnInit(html);
+ }
+ else
+ {
+ this.set(html);
+ if (this.opts.fullpage)
+ {
+ this.buildBindKeyboard();
+ }
+ }
+
+ this.callback('change', false, html);
+ }
+
+ if (this.opts.iframe) this.$frame.show();
+ else this.$editor.show();
+
+ if (this.opts.fullpage) this.$editor.attr('contenteditable', true );
+
+ this.$source.off('keydown.redactor-textarea-indenting');
+
+ this.$editor.focus();
+ this.selectionRestore();
+
+ this.observeStart();
+ this.buttonActiveVisual();
+ this.buttonInactive('html');
+ this.opts.visual = true;
+
+
+ },
+ toggleCode: function(direct)
+ {
+ if (direct !== false) this.selectionSave();
+
+ var height = null;
if (this.opts.iframe)
{
- this.opts.autoresize = false;
+ height = this.$frame.height();
+ if (this.opts.fullpage) this.$editor.removeAttr('contenteditable');
+ this.$frame.hide();
+ }
+ else
+ {
+ height = this.$editor.innerHeight();
+ this.$editor.hide();
+ }
+
+ var html = this.$source.val();
+
+ // tidy html
+ if (html !== '' && this.opts.tidyHtml)
+ {
+ this.$source.val(this.cleanHtml(html));
+ }
+
+ this.modified = html;
+
+ this.$source.height(height).show().focus();
+
+ // textarea indenting
+ this.$source.on('keydown.redactor-textarea-indenting', this.textareaIndenting);
+
+ this.buttonInactiveVisual();
+ this.buttonActive('html');
+ this.opts.visual = false;
+ },
+ textareaIndenting: function(e)
+ {
+ if (e.keyCode === 9)
+ {
+ var $el = $(this);
+ var start = $el.get(0).selectionStart;
+ $el.val($el.val().substring(0, start) + "\t" + $el.val().substring($el.get(0).selectionEnd));
+ $el.get(0).selectionStart = $el.get(0).selectionEnd = start + 1;
+ return false;
+ }
+ },
+
+ // AUTOSAVE
+ autosave: function()
+ {
+ var savedHtml = false;
+ this.autosaveInterval = setInterval($.proxy(function()
+ {
+ var html = this.get();
+ if (savedHtml !== html)
+ {
+ var name = this.$source.attr('name');
+ $.ajax({
+ url: this.opts.autosave,
+ type: 'post',
+ data: 'name=' + name + '&' + name + '=' + escape(encodeURIComponent(html)),
+ success: $.proxy(function(data)
+ {
+ var json = $.parseJSON(data);
+ if (typeof json.error == 'undefined')
+ {
+ // success
+ this.callback('autosave', false, json);
+ }
+ else
+ {
+ // error
+ this.callback('autosaveError', false, json);
+ }
+
+ savedHtml = html;
+
+ }, this)
+ });
+ }
+ }, this), this.opts.autosaveInterval*1000);
+ },
+
+ // TOOLBAR
+ toolbarBuild: function()
+ {
+ // hide on mobile
+ if (this.isMobile() && this.opts.buttonsHideOnMobile.length > 0)
+ {
+ $.each(this.opts.buttonsHideOnMobile, $.proxy(function(i, s)
+ {
+ var index = this.opts.buttons.indexOf(s);
+ this.opts.buttons.splice(index, 1);
+
+ }, this));
}
// extend buttons
@@ -629,1138 +2342,2636 @@ var RLANG = {
{
this.opts.buttons = this.opts.airButtons;
}
- else if (this.opts.toolbar !== false)
+ else
{
- if (this.opts.source === false)
+ if (!this.opts.buttonSource)
{
var index = this.opts.buttons.indexOf('html');
- var next = this.opts.buttons[index+1];
this.opts.buttons.splice(index, 1);
- if (typeof next !== 'undefined' && next === '|')
- {
- this.opts.buttons.splice(index, 1);
- }
}
-
- $.extend(this.opts.toolbar, this.opts.buttonsCustom);
- $.each(this.opts.buttonsAdd, $.proxy(function(i,s)
- {
- this.opts.buttons.push(s);
-
- }, this));
}
// formatting tags
- if (this.opts.toolbar !== false)
+ if (this.opts.toolbar)
{
- $.each(this.opts.toolbar.formatting.dropdown, $.proxy(function(i,s)
+ $.each(this.opts.toolbar.formatting.dropdown, $.proxy(function (i, s)
{
- if ($.inArray(i, this.opts.formattingTags) == '-1')
- {
- delete this.opts.toolbar.formatting.dropdown[i];
- }
+ if ($.inArray(i, this.opts.formattingTags ) == '-1') delete this.opts.toolbar.formatting.dropdown[i];
}, this));
}
- function afterBuild()
+ // if no buttons don't create a toolbar
+ if (this.opts.buttons.length === 0) return false;
+
+ // air enable
+ this.airEnable();
+
+ // toolbar build
+ this.$toolbar = $('').addClass('redactor_toolbar').attr('id', 'redactor_toolbar_' + this.uuid);
+
+ if (this.opts.typewriter)
{
- // air enable
- this.enableAir();
-
- // toolbar
- this.buildToolbar();
-
- // PLUGINS
- if (typeof this.opts.plugins === 'object')
- {
- $.each(this.opts.plugins, $.proxy(function(i,s)
- {
- if (typeof RedactorPlugins[s] !== 'undefined')
- {
- $.extend(this, RedactorPlugins[s]);
-
- if (typeof RedactorPlugins[s].init !== 'undefined')
- {
- this.init();
- }
- }
-
- }, this));
- }
-
- // buttons response
- if (this.opts.activeButtons !== false && this.opts.toolbar !== false)
- {
- var observeFormatting = $.proxy(function() { this.observeFormatting(); }, this);
- this.$editor.click(observeFormatting).keyup(observeFormatting);
- }
-
- // paste
- var oldsafari = false;
- if (this.browser('webkit') && navigator.userAgent.indexOf('Chrome') === -1)
- {
- var arr = this.browser('version').split('.');
- if (arr[0] < 536) oldsafari = true;
- }
-
- if (this.isMobile(true) === false && oldsafari === false)
- {
- this.$editor.bind('paste', $.proxy(function(e)
- {
- if (this.opts.cleanup === false)
- {
- return true;
- }
-
- this.pasteRunning = true;
-
- this.setBuffer();
-
- if (this.opts.autoresize === true)
- {
- this.saveScroll = this.document.body.scrollTop;
- }
- else
- {
- this.saveScroll = this.$editor.scrollTop();
- }
-
- var frag = this.extractContent();
-
- setTimeout($.proxy(function()
- {
- var pastedFrag = this.extractContent();
- this.$editor.append(frag);
-
- this.restoreSelection();
-
- var html = this.getFragmentHtml(pastedFrag);
- this.pasteCleanUp(html);
- this.pasteRunning = false;
-
- }, this), 1);
-
- }, this));
- }
-
- // key handlers
- this.keyup();
- this.keydown();
-
- // autosave
- if (this.opts.autosave !== false)
- {
- this.autoSave();
- }
-
- // observers
- setTimeout($.proxy(function()
- {
- this.observeImages();
- this.observeTables();
-
- }, this), 1);
-
- // FF fix
- if (this.browser('mozilla'))
- {
- this.$editor.click($.proxy(function()
- {
- this.saveSelection();
- }, this));
-
- try
- {
- this.document.execCommand('enableObjectResizing', false, false);
- this.document.execCommand('enableInlineTableEditing', false, false);
- }
- catch (e) {}
- }
-
- // focus
- if (this.opts.focus)
- {
- setTimeout($.proxy(function(){
- this.$editor.focus();
- }, this), 1);
- }
-
- // fixed
- if (this.opts.fixed)
- {
- this.observeScroll();
- $(document).scroll($.proxy(this.observeScroll, this));
- }
-
- // callback
- if (typeof this.opts.callback === 'function')
- {
- this.opts.callback(this);
- }
-
- if (this.opts.toolbar !== false)
- {
- this.$toolbar.find('a').attr('tabindex', '-1');
- }
+ this.$toolbar.addClass('redactor-toolbar-typewriter');
}
- // construct editor
- this.build(false, afterBuild);
-
- },
- shortcuts: function(e, cmd)
- {
- e.preventDefault();
- this.execCommand(cmd, false);
- },
- keyup: function()
- {
- this.$editor.keyup($.proxy(function(e)
+ if (this.opts.toolbarOverflow && this.isMobile())
{
- var key = e.keyCode || e.which;
+ this.$toolbar.addClass('redactor-toolbar-overflow');
+ }
- if (this.browser('mozilla') && !this.pasteRunning)
- {
- this.saveSelection();
- }
-
- // callback as you type
- if (typeof this.opts.keyupCallback === 'function')
- {
- this.opts.keyupCallback(this, e);
- }
-
- // if empty
- if (key === 8 || key === 46)
- {
- this.observeImages();
- return this.formatEmpty(e);
- }
-
- // new line p
- if (key === 13 && !e.shiftKey && !e.ctrlKey && !e.metaKey)
- {
- if (this.browser('webkit'))
- {
- this.formatNewLine(e);
- }
-
- // convert links
- if (this.opts.convertLinks)
- {
- this.$editor.linkify();
- }
- }
-
- this.syncCode();
-
- }, this));
- },
- keydown: function()
- {
- this.$editor.keydown($.proxy(function(e)
+ if (this.opts.air)
{
- var key = e.keyCode || e.which;
- var parent = this.getParentNode();
- var current = this.getCurrentNode();
- var pre = false;
- var ctrl = e.ctrlKey || e.metaKey;
-
- if ((parent || current) && ($(parent).get(0).tagName === 'PRE' || $(current).get(0).tagName === 'PRE'))
- {
- pre = true;
- }
-
- // callback keydown
- if (typeof this.opts.keydownCallback === 'function')
- {
- this.opts.keydownCallback(this, e);
- }
-
- if (ctrl && this.opts.shortcuts)
- {
- if (key === 90)
- {
- if (this.opts.buffer !== false)
- {
- e.preventDefault();
- this.getBuffer();
- }
- else if (e.shiftKey)
- {
- this.shortcuts(e, 'redo'); // Ctrl + Shift + z
- }
- else
- {
- this.shortcuts(e, 'undo'); // Ctrl + 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
- }
- else if (key === 72)
- {
- this.shortcuts(e, 'subscript'); // Ctrl + h
- }
- }
-
- // clear undo buffer
- if (!ctrl && key !== 90)
- {
- this.opts.buffer = false;
- }
-
- // enter
- if (pre === true && key === 13)
- {
- e.preventDefault();
-
- var html = $(current).parent().text();
- this.insertNodeAtCaret(this.document.createTextNode('\r\n'));
- if (html.search(/\s$/) == -1)
- {
- this.insertNodeAtCaret(this.document.createTextNode('\r\n'));
- }
- this.syncCode();
-
- return false;
- }
-
- // tab
- if (this.opts.shortcuts && !e.shiftKey && key === 9)
- {
- if (pre === false)
- {
- this.shortcuts(e, 'indent'); // Tab
- }
- else
- {
- e.preventDefault();
- this.insertNodeAtCaret(this.document.createTextNode('\t'));
- this.syncCode();
- return false;
- }
- }
- else if (this.opts.shortcuts && e.shiftKey && key === 9 )
- {
- this.shortcuts(e, 'outdent'); // Shift + tab
- }
-
- // safari shift key + enter
- if (this.browser('webkit') && navigator.userAgent.indexOf('Chrome') === -1)
- {
- return this.safariShiftKeyEnter(e, key);
- }
- }, this));
- },
- build: function(mobile, whendone)
- {
- if (mobile !== true)
- {
- // container
- this.$box = $('
');
-
// air box
- if (this.opts.air)
- {
- this.air = $('
');
- }
-
- this.$content = null;
-
- function initFrame()
- {
- this.$editor = this.$content.contents().find("body").attr('contenteditable', true).attr('dir', this.opts.direction);
-
- rdocument = this.document = this.$editor[0].ownerDocument;
- rwindow = this.window = this.document.defaultView || window;
-
- if (this.opts.css !== false)
- {
- this.$content.contents().find('head').append(' ');
- }
-
- this.$editor.html(html);
-
- if (whendone)
- {
- whendone.call(this);
- whendone = null;
- }
- }
-
- // editor
- this.textareamode = true;
- if (this.$el.get(0).tagName === 'TEXTAREA')
- {
- if(this.opts.iframe)
- {
- var me = this;
- this.$content = $('').load(function()
- {
- initFrame.call(me);
- });
- }
- else
- {
- this.$content = this.$editor = $('
');
- }
-
- var classlist = this.$el.get(0).className.split(/\s+/);
- $.each(classlist, $.proxy(function(i,s)
- {
- this.$content.addClass('redactor_' + s);
- }, this));
- }
- else
- {
- this.textareamode = false;
- this.$content = this.$editor = this.$el;
- this.$el = $('').css('height', this.height);
- }
-
- if (this.$editor)
- {
- this.$editor.addClass('redactor_editor').attr('contenteditable', true).attr('dir', this.opts.direction);
- }
-
- if (this.opts.tabindex !== false)
- {
- this.$content.attr('tabindex', this.opts.tabindex);
- }
-
- if (this.opts.minHeight !== false)
- {
- this.$content.css('min-height', this.opts.minHeight + 'px');
- }
-
- if (this.opts.wym === true)
- {
- this.$content.addClass('redactor_editor_wym');
- }
-
- if (this.opts.autoresize === false)
- {
- this.$content.css('height', this.height);
- }
-
- // hide textarea
- this.$el.hide();
-
- // append box and frame
- var html = '';
- if (this.textareamode)
- {
- // get html
- html = this.$el.val();
- html = this.savePreCode(html);
-
- this.$box.insertAfter(this.$el).append(this.$content).append(this.$el);
- }
- else
- {
- // get html
- html = this.$editor.html();
- html = this.savePreCode(html);
-
- this.$box.insertAfter(this.$content).append(this.$el).append(this.$editor);
-
- }
-
- // conver newlines to p
- html = this.paragraphy(html);
-
- // enable
- if (this.$editor)
- {
- this.$editor.html(html);
- }
-
- if (this.textareamode === false)
- {
- this.syncCode();
- }
+ this.$air = $('').attr('id', 'redactor_air_' + this.uuid).hide();
+ this.$air.append(this.$toolbar);
+ $('body').append(this.$air);
}
else
{
- if (this.$el.get(0).tagName !== 'TEXTAREA')
+ if (this.opts.toolbarExternal)
{
- var html = this.$el.val();
- var textarea = $('
').css('height', this.height).val(html);
- this.$el.hide();
- this.$el.after(textarea);
+ this.$toolbar.addClass('redactor-toolbar-external');
+ $(this.opts.toolbarExternal).html(this.$toolbar);
}
+ else this.$box.prepend(this.$toolbar);
}
- if (whendone && this.$editor)
+ $.each(this.opts.buttons, $.proxy(function(i, btnName)
{
- whendone.call(this);
- }
-
- },
- enableAir: function()
- {
- if (this.opts.air === false)
- {
- return false;
- }
-
- this.air.hide();
-
- this.$editor.bind('textselect', $.proxy(function(e)
- {
- this.showAir(e);
-
- }, this));
-
- this.$editor.bind('textunselect', $.proxy(function()
- {
- this.air.hide();
-
- }, this));
-
- },
- showAir: function(e)
- {
- $('.redactor_air').hide();
-
- var width = this.air.innerWidth();
- var left = e.clientX;
-
- if ($(this.document).width() < (left + width))
- {
- left = left - width;
- }
-
- var top = e.clientY + $(document).scrollTop() + 14;
- if (this.opts.iframe === true)
- {
- top = top + this.$box.position().top;
- left = left + this.$box.position().left;
- }
-
- this.air.css({ left: left + 'px', top: top + 'px' }).show();
- },
- syncCode: function()
- {
- this.$el.val(this.$editor.html());
- },
-
- // API functions
- setCode: function(html)
- {
- html = this.stripTags(html);
- this.$editor.html(html).focus();
-
- this.syncCode();
- },
- getCode: function()
- {
- var html = '';
- if (this.opts.visual)
- {
- html = this.$editor.html()
- }
- else
- {
- html = this.$el.val();
- }
-
- return this.stripTags(html);
- },
- insertHtml: function(html)
- {
- this.$editor.focus();
- this.pasteHtmlAtCaret(html);
- this.observeImages();
- this.syncCode();
- },
-
- pasteHtmlAtCaret: function (html)
- {
- var sel, range;
- if (this.document.getSelection)
- {
- sel = this.window.getSelection();
- if (sel.getRangeAt && sel.rangeCount)
+ if (this.opts.toolbar[btnName])
{
- range = sel.getRangeAt(0);
- range.deleteContents();
- var el = this.document.createElement("div");
- el.innerHTML = html;
- var frag = this.document.createDocumentFragment(), node, lastNode;
- while (node = el.firstChild)
- {
- lastNode = frag.appendChild(node);
- }
- range.insertNode(frag);
-
- if (lastNode)
- {
- range = range.cloneRange();
- range.setStartAfter(lastNode);
- range.collapse(true);
- sel.removeAllRanges();
- sel.addRange(range);
- }
- }
- }
- else if (this.document.selection && this.document.selection.type != "Control")
- {
- this.document.selection.createRange().pasteHTML(html);
- }
- },
-
- destroy: function()
- {
- var html = this.getCode();
-
- if (this.textareamode)
- {
- this.$box.after(this.$el);
- this.$box.remove();
- this.$el.height(this.height).val(html).show();
- }
- else
- {
- this.$box.after(this.$editor);
- this.$box.remove();
- this.$editor.removeClass('redactor_editor').removeClass('redactor_editor_wym').attr('contenteditable', false).html(html).show();
- }
-
- if (this.opts.toolbarExternal)
- {
- $(this.opts.toolbarExternal).empty();
- }
-
- $('.redactor_air').remove();
-
- for (var i = 0; i < this.dropdowns.length; i++)
- {
- this.dropdowns[i].remove();
- delete(this.dropdowns[i]);
- }
-
- if (this.opts.autosave !== false)
- {
- clearInterval(this.autosaveInterval);
- }
-
- },
- // end API functions
-
- // OBSERVERS
- observeFormatting: function()
- {
- var parent = this.getCurrentNode();
-
- this.inactiveAllButtons();
-
- $.each(this.opts.activeButtonsStates, $.proxy(function(i,s)
- {
- if ($(parent).closest(i,this.$editor.get()[0]).length != 0)
- {
- this.setBtnActive(s);
+ var btnObject = this.opts.toolbar[btnName];
+ if (this.opts.fileUpload === false && btnName === 'file') return true;
+ this.$toolbar.append( $('
').append(this.buttonBuild(btnName, btnObject)));
}
}, this));
- var tag = $(parent).closest(['p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'td']);
+ this.$toolbar.find('a').attr('tabindex', '-1');
- if (typeof tag[0] !== 'undefined' && typeof tag[0].elem !== 'undefined' && $(tag[0].elem).size() != 0)
+ // fixed
+ if (this.opts.toolbarFixed)
{
- var align = $(tag[0].elem).css('text-align');
-
- switch (align)
- {
- case 'right':
- this.setBtnActive('alignright');
- break;
- case 'center':
- this.setBtnActive('aligncenter');
- break;
- case 'justify':
- this.setBtnActive('justify');
- break;
- default:
- this.setBtnActive('alignleft');
- break;
- }
- }
- },
- observeImages: function()
- {
- if (this.opts.observeImages === false)
- {
- return false;
+ this.toolbarObserveScroll();
+ $(this.opts.toolbarFixedTarget).on('scroll.redactor', $.proxy(this.toolbarObserveScroll, this));
}
- this.$editor.find('img').each($.proxy(function(i,s)
+ // buttons response
+ if (this.opts.activeButtons)
{
- if (this.browser('msie'))
- {
- $(s).attr('unselectable', 'on');
- }
-
- this.resizeImage(s);
-
- }, this));
-
+ this.$editor.on('mouseup.redactor keyup.redactor', $.proxy(this.buttonActiveObserver, this));
+ }
},
- observeTables: function()
+ toolbarObserveScroll: function()
{
- this.$editor.find('table').click($.proxy(this.tableObserver, this));
- },
- observeScroll: function()
- {
- var scrolltop = $(this.document).scrollTop();
- var boxtop = this.$box.offset().top;
+ var scrollTop = $(this.opts.toolbarFixedTarget).scrollTop();
+
+ var boxTop = 0;
var left = 0;
+ var end = 0;
- if (scrolltop > boxtop)
+ if (this.opts.toolbarFixedTarget === document)
+ {
+ boxTop = this.$box.offset().top;
+ }
+ else
+ {
+ boxTop = 1;
+ }
+
+ end = boxTop + this.$box.height() + 40;
+
+ if (scrollTop > boxTop)
{
var width = '100%';
- if (this.opts.fixedBox)
+ if (this.opts.toolbarFixedBox)
{
left = this.$box.offset().left;
width = this.$box.innerWidth();
+ this.$toolbar.addClass('toolbar_fixed_box');
}
- this.fixed = true;
- this.$toolbar.css({ position: 'fixed', width: width, zIndex: 1005, top: this.opts.fixedTop + 'px', left: left });
- }
- else
- {
- this.fixed = false;
- this.$toolbar.css({ position: 'relative', width: 'auto', zIndex: 1, top: 0, left: left });
- }
- },
+ this.toolbarFixed = true;
- // BUFFER
- setBuffer: function()
- {
- this.saveSelection();
- this.opts.buffer = this.$editor.html();
- },
- getBuffer: function()
- {
- if (this.opts.buffer === false)
- {
- return false;
- }
-
- this.$editor.html(this.opts.buffer);
-
- if (!this.browser('msie'))
- {
- this.restoreSelection();
- }
-
- this.opts.buffer = false;
- },
-
-
-
- // EXECCOMMAND
- execCommand: function(cmd, param)
- {
- if (this.opts.visual == false)
- {
- this.$el.focus();
- return false;
- }
-
- try
- {
-
- var parent;
-
- if (cmd === 'inserthtml')
+ if (this.opts.toolbarFixedTarget === document)
{
- if (this.browser('msie'))
- {
- this.$editor.focus();
- this.document.selection.createRange().pasteHTML(param);
- }
- else
- {
- this.pasteHtmlAtCaret(param);
- //this.execRun(cmd, param);
- }
-
- this.observeImages();
- }
- else if (cmd === 'unlink')
- {
- parent = this.getParentNode();
- if ($(parent).get(0).tagName === 'A')
- {
- $(parent).replaceWith($(parent).text());
- }
- else
- {
- this.execRun(cmd, param);
- }
- }
- else if (cmd === 'JustifyLeft' || cmd === 'JustifyCenter' || cmd === 'JustifyRight' || cmd === 'JustifyFull')
- {
- parent = this.getCurrentNode();
- var tag = $(parent).get(0).tagName;
-
- if (this.opts.iframe === false && $(parent).parents('.redactor_editor').size() == 0)
- {
- return false;
- }
-
- var tagsArray = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'TD'];
- if ($.inArray(tag, tagsArray) != -1)
- {
- var align = false;
-
- if (cmd === 'JustifyCenter')
- {
- align = 'center';
- }
- else if (cmd === 'JustifyRight')
- {
- align = 'right';
- }
- else if (cmd === 'JustifyFull')
- {
- align = 'justify';
- }
-
- if (align === false)
- {
- $(parent).css('text-align', '');
- }
- else
- {
- $(parent).css('text-align', align);
- }
- }
- else
- {
- this.execRun(cmd, param);
- }
- }
- else if (cmd === 'formatblock' && param === 'blockquote')
- {
- parent = this.getCurrentNode();
- if ($(parent).get(0).tagName === 'BLOCKQUOTE')
- {
- if (this.browser('msie'))
- {
- var node = $('' + $(parent).html() + '
');
- $(parent).replaceWith(node);
- }
- else
- {
- this.execRun(cmd, 'p');
- }
- }
- else if ($(parent).get(0).tagName === 'P')
- {
- var parent2 = $(parent).parent();
- if ($(parent2).get(0).tagName === 'BLOCKQUOTE')
- {
- var node = $('' + $(parent).html() + '
');
- $(parent2).replaceWith(node);
- this.setSelection(node[0], 0, node[0], 0);
- }
- else
- {
- if (this.browser('msie'))
- {
- var node = $('' + $(parent).html() + ' ');
- $(parent).replaceWith(node);
- }
- else
- {
- this.execRun(cmd, param);
- }
- }
- }
- else
- {
- this.execRun(cmd, param);
- }
- }
- else if (cmd === 'formatblock' && (param === 'pre' || param === 'p'))
- {
- parent = this.getParentNode();
-
- if ($(parent).get(0).tagName === 'PRE')
- {
- $(parent).replaceWith('' + this.encodeEntities($(parent).text()) + '
');
- }
- else
- {
- this.execRun(cmd, param);
- }
+ this.$toolbar.css({
+ position: 'fixed',
+ width: width,
+ zIndex: 10005,
+ top: this.opts.toolbarFixedTopOffset + 'px',
+ left: left
+ });
}
else
{
- if (cmd === 'inserthorizontalrule' && this.browser('msie'))
- {
- this.$editor.focus();
- }
-
- if (cmd === 'formatblock' && this.browser('mozilla'))
- {
- this.$editor.focus();
- }
-
- this.execRun(cmd, param);
+ this.$toolbar.css({
+ position: 'absolute',
+ width: width,
+ zIndex: 10005,
+ top: (this.opts.toolbarFixedTopOffset + scrollTop) + 'px',
+ left: 0
+ });
}
- if (cmd === 'inserthorizontalrule')
+ if (scrollTop < end) this.$toolbar.css('visibility', 'visible');
+ else this.$toolbar.css('visibility', 'hidden');
+ }
+ else
+ {
+ this.toolbarFixed = false;
+ this.$toolbar.css({
+ position: 'relative',
+ width: 'auto',
+ top: 0,
+ left: left
+ });
+
+ if (this.opts.toolbarFixedBox) this.$toolbar.removeClass('toolbar_fixed_box');
+ }
+ },
+
+ // AIR
+ airEnable: function()
+ {
+ if (!this.opts.air) return;
+
+ this.$editor.on('mouseup.redactor keyup.redactor', this, $.proxy(function(e)
+ {
+ var text = this.getSelectionText();
+
+ if (e.type === 'mouseup' && text != '') this.airShow(e);
+ if (e.type === 'keyup' && e.shiftKey && text != '')
{
- this.$editor.find('hr').removeAttr('id');
+ var $focusElem = $(this.getElement(this.getSelection().focusNode)), offset = $focusElem.offset();
+ offset.height = $focusElem.height();
+ this.airShow(offset, true);
}
- this.syncCode();
+ }, this));
+ },
+ airShow: function (e, keyboard)
+ {
+ if (!this.opts.air) return;
- if (this.oldIE())
- {
- this.$editor.focus();
- }
+ var left, top;
+ $('.redactor_air').hide();
- if (typeof this.opts.execCommandCallback === 'function')
- {
- this.opts.execCommandCallback(this, cmd);
- }
+ if (keyboard)
+ {
+ left = e.left;
+ top = e.top + e.height + 14;
- if (this.opts.air)
+ if (this.opts.iframe)
{
- this.air.hide();
+ top += this.$box.position().top - $(this.document).scrollTop();
+ left += this.$box.position().left;
}
}
- catch (e) { }
+ else
+ {
+ var width = this.$air.innerWidth();
+
+ left = e.clientX;
+ if ($(this.document).width() < (left + width)) left -= width;
+
+ top = e.clientY + 14;
+ if (this.opts.iframe)
+ {
+ top += this.$box.position().top;
+ left += this.$box.position().left;
+ }
+ else top += $( this.document ).scrollTop();
+ }
+
+ this.$air.css({
+ left: left + 'px',
+ top: top + 'px'
+ }).show();
+
+ this.airBindHide();
},
- execRun: function(cmd, param)
+ airBindHide: function()
+ {
+ if (!this.opts.air) return;
+
+ var hideHandler = $.proxy(function(doc)
+ {
+ $(doc).on('mousedown.redactor', $.proxy(function(e)
+ {
+ if ($( e.target ).closest(this.$toolbar).length === 0)
+ {
+ this.$air.fadeOut(100);
+ this.selectionRemove();
+ $(doc).off(e);
+ }
+
+ }, this)).on('keydown.redactor', $.proxy(function(e)
+ {
+ if (e.which === this.keyCode.ESC)
+ {
+ this.getSelection().collapseToStart();
+ }
+
+ this.$air.fadeOut(100);
+ $(doc).off(e);
+
+ }, this));
+ }, this);
+
+ // Hide the toolbar at events in all documents (iframe)
+ hideHandler(document);
+ if (this.opts.iframe) hideHandler(this.document);
+ },
+ airBindMousemoveHide: function()
+ {
+ if (!this.opts.air) return;
+
+ var hideHandler = $.proxy(function(doc)
+ {
+ $(doc).on('mousemove.redactor', $.proxy(function(e)
+ {
+ if ($( e.target ).closest(this.$toolbar).length === 0)
+ {
+ this.$air.fadeOut(100);
+ $(doc).off(e);
+ }
+
+ }, this));
+ }, this);
+
+ // Hide the toolbar at events in all documents (iframe)
+ hideHandler(document);
+ if (this.opts.iframe) hideHandler(this.document);
+ },
+
+ // DROPDOWNS
+ dropdownBuild: function($dropdown, dropdownObject)
+ {
+ $.each(dropdownObject, $.proxy(function(btnName, btnObject)
+ {
+ if (!btnObject.className) btnObject.className = '';
+
+ var $item;
+ if (btnObject.name === 'separator') $item = $('');
+ else
+ {
+ $item = $(' ' + btnObject.title + ' ');
+ $item.on('click', $.proxy(function(e)
+ {
+ if (e.preventDefault) e.preventDefault();
+ if (this.browser('msie')) e.returnValue = false;
+
+ if (btnObject.callback) btnObject.callback.call(this, btnName, $item, btnObject, e);
+ if (btnObject.exec) this.execCommand(btnObject.exec, btnName);
+ if (btnObject.func) this[btnObject.func](btnName);
+
+ this.buttonActiveObserver();
+ if (this.opts.air) this.$air.fadeOut(100);
+
+ }, this));
+ }
+
+ $dropdown.append($item);
+
+ }, this));
+ },
+ dropdownShow: function(e, key)
+ {
+ if (!this.opts.visual)
+ {
+ e.preventDefault();
+ return false;
+ }
+
+ var $button = this.buttonGet(key);
+
+ // Always re-append it to the end of so it always has the highest sub-z-index.
+ var $dropdown = $button.data('dropdown').appendTo(document.body);
+
+ if ($button.hasClass('dropact')) this.dropdownHideAll();
+ else
+ {
+ this.dropdownHideAll();
+ this.callback('dropdownShow', { dropdown: $dropdown, key: key, button: $button });
+
+ this.buttonActive(key);
+ $button.addClass('dropact');
+
+ var keyPosition = $button.offset();
+
+ // fix right placement
+ var dropdownWidth = $dropdown.width();
+ if ((keyPosition.left + dropdownWidth) > $(document).width())
+ {
+ keyPosition.left -= dropdownWidth;
+ }
+
+ var left = keyPosition.left + 'px';
+ var btnHeight = $button.innerHeight();
+
+ var position = 'absolute';
+ var top = (btnHeight + this.opts.toolbarFixedTopOffset) + 'px';
+
+ if (this.opts.toolbarFixed && this.toolbarFixed) position = 'fixed';
+ else top = keyPosition.top + btnHeight + 'px';
+
+ $dropdown.css({ position: position, left: left, top: top }).show();
+ this.callback('dropdownShown', { dropdown: $dropdown, key: key, button: $button });
+ }
+
+
+ var hdlHideDropDown = $.proxy(function(e)
+ {
+
+ this.dropdownHide(e, $dropdown);
+
+ }, this);
+
+ $(document).one('click', hdlHideDropDown);
+ this.$editor.one('click', hdlHideDropDown);
+ this.$editor.one('touchstart', hdlHideDropDown);
+
+
+ e.stopPropagation();
+ this.focusWithSaveScroll();
+ },
+ dropdownHideAll: function()
+ {
+ this.$toolbar.find('a.dropact').removeClass('redactor_act').removeClass('dropact');
+ $('.redactor_dropdown').hide();
+ this.callback('dropdownHide');
+ },
+ dropdownHide: function (e, $dropdown)
+ {
+ if (!$(e.target).hasClass('dropact'))
+ {
+ $dropdown.removeClass('dropact');
+ this.dropdownHideAll();
+ }
+ },
+
+ // BUTTONS
+ buttonBuild: function(btnName, btnObject, buttonImage)
+ {
+ var $button = $(' ');
+
+ if (typeof buttonImage != 'undefined')
+ {
+ $button.addClass('redactor-btn-image');
+ }
+
+ $button.on('click', $.proxy(function(e)
+ {
+ if (e.preventDefault) e.preventDefault();
+ if (this.browser('msie')) e.returnValue = false;
+
+ if ($button.hasClass('redactor_button_disabled')) return false;
+
+ if (this.isFocused() === false && !btnObject.exec)
+ {
+ this.focusWithSaveScroll();
+ }
+
+ if (btnObject.exec)
+ {
+ this.focusWithSaveScroll();
+
+ this.execCommand(btnObject.exec, btnName);
+ this.airBindMousemoveHide();
+
+ }
+ else if (btnObject.func && btnObject.func !== 'show')
+ {
+ this[btnObject.func](btnName);
+ this.airBindMousemoveHide();
+
+ }
+ else if (btnObject.callback)
+ {
+ btnObject.callback.call(this, btnName, $button, btnObject, e);
+ this.airBindMousemoveHide();
+
+ }
+ else if (btnObject.dropdown)
+ {
+ this.dropdownShow(e, btnName);
+ }
+
+ this.buttonActiveObserver(false, btnName);
+
+ }, this));
+
+ // dropdown
+ if (btnObject.dropdown)
+ {
+ var $dropdown = $('');
+ $button.data('dropdown', $dropdown);
+ this.dropdownBuild($dropdown, btnObject.dropdown);
+ }
+
+ return $button;
+ },
+ buttonGet: function(key)
+ {
+ if (!this.opts.toolbar) return false;
+ return $(this.$toolbar.find('a.re-' + key));
+ },
+ buttonTagToActiveState: function(buttonName, tagName)
+ {
+ this.opts.activeButtons.push(buttonName);
+ this.opts.activeButtonsStates[tagName] = buttonName;
+ },
+ buttonActiveToggle: function(key)
+ {
+ var btn = this.buttonGet(key);
+
+ if (btn.hasClass('redactor_act'))
+ {
+ this.buttonInactive(key);
+ }
+ else
+ {
+ this.buttonActive(key);
+ }
+ },
+ buttonActive: function(key)
+ {
+ var btn = this.buttonGet(key);
+ btn.addClass('redactor_act');
+ },
+ buttonInactive: function(key)
+ {
+ var btn = this.buttonGet(key);
+ btn.removeClass('redactor_act');
+ },
+ buttonInactiveAll: function(btnName)
+ {
+ this.$toolbar.find('a.re-icon').not('.re-' + btnName).removeClass('redactor_act');
+ },
+ buttonActiveVisual: function()
+ {
+ this.$toolbar.find('a.re-icon').not('a.re-html').removeClass('redactor_button_disabled');
+ },
+ buttonInactiveVisual: function()
+ {
+ this.$toolbar.find('a.re-icon').not('a.re-html').addClass('redactor_button_disabled');
+ },
+ buttonChangeIcon: function (key, classname)
+ {
+ this.buttonGet(key).addClass('re-' + classname);
+ },
+ buttonRemoveIcon: function(key, classname)
+ {
+ this.buttonGet(key).removeClass('re-' + classname);
+ },
+ buttonAwesome: function(key, name)
+ {
+ var button = this.buttonGet(key);
+ button.removeClass('redactor-btn-image');
+ button.addClass('fa-redactor-btn');
+ button.html('
');
+ },
+ buttonAdd: function(key, title, callback, dropdown)
+ {
+ if (!this.opts.toolbar) return;
+ var btn = this.buttonBuild(key, { title: title, callback: callback, dropdown: dropdown }, true);
+
+ this.$toolbar.append($('
').append(btn));
+
+ return btn;
+ },
+ buttonAddFirst: function(key, title, callback, dropdown)
+ {
+ if (!this.opts.toolbar) return;
+ var btn = this.buttonBuild(key, { title: title, callback: callback, dropdown: dropdown }, true);
+ this.$toolbar.prepend($(' ').append(btn));
+ },
+ buttonAddAfter: function(afterkey, key, title, callback, dropdown)
+ {
+ if (!this.opts.toolbar) return;
+ var btn = this.buttonBuild(key, { title: title, callback: callback, dropdown: dropdown }, true);
+ var $btn = this.buttonGet(afterkey);
+
+ if ($btn.size() !== 0) $btn.parent().after($(' ').append(btn));
+ else this.$toolbar.append($(' ').append(btn));
+
+ return btn;
+ },
+ buttonAddBefore: function(beforekey, key, title, callback, dropdown)
+ {
+ if (!this.opts.toolbar) return;
+ var btn = this.buttonBuild(key, { title: title, callback: callback, dropdown: dropdown }, true);
+ var $btn = this.buttonGet(beforekey);
+
+ if ($btn.size() !== 0) $btn.parent().before($(' ').append(btn));
+ else this.$toolbar.append($(' ').append(btn));
+
+ return btn;
+ },
+ buttonRemove: function (key)
+ {
+ var $btn = this.buttonGet(key);
+ $btn.remove();
+ },
+ buttonActiveObserver: function(e, btnName)
+ {
+ var parent = this.getParent();
+ this.buttonInactiveAll(btnName);
+
+ if (e === false && btnName !== 'html')
+ {
+ if ($.inArray(btnName, this.opts.activeButtons) != -1)
+ {
+ this.buttonActiveToggle(btnName);
+ }
+ return;
+ }
+
+ if (parent && parent.tagName === 'A') this.$toolbar.find('a.redactor_dropdown_link').text(this.opts.curLang.link_edit);
+ else this.$toolbar.find('a.redactor_dropdown_link').text(this.opts.curLang.link_insert);
+
+ $.each(this.opts.activeButtonsStates, $.proxy(function(key, value)
+ {
+ if ($(parent).closest(key, this.$editor.get()[0]).length != 0)
+ {
+ this.buttonActive(value);
+ }
+
+ }, this));
+
+ var $parent = $(parent).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]);
+ if ($parent.length)
+ {
+ var align = $parent.css('text-align');
+ if (align == '')
+ {
+ align = 'left';
+ }
+
+ this.buttonActive('align' + align);
+ }
+ },
+
+ // EXEC
+ execPasteFrag: function(html)
+ {
+ var sel = this.getSelection();
+ if (sel.getRangeAt && sel.rangeCount)
+ {
+ var range = this.getRange();
+ range.deleteContents();
+
+ var el = this.document.createElement("div");
+ el.innerHTML = html;
+
+ var frag = this.document.createDocumentFragment(), node, lastNode;
+ while ((node = el.firstChild))
+ {
+ lastNode = frag.appendChild(node);
+ }
+
+ var firstNode = frag.firstChild;
+ range.insertNode(frag);
+
+ if (lastNode)
+ {
+ range = range.cloneRange();
+ range.setStartAfter(lastNode);
+ range.collapse(true);
+ }
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ },
+ exec: function(cmd, param, sync)
{
if (cmd === 'formatblock' && this.browser('msie'))
{
param = '<' + param + '>';
}
- this.document.execCommand(cmd, false, param);
+ if (cmd === 'inserthtml' && this.browser('msie'))
+ {
+ if (!this.isIe11())
+ {
+ this.focusWithSaveScroll();
+ this.document.selection.createRange().pasteHTML(param);
+ }
+ else this.execPasteFrag(param);
+ }
+ else
+ {
+ this.document.execCommand(cmd, false, param);
+ }
+
+ if (sync !== false) this.sync();
+ this.callback('execCommand', cmd, param);
+ },
+ execCommand: function(cmd, param, sync)
+ {
+ if (!this.opts.visual)
+ {
+ this.$source.focus();
+ return false;
+ }
+
+ if ( cmd === 'bold'
+ || cmd === 'italic'
+ || cmd === 'underline'
+ || cmd === 'strikethrough')
+ {
+ this.bufferSet();
+ }
+
+
+ if (cmd === 'superscript' || cmd === 'subscript')
+ {
+ var parent = this.getParent();
+ if (parent.tagName === 'SUP' || parent.tagName === 'SUB')
+ {
+ this.inlineRemoveFormatReplace(parent);
+ }
+ }
+
+ if (cmd === 'inserthtml')
+ {
+ this.insertHtml(param, sync);
+ this.callback('execCommand', cmd, param);
+ return;
+ }
+
+ // Stop formatting pre
+ if (this.currentOrParentIs('PRE') && !this.opts.formattingPre) return false;
+
+ // Lists
+ if (cmd === 'insertunorderedlist' || cmd === 'insertorderedlist') return this.execLists(cmd, param);
+
+ // Unlink
+ if (cmd === 'unlink') return this.execUnlink(cmd, param);
+
+ // Usual exec
+ this.exec(cmd, param, sync);
+
+ // Line
+ if (cmd === 'inserthorizontalrule') this.$editor.find('hr').removeAttr('id');
+
+ },
+ execUnlink: function(cmd, param)
+ {
+ this.bufferSet();
+
+ var link = this.currentOrParentIs('A');
+ if (link)
+ {
+ $(link).replaceWith($(link).text());
+
+ this.sync();
+ this.callback('execCommand', cmd, param);
+ return;
+ }
+ },
+ execLists: function(cmd, param)
+ {
+ this.bufferSet();
+
+ var parent = this.getParent();
+ var $list = $(parent).closest('ol, ul');
+
+ if (!this.isParentRedactor($list) && $list.size() != 0)
+ {
+ $list = false;
+ }
+
+ var remove = false;
+
+ if ($list && $list.length)
+ {
+ remove = true;
+ var listTag = $list[0].tagName;
+ if ((cmd === 'insertunorderedlist' && listTag === 'OL')
+ || (cmd === 'insertorderedlist' && listTag === 'UL'))
+ {
+ remove = false;
+ }
+ }
+
+ this.selectionSave();
+
+ // remove lists
+ if (remove)
+ {
+
+ var nodes = this.getNodes();
+ var elems = this.getBlocks(nodes);
+
+ if (typeof nodes[0] != 'undefined' && nodes.length > 1 && nodes[0].nodeType == 3)
+ {
+ // fix the adding the first li to the array
+ elems.unshift(this.getBlock());
+ }
+
+ var data = '', replaced = '';
+ $.each(elems, $.proxy(function(i,s)
+ {
+ if (s.tagName == 'LI')
+ {
+ var $s = $(s);
+ var cloned = $s.clone();
+ cloned.find('ul', 'ol').remove();
+
+ if (this.opts.linebreaks === false)
+ {
+ data += this.outerHtml($('').append(cloned.contents()));
+ }
+ else
+ {
+ var clonedHtml = cloned.html().replace(/ $/i, '');
+ data += clonedHtml + ' ';
+ }
+
+ if (i == 0)
+ {
+ $s.addClass('redactor-replaced').empty();
+ replaced = this.outerHtml($s);
+ }
+ else $s.remove();
+ }
+
+ }, this));
+
+
+ html = this.$editor.html().replace(replaced, '' + listTag + '>' + data + '<' + listTag + '>');
+
+ this.$editor.html(html);
+ this.$editor.find(listTag + ':empty').remove();
+
+ }
+
+ // insert lists
+ else
+ {
+ var firstParent = $(this.getParent()).closest('td');
+
+ if (this.browser('msie') && !this.isIe11() && this.opts.linebreaks)
+ {
+ var wrapper = this.selectionWrap('div');
+ var wrapperHtml = $(wrapper).html();
+ var tmpList = $('
');
+ if (cmd == 'insertorderedlist')
+ {
+ tmpList = $('');
+ }
+
+ var tmpLi = $('');
+
+ if ($.trim(wrapperHtml) == '')
+ {
+ tmpLi.append(wrapperHtml + '' + this.opts.invisibleSpace + ' ');
+ tmpList.append(tmpLi);
+ this.$editor.find('#selection-marker-1').replaceWith(tmpList);
+ }
+ else
+ {
+ tmpLi.append(wrapperHtml);
+ tmpList.append(tmpLi);
+ $(wrapper).replaceWith(tmpList);
+ }
+ }
+ else
+ {
+ this.document.execCommand(cmd);
+ }
+
+ var parent = this.getParent();
+ var $list = $(parent).closest('ol, ul');
+
+ if (this.opts.linebreaks === false)
+ {
+ var listText = $.trim($list.text());
+ if (listText == '')
+ {
+ $list.children('li').find('br').remove();
+ $list.children('li').append('' + this.opts.invisibleSpace + ' ');
+ }
+ }
+
+ if (firstParent.size() != 0)
+ {
+ $list.wrapAll('');
+ }
+
+ if ($list.length)
+ {
+ // remove block-element list wrapper
+ var $listParent = $list.parent();
+ if (this.isParentRedactor($listParent) && $listParent[0].tagName != 'LI' && this.nodeTestBlocks($listParent[0]))
+ {
+ $listParent.replaceWith($listParent.contents());
+ }
+ }
+
+ if (this.browser('mozilla'))
+ {
+ this.$editor.focus();
+ }
+ }
+
+ this.selectionRestore();
+ this.$editor.find('#selection-marker-1').removeAttr('id');
+ this.sync();
+ this.callback('execCommand', cmd, param);
+ return;
},
- // FORMAT NEW LINE
- formatNewLine: function(e)
+ // INDENTING
+ indentingIndent: function()
{
- var parent = this.getParentNode();
+ this.indentingStart('indent');
+ },
+ indentingOutdent: function()
+ {
+ this.indentingStart('outdent');
+ },
+ indentingStart: function(cmd)
+ {
+ this.bufferSet();
- if (parent.nodeName === 'DIV' && parent.className === 'redactor_editor')
+ if (cmd === 'indent')
{
- var element = $(this.getCurrentNode());
+ var block = this.getBlock();
- if (element.get(0).tagName === 'DIV' && (element.html() === '' || element.html() === ' '))
+ this.selectionSave();
+
+ if (block && block.tagName == 'LI')
{
- var newElement = $('').append(element.clone().get(0).childNodes);
- element.replaceWith(newElement);
- newElement.html(' ');
- this.setSelection(newElement[0], 0, newElement[0], 0);
+ // li
+ var parent = this.getParent();
+
+ var $list = $(parent).closest('ol, ul');
+ var listTag = $list[0].tagName;
+
+ var elems = this.getBlocks();
+
+ $.each(elems, function(i,s)
+ {
+ if (s.tagName == 'LI')
+ {
+ var $prev = $(s).prev();
+ if ($prev.size() != 0 && $prev[0].tagName == 'LI')
+ {
+ var $childList = $prev.children('ul, ol');
+ if ($childList.size() == 0)
+ {
+ $prev.append($('<' + listTag + '>').append(s));
+ }
+ else $childList.append(s);
+ }
+ }
+ });
+ }
+ // linebreaks
+ else if (block === false && this.opts.linebreaks === true)
+ {
+ this.exec('formatBlock', 'blockquote');
+ var newblock = this.getBlock();
+ var block = $('
').html($(newblock).html());
+ $(newblock).replaceWith(block);
+
+ var left = this.normalize($(block).css('margin-left')) + this.opts.indentValue;
+ $(block).css('margin-left', left + 'px');
+ }
+ else
+ {
+ // all block tags
+ var elements = this.getBlocks();
+ $.each(elements, $.proxy(function(i, elem)
+ {
+ var $el = false;
+
+ if (elem.tagName === 'TD') return;
+
+ if ($.inArray(elem.tagName, this.opts.alignmentTags) !== -1)
+ {
+ $el = $(elem);
+ }
+ else
+ {
+ $el = $(elem).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]);
+ }
+
+ var left = this.normalize($el.css('margin-left')) + this.opts.indentValue;
+ $el.css('margin-left', left + 'px');
+
+ }, this));
+ }
+
+ this.selectionRestore();
+
+ }
+ // outdent
+ else
+ {
+ this.selectionSave();
+
+ var block = this.getBlock();
+ if (block && block.tagName == 'LI')
+ {
+ // li
+ var elems = this.getBlocks();
+ var index = 0;
+
+ this.insideOutdent(block, index, elems);
+ }
+ else
+ {
+ // all block tags
+ var elements = this.getBlocks();
+ $.each(elements, $.proxy(function(i, elem)
+ {
+ var $el = false;
+
+ if ($.inArray(elem.tagName, this.opts.alignmentTags) !== -1)
+ {
+ $el = $(elem);
+ }
+ else
+ {
+ $el = $(elem).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]);
+ }
+
+ var left = this.normalize($el.css('margin-left')) - this.opts.indentValue;
+ if (left <= 0)
+ {
+ // linebreaks
+ if (this.opts.linebreaks === true && typeof($el.data('tagblock')) !== 'undefined')
+ {
+ $el.replaceWith($el.html() + '
');
+ }
+ // all block tags
+ else
+ {
+ $el.css('margin-left', '');
+ this.removeEmptyAttr($el, 'style');
+ }
+ }
+ else
+ {
+ $el.css('margin-left', left + 'px');
+ }
+
+ }, this));
+ }
+
+
+ this.selectionRestore();
+ }
+
+ this.sync();
+
+ },
+ insideOutdent: function (li, index, elems)
+ {
+ if (li && li.tagName == 'LI')
+ {
+ var $parent = $(li).parent().parent();
+ if ($parent.size() != 0 && $parent[0].tagName == 'LI')
+ {
+ $parent.after(li);
+ }
+ else
+ {
+ if (typeof elems[index] != 'undefined')
+ {
+ li = elems[index];
+ index++;
+
+ this.insideOutdent(li, index, elems);
+ }
+ else
+ {
+ this.execCommand('insertunorderedlist');
+ }
}
}
},
- // SAFARI SHIFT KEY + ENTER
- safariShiftKeyEnter: function(e, key)
+ // ALIGNMENT
+ alignmentLeft: function()
{
- if (e.shiftKey && key === 13)
- {
- e.preventDefault();
- this.insertNodeAtCaret($('
').get(0));
- this.syncCode();
- return false;
- }
- else
+ this.alignmentSet('', 'JustifyLeft');
+ },
+ alignmentRight: function()
+ {
+ this.alignmentSet('right', 'JustifyRight');
+ },
+ alignmentCenter: function()
+ {
+ this.alignmentSet('center', 'JustifyCenter');
+ },
+ alignmentJustify: function()
+ {
+ this.alignmentSet('justify', 'JustifyFull');
+ },
+ alignmentSet: function(type, cmd)
+ {
+ this.bufferSet();
+
+ if (this.oldIE())
{
+ this.document.execCommand(cmd, false, false);
return true;
}
- },
- // FORMAT EMPTY
- formatEmpty: function(e)
- {
- var html = $.trim(this.$editor.html());
+ this.selectionSave();
- if (this.browser('mozilla'))
+ var block = this.getBlock();
+ if (!block && this.opts.linebreaks)
{
- html = html.replace(/
/i, '');
- }
+ // one element
+ this.exec('formatblock', 'div');
- var thtml = html.replace(/<(?:.|\n)*?>/gm, '');
+ var newblock = this.getBlock();
+ var block = $('
').html($(newblock).html());
+ $(newblock).replaceWith(block);
- if (html === '' || thtml === '')
- {
- e.preventDefault();
+ $(block).css('text-align', type);
+ this.removeEmptyAttr(block, 'style');
- var node = $(this.opts.emptyHtml).get(0);
- this.$editor.html(node);
- this.setSelection(node, 0, node, 0);
-
- this.syncCode();
- return false;
+ if (type == '' && typeof($(block).data('tagblock')) !== 'undefined')
+ {
+ $(block).replaceWith($(block).html());
+ }
}
else
{
- this.syncCode();
+ var elements = this.getBlocks();
+ $.each(elements, $.proxy(function(i, elem)
+ {
+ var $el = false;
+
+ if ($.inArray(elem.tagName, this.opts.alignmentTags) !== -1)
+ {
+ $el = $(elem);
+ }
+ else
+ {
+ $el = $(elem).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]);
+ }
+
+ if ($el)
+ {
+ $el.css('text-align', type);
+ this.removeEmptyAttr($el, 'style');
+ }
+
+ }, this));
}
+
+ this.selectionRestore();
+ this.sync();
},
- // PARAGRAPHY
- paragraphy: function (str)
+ // CLEAN
+ cleanEmpty: function(html)
{
- str = $.trim(str);
- if (str === '' || str === '
')
+ var ph = this.placeholderStart(html);
+ if (ph !== false) return ph;
+
+ if (this.opts.linebreaks === false)
{
- return this.opts.emptyHtml;
+ if (html === '') html = this.opts.emptyHtml;
+ else if (html.search(/^
$/gi) !== -1) html = '
' + this.opts.emptyHtml;
}
+ return html;
+ },
+ cleanConverters: function(html)
+ {
// convert div to p
- if (this.opts.convertDivs)
+ if (this.opts.convertDivs && !this.opts.gallery)
{
- str = str.replace(/
([\w\W]*?)<\/div>/gi, '
$2
');
+ html = html.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); };
+ if (this.opts.paragraphy) html = this.cleanParagraphy(html);
- // 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 = '
' + str;
- str += '\n';
-
- R(' \\s* ', '\n\n');
- R('(<' + blocks + '[^>]*>)', '\n$1');
- R('(' + blocks + '>)', '$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*?((div|address|form)[^>]*>)', '
$1
$2');
- R('
\\s*(?' + blocks + '[^>]*>)\\s*
', '$1');
- R('
(
', '$1');
- R('\\s*(?' + blocks + '[^>]*>)', '$1');
- R('(?' + blocks + '[^>]*>)\\s*
', '$1');
- R('(?' + blocks + '[^>]*>)\\s* ', '$1');
- R(' (\\s*?(p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)', '$1');
-
- // pre
- if (str.indexOf(')((.|\n)*?) ', function(m0, m1, m2, m3)
+ html = html.replace(/\{\{(.*?)\}\}/gi, '');
+ html = html.replace(/\{(.*?)\}/gi, '');
+ }
+
+ html = html.replace(/');
+ html = html.replace(/([\w\W]*?)<\/section>/gi, '');
+ html = html.replace(/([\w\W]*?)<\/section>/gi, '');
+
+ // php tags convertation
+ if (this.opts.phpTags) html = html.replace(/([\w\W]*?)<\/section>/gi, '');
+
+ return html;
+ },
+ cleanRemoveSpaces: function(html, buffer)
+ {
+ if (buffer !== false)
+ {
+ var buffer = []
+ var matches = html.match(/<(pre|style|script|title)(.*?)>([\w\W]*?)<\/(pre|style|script|title)>/gi);
+ if (matches === null) matches = [];
+
+ if (this.opts.phpTags)
{
- return X(m1, '\\\\([\'\"\\\\])', '$1') + X(X(X(m3, '', '\n'), '
| ', ''), '\\\\([\'\"\\\\])', '$1') + '';
+ var phpMatches = html.match(/<\?php([\w\W]*?)\?>/gi);
+ if (phpMatches) matches = $.merge(matches, phpMatches);
+ }
+
+ if (matches)
+ {
+ $.each(matches, function(i, s)
+ {
+ html = html.replace(s, 'buffer_' + i);
+ buffer.push(s);
+ });
+ }
+ }
+
+ html = html.replace(/\n/g, ' ');
+ html = html.replace(/[\t]*/g, '');
+ html = html.replace(/\n\s*\n/g, "\n");
+ html = html.replace(/^[\s\n]*/g, ' ');
+ html = html.replace(/[\s\n]*$/g, ' ');
+ html = html.replace( />\s{2,} <'); // between inline tags can be only one space
+
+ html = this.cleanReplacer(html, buffer);
+
+ html = html.replace(/\n\n/g, "\n");
+
+ return html;
+ },
+ cleanReplacer: function(html, buffer)
+ {
+ if (buffer === false) return html;
+
+ $.each(buffer, function(i,s)
+ {
+ html = html.replace('buffer_' + i, s);
+ });
+
+ return html;
+ },
+ cleanRemoveEmptyTags: function(html)
+ {
+ // remove zero width-space
+ html = html.replace(/[\u200B-\u200D\uFEFF]/g, '');
+
+ var etagsInline = ["\\s* ", " ", "\\s* "]
+ var etags = [" ", "\\s* ", " ", " ", "", " ", " ", "", " ", "\\s*", " ", "\\s*
", "
", "
", "\\s* \\s*
", "\\s*
", "\\s* \\s*
"];
+
+ if (this.opts.removeEmptyTags)
+ {
+ etags = etags.concat(etagsInline);
+ }
+ else etags = etagsInline;
+
+ var len = etags.length;
+ for (var i = 0; i < len; ++i)
+ {
+ html = html.replace(new RegExp(etags[i], 'gi'), "");
+ }
+
+ return html;
+ },
+ cleanParagraphy: function(html)
+ {
+ html = $.trim(html);
+
+ if (this.opts.linebreaks === true) return html;
+ if (html === '' || html === '
') return this.opts.emptyHtml;
+
+ html = html + "\n";
+
+ if (this.opts.removeEmptyTags === false)
+ {
+ return html;
+ }
+
+ var safes = [];
+ var matches = html.match(/<(table|div|pre|object)(.*?)>([\w\W]*?)<\/(table|div|pre|object)>/gi);
+ if (!matches) matches = [];
+
+ var commentsMatches = html.match(//gi);
+ if (commentsMatches) matches = $.merge(matches, commentsMatches);
+
+ if (this.opts.phpTags)
+ {
+ var phpMatches = html.match(/([\w\W]*?)<\/section>/gi);
+ if (phpMatches) matches = $.merge(matches, phpMatches);
+ }
+
+ if (matches)
+ {
+ $.each(matches, function(i,s)
+ {
+ safes[i] = s;
+ html = html.replace(s, '{replace' + i + '}\n');
});
}
- return R('\n$', '');
- },
+ html = html.replace(/ \s* /gi, "\n\n");
+ html = html.replace(/ /gi, "\n\n");
- // REMOVE TAGS
- stripTags: function(html)
- {
- var allowed = this.opts.allowedTags;
- var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
- return html.replace(tags, function ($0, $1)
+ function R(str, mod, r)
{
- return $.inArray($1.toLowerCase(), allowed) > '-1' ? $0 : '';
+ return html.replace(new RegExp(str, mod), r);
+ }
+
+ var blocks = '(comment|html|body|head|title|meta|style|script|link|iframe|table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)';
+
+ html = R('(<' + blocks + '[^>]*>)', 'gi', "\n$1");
+ html = R('(' + blocks + '>)', 'gi', "$1\n\n");
+ html = R("\r\n", 'g', "\n");
+ html = R("\r", 'g', "\n");
+ html = R("/\n\n+/", 'g', "\n\n");
+
+ var htmls = html.split(new RegExp('\n\s*\n', 'g'), -1);
+
+ html = '';
+ for (var i in htmls)
+ {
+ if (htmls.hasOwnProperty(i))
+ {
+ if (htmls[i].search('{replace') == -1)
+ {
+ htmls[i] = htmls[i].replace(/\n\t?<\/p>/gi, '');
+ htmls[i] = htmls[i].replace(/
<\/p>/gi, '');
+
+ if (htmls[i] != '')
+ {
+ html += '
' + htmls[i].replace(/^\n+|\n+$/g, "") + "
";
+ }
+ }
+ else html += htmls[i];
+ }
+ }
+
+ html = R('
', 'gi', '
');
+ html = R('
', 'gi', '');
+
+ html = R('\s?
', 'gi', '');
+
+ html = R('([^<]+)(div|address|form)>', 'gi', "
$1
$2>");
+
+ html = R('(?' + blocks + '[^>]*>)
', 'gi', "$1");
+ html = R("(
", 'gi', "$1");
+ html = R('\s?(?' + blocks + '[^>]*>)', 'gi', "$1");
+
+ html = R('(?' + blocks + '[^>]*>)\s?
', 'gi', "$1");
+ html = R('(?' + blocks + '[^>]*>)\s? ', 'gi', "$1");
+ html = R(' (\s*?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)', 'gi', '$1');
+ html = R("\n", 'gi', '');
+
+ html = R('', 'gi', '
');
+ html = R(' ', 'gi', '');
+ html = R('', 'gi', '');
+ //html = R('
(.*?)', 'gi', '');
+ // html = R('
', 'gi', '');
+ html = R('
\t?\n?
', 'gi', '
');
+ html = R('
', 'gi', '');
+ html = R('
', 'gi', '');
+ html = R('
', 'gi', '');
+ html = R('\t*
', 'gi', '');
+
+ // restore safes
+ $.each(safes, function(i,s)
+ {
+ html = html.replace('{replace' + i + '}', s);
});
+
+ return $.trim(html);
},
-
-
- savePreCode: function(html)
+ cleanConvertInlineTags: function(html, set)
{
- var pre = html.match(/([\w\W]*?)<\/pre>/gi);
+ var boldTag = 'strong';
+ if (this.opts.boldTag === 'b') boldTag = 'b';
+
+ var italicTag = 'em';
+ if (this.opts.italicTag === 'i') italicTag = 'i';
+
+ html = html.replace(/([\w\W]*?)<\/span>/gi, '<' + italicTag + '>$1' + italicTag + '>');
+ html = html.replace(/([\w\W]*?)<\/span>/gi, '<' + boldTag + '>$1' + boldTag + '>');
+
+ // bold, italic, del
+ if (this.opts.boldTag === 'strong') html = html.replace(/([\w\W]*?)<\/b>/gi, '$1 ');
+ else html = html.replace(/([\w\W]*?)<\/strong>/gi, '$1 ');
+
+ if (this.opts.italicTag === 'em') html = html.replace(/([\w\W]*?)<\/i>/gi, '$1 ');
+ else html = html.replace(/([\w\W]*?)<\/em>/gi, '$1 ');
+
+ html = html.replace(/([\w\W]*?)<\/span>/gi, '$1 ');
+
+ if (set !== true) html = html.replace(/([\w\W]*?)<\/strike>/gi, '$1');
+ else html = html.replace(/([\w\W]*?)<\/del>/gi, '$1 ');
+
+ return html;
+ },
+ cleanStripTags: function(html)
+ {
+ if (html == '' || typeof html == 'undefined') return html;
+
+ var allowed = false;
+ if (this.opts.allowedTags !== false) allowed = true;
+
+ var arr = allowed === true ? this.opts.allowedTags : this.opts.deniedTags;
+
+ var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
+ html = html.replace(tags, function ($0, $1)
+ {
+ if (allowed === true) return $.inArray($1.toLowerCase(), arr) > '-1' ? $0 : '';
+ else return $.inArray($1.toLowerCase(), arr) > '-1' ? '' : $0;
+ });
+
+ html = this.cleanConvertInlineTags(html);
+
+ return html;
+
+ },
+ cleanSavePreCode: function(html, encode)
+ {
+ var pre = html.match(/<(pre|code)(.*?)>([\w\W]*?)<\/(pre|code)>/gi);
if (pre !== null)
{
$.each(pre, $.proxy(function(i,s)
{
- var arr = s.match(/([\w\W]*?)<\/pre>/i);
- arr[2] = this.encodeEntities(arr[2]);
- html = html.replace(s, '' + arr[2] + ' ');
+ var arr = s.match(/<(pre|code)(.*?)>([\w\W]*?)<\/(pre|code)>/i);
+
+ arr[3] = arr[3].replace(/ /g, ' ');
+
+ if (encode !== false) arr[3] = this.cleanEncodeEntities(arr[3]);
+
+ // $ fix
+ arr[3] = arr[3].replace(/\$/g, '$');
+
+ html = html.replace(s, '<' + arr[1] + arr[2] + '>' + arr[3] + '' + arr[1] + '>');
+
}, this));
}
return html;
},
- encodeEntities: function(str)
+ cleanEncodeEntities: function(str)
{
str = String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
- return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+ return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
},
- cleanupPre: function(s)
+ cleanUnverified: function()
{
- s = s.replace(/ /gi, '\n');
- s = s.replace(/<\/p>/gi, '\n');
- s = s.replace(/<\/div>/gi, '\n');
+ // label, abbr, mark, meter, code, q, dfn, ins, time, kbd, var
+ var $elem = this.$editor.find('li, img, a, b, strong, sub, sup, i, em, u, small, strike, del, span, cite');
- var tmp = this.document.createElement("div");
- tmp.innerHTML = s;
- return tmp.textContent||tmp.innerText;
+ $elem.filter('[style*="background-color: transparent;"][style*="line-height"]')
+ .css('background-color', '')
+ .css('line-height', '');
- },
+ $elem.filter('[style*="background-color: transparent;"]')
+ .css('background-color', '');
+ $elem.css('line-height', '');
- // PASTE CLEANUP
- pasteCleanUp: function(html)
- {
- var parent = this.getParentNode();
-
- // clean up pre
- if ($(parent).get(0).tagName === 'PRE')
+ $.each($elem, $.proxy(function(i,s)
{
- html = this.cleanupPre(html);
- this.pasteCleanUpInsert(html);
+ this.removeEmptyAttr(s, 'style');
+ }, this));
+
+ var $elem2 = this.$editor.find('b, strong, i, em, u, strike, del');
+ $elem2.css('font-size', '');
+
+ $.each($elem2, $.proxy(function(i,s)
+ {
+ this.removeEmptyAttr(s, 'style');
+ }, this));
+
+ // When we paste text in Safari is wrapping inserted div (remove it)
+ this.$editor.find('div[style="text-align: -webkit-auto;"]').contents().unwrap();
+
+ // Remove all styles in ul, ol, li
+ this.$editor.find('ul, ol, li').removeAttr('style');
+ },
+
+
+ // TEXTAREA CODE FORMATTING
+ cleanHtml: function(code)
+ {
+ var i = 0,
+ codeLength = code.length,
+ point = 0,
+ start = null,
+ end = null,
+ tag = '',
+ out = '',
+ cont = '';
+
+ this.cleanlevel = 0;
+
+ for (; i < codeLength; i++)
+ {
+ point = i;
+
+ // if no more tags, copy and exit
+ if (-1 == code.substr(i).indexOf( '<' ))
+ {
+ out += code.substr(i);
+
+ return this.cleanFinish(out);
+ }
+
+ // copy verbatim until a tag
+ while (point < codeLength && code.charAt(point) != '<')
+ {
+ point++;
+ }
+
+ if (i != point)
+ {
+ cont = code.substr(i, point - i);
+ if (!cont.match(/^\s{2,}$/g))
+ {
+ if ('\n' == out.charAt(out.length - 1)) out += this.cleanGetTabs();
+ else if ('\n' == cont.charAt(0))
+ {
+ out += '\n' + this.cleanGetTabs();
+ cont = cont.replace(/^\s+/, '');
+ }
+
+ out += cont;
+ }
+
+ if (cont.match(/\n/)) out += '\n' + this.cleanGetTabs();
+ }
+
+ start = point;
+
+ // find the end of the tag
+ while (point < codeLength && '>' != code.charAt(point))
+ {
+ point++;
+ }
+
+ tag = code.substr(start, point - start);
+ i = point;
+
+ var t;
+
+ if ('!--' == tag.substr(1, 3))
+ {
+ if (!tag.match(/--$/))
+ {
+ while ('-->' != code.substr(point, 3))
+ {
+ point++;
+ }
+ point += 2;
+ tag = code.substr(start, point - start);
+ i = point;
+ }
+
+ if ('\n' != out.charAt(out.length - 1)) out += '\n';
+
+ out += this.cleanGetTabs();
+ out += tag + '>\n';
+ }
+ else if ('!' == tag[1])
+ {
+ out = this.placeTag(tag + '>', out);
+ }
+ else if ('?' == tag[1])
+ {
+ out += tag + '>\n';
+ }
+ else if (t = tag.match(/^<(script|style|pre)/i))
+ {
+ t[1] = t[1].toLowerCase();
+ tag = this.cleanTag(tag);
+ out = this.placeTag(tag, out);
+ end = String(code.substr(i + 1)).toLowerCase().indexOf('' + t[1]);
+
+ if (end)
+ {
+ cont = code.substr(i + 1, end);
+ i += end;
+ out += cont;
+ }
+ }
+ else
+ {
+ tag = this.cleanTag(tag);
+ out = this.placeTag(tag, out);
+ }
+ }
+
+ return this.cleanFinish(out);
+ },
+ cleanGetTabs: function()
+ {
+ var s = '';
+ for ( var j = 0; j < this.cleanlevel; j++ )
+ {
+ s += '\t';
+ }
+
+ return s;
+ },
+ cleanFinish: function(code)
+ {
+ code = code.replace(/\n\s*\n/g, '\n');
+ code = code.replace(/^[\s\n]*/, '');
+ code = code.replace(/[\s\n]*$/, '');
+ code = code.replace(/');
+
+ this.cleanlevel = 0;
+
+ return code;
+ },
+ cleanTag: function (tag)
+ {
+ var tagout = '';
+ tag = tag.replace(/\n/g, ' ');
+ tag = tag.replace(/\s{2,}/g, ' ');
+ tag = tag.replace(/^\s+|\s+$/g, ' ');
+
+ var suffix = '';
+ if (tag.match(/\/$/))
+ {
+ suffix = '/';
+ tag = tag.replace(/\/+$/, '');
+ }
+
+ var m;
+ while (m = /\s*([^= ]+)(?:=((['"']).*?\3|[^ ]+))?/.exec(tag))
+ {
+ if (m[2]) tagout += m[1].toLowerCase() + '=' + m[2];
+ else if (m[1]) tagout += m[1].toLowerCase();
+
+ tagout += ' ';
+ tag = tag.substr(m[0].length);
+ }
+
+ return tagout.replace(/\s*$/, '') + suffix + '>';
+ },
+ placeTag: function (tag, out)
+ {
+ var nl = tag.match(this.cleannewLevel);
+ if (tag.match(this.cleanlineBefore) || nl)
+ {
+ out = out.replace(/\s*$/, '');
+ out += '\n';
+ }
+
+ if (nl && '/' == tag.charAt(1)) this.cleanlevel--;
+ if ('\n' == out.charAt(out.length - 1)) out += this.cleanGetTabs();
+ if (nl && '/' != tag.charAt(1)) this.cleanlevel++;
+
+ out += tag;
+
+ if (tag.match(this.cleanlineAfter) || tag.match(this.cleannewLevel))
+ {
+ out = out.replace(/ *$/, '');
+ out += '\n';
+ }
+
+ return out;
+ },
+
+ // FORMAT
+ formatEmpty: function(e)
+ {
+ var html = $.trim(this.$editor.html());
+
+ if (this.opts.linebreaks)
+ {
+ if (html == '')
+ {
+ e.preventDefault();
+ this.$editor.html('');
+ this.focus();
+ }
+ }
+ else
+ {
+ html = html.replace(/ /i, '');
+ var thtml = html.replace(/\s?<\/p>/gi, '');
+
+ if (html === '' || thtml === '')
+ {
+ e.preventDefault();
+
+ var node = $(this.opts.emptyHtml).get(0);
+ this.$editor.html(node);
+ this.focus();
+ }
+ }
+
+ this.sync();
+ },
+ formatBlocks: function(tag)
+ {
+ if (this.browser('mozilla') && this.isFocused())
+ {
+ this.$editor.focus();
+ }
+
+ this.bufferSet();
+
+ var nodes = this.getBlocks();
+ this.selectionSave();
+
+ $.each(nodes, $.proxy(function(i, node)
+ {
+ if (node.tagName !== 'LI')
+ {
+ var parent = $(node).parent();
+
+ if (tag === 'p')
+ {
+ if ((node.tagName === 'P'
+ && parent.size() != 0
+ && parent[0].tagName === 'BLOCKQUOTE')
+ ||
+ node.tagName === 'BLOCKQUOTE')
+ {
+ this.formatQuote();
+ return;
+ }
+ else if (this.opts.linebreaks)
+ {
+ if (node && node.tagName.search(/H[1-6]/) == 0)
+ {
+ $(node).replaceWith(node.innerHTML + ' ');
+ }
+ else return;
+ }
+ else
+ {
+ this.formatBlock(tag, node);
+ }
+ }
+ else
+ {
+ this.formatBlock(tag, node);
+ }
+ }
+
+ }, this));
+
+ this.selectionRestore();
+ this.sync();
+ },
+ formatBlock: function(tag, block)
+ {
+ if (block === false) block = this.getBlock();
+ if (block === false && this.opts.linebreaks === true)
+ {
+ this.execCommand('formatblock', tag);
return true;
}
+ var contents = '';
+ if (tag !== 'pre')
+ {
+ contents = $(block).contents();
+ }
+ else
+ {
+ //contents = this.cleanEncodeEntities($(block).text());
+ contents = $(block).html();
+ if ($.trim(contents) === '')
+ {
+ contents = ' ';
+ }
+ }
+
+ if (block.tagName === 'PRE') tag = 'p';
+
+ if (this.opts.linebreaks === true && tag === 'p')
+ {
+ $(block).replaceWith($('
').append(contents).html() + '
');
+ }
+ else
+ {
+ var parent = this.getParent();
+
+ var node = $('<' + tag + '>').append(contents);
+ $(block).replaceWith(node);
+
+ if (parent && parent.tagName == 'TD')
+ {
+ $(node).wrapAll('
');
+ }
+ }
+ },
+ formatChangeTag: function(fromElement, toTagName, save)
+ {
+ if (save !== false) this.selectionSave();
+
+ var newElement = $('<' + toTagName + '/>');
+ $(fromElement).replaceWith(function() { return newElement.append($(this).contents()); });
+
+ if (save !== false) this.selectionRestore();
+
+ return newElement;
+ },
+
+ // QUOTE
+ formatQuote: function()
+ {
+ if (this.browser('mozilla') && this.isFocused())
+ {
+ this.$editor.focus();
+ }
+
+ this.bufferSet();
+
+ // paragraphy
+ if (this.opts.linebreaks === false)
+ {
+ this.selectionSave();
+
+ var blocks = this.getBlocks();
+
+ var blockquote = false;
+ var blocksLen = blocks.length;
+ if (blocks)
+ {
+ var data = '';
+ var replaced = '';
+ var replace = false;
+ var paragraphsOnly = true;
+
+ $.each(blocks, function(i,s)
+ {
+ if (s.tagName !== 'P') paragraphsOnly = false;
+ });
+
+ $.each(blocks, $.proxy(function(i,s)
+ {
+ if (s.tagName === 'BLOCKQUOTE')
+ {
+ this.formatBlock('p', s, false);
+ }
+ else if (s.tagName === 'P')
+ {
+ blockquote = $(s).parent();
+ // from blockquote
+ if (blockquote[0].tagName == 'BLOCKQUOTE')
+ {
+ var count = $(blockquote).children('p').size();
+
+ // one
+ if (count == 1)
+ {
+ $(blockquote).replaceWith(s);
+ }
+ // all
+ else if (count == blocksLen)
+ {
+ replace = 'blockquote';
+ data += this.outerHtml(s);
+ }
+ // some
+ else
+ {
+ replace = 'html';
+ data += this.outerHtml(s);
+
+ if (i == 0)
+ {
+ $(s).addClass('redactor-replaced').empty();
+ replaced = this.outerHtml(s);
+ }
+ else $(s).remove();
+ }
+ }
+ // to blockquote
+ else
+ {
+ if (paragraphsOnly === false || blocks.length == 1)
+ {
+ this.formatBlock('blockquote', s, false);
+ }
+ else
+ {
+ replace = 'paragraphs';
+ data += this.outerHtml(s);
+ }
+ }
+
+ }
+ else if (s.tagName !== 'LI')
+ {
+ this.formatBlock('blockquote', s, false);
+ }
+
+ }, this));
+
+ if (replace)
+ {
+ if (replace == 'paragraphs')
+ {
+ $(blocks[0]).replaceWith('' + data + ' ');
+ $(blocks).remove();
+ }
+ else if (replace == 'blockquote')
+ {
+ $(blockquote).replaceWith(data);
+ }
+ else if (replace == 'html')
+ {
+ var html = this.$editor.html().replace(replaced, '' + data + '');
+
+ this.$editor.html(html);
+ this.$editor.find('blockquote').each(function()
+ {
+ if ($.trim($(this).html()) == '') $(this).remove();
+ })
+ }
+ }
+ }
+
+ this.selectionRestore();
+ }
+ // linebreaks
+ else
+ {
+ var block = this.getBlock();
+ if (block.tagName === 'BLOCKQUOTE')
+ {
+ this.selectionSave();
+
+ var html = $.trim($(block).html());
+ var selection = $.trim(this.getSelectionHtml());
+
+ html = html.replace(//gi, '');
+
+ if (html == selection)
+ {
+ $(block).replaceWith($(block).html() + ' ');
+ }
+ else
+ {
+ // replace
+ this.inlineFormat('tmp');
+ var tmp = this.$editor.find('tmp');
+ tmp.empty();
+
+ var newhtml = this.$editor.html().replace(' ', ' ' + this.opts.invisibleSpace + ' ' + selection + '');
+
+ this.$editor.html(newhtml);
+ tmp.remove();
+ this.$editor.find('blockquote').each(function()
+ {
+ if ($.trim($(this).html()) == '') $(this).remove();
+ })
+ }
+
+ this.selectionRestore();
+ this.$editor.find('span#selection-marker-1').attr('id', false);
+ }
+ else
+ {
+ var wrapper = this.selectionWrap('blockquote');
+ var html = $(wrapper).html();
+
+ var blocksElemsRemove = ['ul', 'ol', 'table', 'tr', 'tbody', 'thead', 'tfoot', 'dl'];
+ $.each(blocksElemsRemove, function(i,s)
+ {
+ html = html.replace(new RegExp('<' + s + '(.*?)>', 'gi'), '');
+ html = html.replace(new RegExp('' + s + '>', 'gi'), '');
+ });
+
+ var blocksElems = this.opts.blockLevelElements;
+ $.each(blocksElems, function(i,s)
+ {
+ html = html.replace(new RegExp('<' + s + '(.*?)>', 'gi'), '');
+ html = html.replace(new RegExp('' + s + '>', 'gi'), ' ');
+ });
+
+ $(wrapper).html(html);
+ this.selectionElement(wrapper);
+ var next = $(wrapper).next();
+ if (next.size() != 0 && next[0].tagName === 'BR')
+ {
+ next.remove();
+ }
+ }
+ }
+
+ this.sync();
+ },
+
+ // BLOCK
+ blockRemoveAttr: function(attr, value)
+ {
+ var nodes = this.getBlocks();
+ $(nodes).removeAttr(attr);
+
+ this.sync();
+ },
+ blockSetAttr: function(attr, value)
+ {
+ var nodes = this.getBlocks();
+ $(nodes).attr(attr, value);
+
+ this.sync();
+ },
+ blockRemoveStyle: function(rule)
+ {
+ var nodes = this.getBlocks();
+ $(nodes).css(rule, '');
+ this.removeEmptyAttr(nodes, 'style');
+
+ this.sync();
+ },
+ blockSetStyle: function (rule, value)
+ {
+ var nodes = this.getBlocks();
+ $(nodes).css(rule, value);
+
+ this.sync();
+ },
+ blockRemoveClass: function(className)
+ {
+ var nodes = this.getBlocks();
+ $(nodes).removeClass(className);
+ this.removeEmptyAttr(nodes, 'class');
+
+ this.sync();
+ },
+ blockSetClass: function(className)
+ {
+ var nodes = this.getBlocks();
+ $(nodes).addClass(className);
+
+ this.sync();
+ },
+
+ // INLINE
+ inlineRemoveClass: function(className)
+ {
+ this.selectionSave();
+
+ this.inlineEachNodes(function(node)
+ {
+ $(node).removeClass(className);
+ this.removeEmptyAttr(node, 'class');
+ });
+
+ this.selectionRestore();
+ this.sync();
+ },
+ inlineSetClass: function(className)
+ {
+ var current = this.getCurrent();
+ if (!$(current).hasClass(className)) this.inlineMethods('addClass', className);
+ },
+ inlineRemoveStyle: function (rule)
+ {
+ this.selectionSave();
+
+ this.inlineEachNodes(function(node)
+ {
+ $(node).css(rule, '');
+ this.removeEmptyAttr(node, 'style');
+ });
+
+ this.selectionRestore();
+ this.sync();
+ },
+ inlineSetStyle: function(rule, value)
+ {
+ this.inlineMethods('css', rule, value);
+ },
+ inlineRemoveAttr: function (attr)
+ {
+ this.selectionSave();
+
+ var range = this.getRange(), node = this.getElement(), nodes = this.getNodes();
+
+ if (range.collapsed || range.startContainer === range.endContainer && node)
+ {
+ nodes = $( node );
+ }
+
+ $(nodes).removeAttr(attr);
+
+ this.inlineUnwrapSpan();
+
+ this.selectionRestore();
+ this.sync();
+ },
+ inlineSetAttr: function(attr, value)
+ {
+ this.inlineMethods('attr', attr, value );
+ },
+ inlineMethods: function(type, attr, value)
+ {
+ this.bufferSet();
+ this.selectionSave();
+
+ var range = this.getRange()
+ var el = this.getElement();
+
+ if ((range.collapsed || range.startContainer === range.endContainer) && el && !this.nodeTestBlocks(el))
+ {
+ $(el)[type](attr, value);
+ }
+ else
+ {
+ this.document.execCommand('fontSize', false, 4 );
+
+ var fonts = this.$editor.find('font');
+ $.each(fonts, $.proxy(function(i, s)
+ {
+ this.inlineSetMethods(type, s, attr, value);
+
+ }, this));
+
+ }
+
+ this.selectionRestore();
+ this.sync();
+ },
+ inlineSetMethods: function(type, s, attr, value)
+ {
+ var parent = $(s).parent(), el;
+
+ var selectionHtml = this.getSelectionText();
+ var parentHtml = $(parent).text();
+ var selected = selectionHtml == parentHtml;
+
+ if (selected && parent && parent[0].tagName === 'INLINE' && parent[0].attributes.length != 0)
+ {
+ el = parent;
+ $(s).replaceWith($(s).html());
+ }
+ else
+ {
+ el = $('').append($(s).contents());
+ $(s).replaceWith(el);
+ }
+
+
+ $(el)[type](attr, value);
+
+ return el;
+ },
+ // Sort elements and execute callback
+ inlineEachNodes: function(callback)
+ {
+ var range = this.getRange(),
+ node = this.getElement(),
+ nodes = this.getNodes(),
+ collapsed;
+
+ if (range.collapsed || range.startContainer === range.endContainer && node)
+ {
+ nodes = $(node);
+ collapsed = true;
+ }
+
+ $.each(nodes, $.proxy(function(i, node)
+ {
+ if (!collapsed && node.tagName !== 'INLINE')
+ {
+ var selectionHtml = this.getSelectionText();
+ var parentHtml = $(node).parent().text();
+ var selected = selectionHtml == parentHtml;
+
+ if (selected && node.parentNode.tagName === 'INLINE' && !$(node.parentNode).hasClass('redactor_editor'))
+ {
+ node = node.parentNode;
+ }
+ else return;
+ }
+ callback.call(this, node);
+
+ }, this ) );
+ },
+ inlineUnwrapSpan: function()
+ {
+ var $spans = this.$editor.find('inline');
+
+ $.each($spans, $.proxy(function(i, span)
+ {
+ var $span = $(span);
+
+ if ($span.attr('class') === undefined && $span.attr('style') === undefined)
+ {
+ $span.contents().unwrap();
+ }
+
+ }, this));
+ },
+ inlineFormat: function(tag)
+ {
+ this.selectionSave();
+
+ this.document.execCommand('fontSize', false, 4 );
+
+ var fonts = this.$editor.find('font');
+ var last;
+ $.each(fonts, function(i, s)
+ {
+ var el = $('<' + tag + '/>').append($(s).contents());
+ $(s).replaceWith(el);
+ last = el;
+ });
+
+ this.selectionRestore();
+
+ this.sync();
+ },
+ inlineRemoveFormat: function(tag)
+ {
+ this.selectionSave();
+
+ var utag = tag.toUpperCase();
+ var nodes = this.getNodes();
+ var parent = $(this.getParent()).parent();
+
+ $.each(nodes, function(i, s)
+ {
+ if (s.tagName === utag) this.inlineRemoveFormatReplace(s);
+ });
+
+ if (parent && parent[0].tagName === utag) this.inlineRemoveFormatReplace(parent);
+
+ this.selectionRestore();
+ this.sync();
+ },
+ inlineRemoveFormatReplace: function(el)
+ {
+ $(el).replaceWith($(el).contents());
+ },
+
+
+ // INSERT
+ insertHtml: function (html, sync)
+ {
+ var current = this.getCurrent();
+ var parent = current.parentNode;
+
+ this.focusWithSaveScroll();
+
+ this.bufferSet();
+
+ var $html = $('').append($.parseHTML(html));
+ html = $html.html();
+
+ html = this.cleanRemoveEmptyTags(html);
+
+ // Update value
+ $html = $('
').append($.parseHTML(html));
+ var currBlock = this.getBlock();
+
+ if ($html.contents().length == 1)
+ {
+ var htmlTagName = $html.contents()[0].tagName;
+
+ // If the inserted and received text tags match
+ if (htmlTagName != 'P' && htmlTagName == currBlock.tagName || htmlTagName == 'PRE')
+ {
+ //html = $html.html();
+ $html = $('
').append(html);
+ }
+ }
+
+ if (this.opts.linebreaks)
+ {
+ html = html.replace(/
([\w\W]*?)<\/p>/gi, '$2 ');
+ }
+
+ // add text in a paragraph
+ if (!this.opts.linebreaks && $html.contents().length == 1 && $html.contents()[0].nodeType == 3
+ && (this.getRangeSelectedNodes().length > 2 || (!current || current.tagName == 'BODY' && !parent || parent.tagName == 'HTML')))
+ {
+ html = '
' + html + '
';
+ }
+
+ html = this.setSpansVerifiedHtml(html);
+
+ if ($html.contents().length > 1 && currBlock
+ || $html.contents().is('p, :header, ul, ol, li, div, table, td, blockquote, pre, address, section, header, footer, aside, article'))
+ {
+ if (this.browser('msie'))
+ {
+ if (!this.isIe11())
+ {
+ this.document.selection.createRange().pasteHTML(html);
+ }
+ else
+ {
+ this.execPasteFrag(html);
+ }
+ }
+ else
+ {
+ this.document.execCommand('inserthtml', false, html);
+ }
+ }
+ else this.insertHtmlAdvanced(html, false);
+
+ if (this.selectall)
+ {
+ this.window.setTimeout($.proxy(function()
+ {
+ if (!this.opts.linebreaks) this.selectionEnd(this.$editor.contents().last());
+ else this.focusEnd();
+
+ }, this), 1);
+ }
+
+ this.observeStart();
+
+ // set no editable
+ this.setNonEditable();
+
+ if (sync !== false) this.sync();
+ },
+ insertHtmlAdvanced: function(html, sync)
+ {
+ html = this.setSpansVerifiedHtml(html);
+
+ var sel = this.getSelection();
+
+ if (sel.getRangeAt && sel.rangeCount)
+ {
+ var range = sel.getRangeAt(0);
+ range.deleteContents();
+
+ var el = this.document.createElement('div');
+ el.innerHTML = html;
+ var frag = this.document.createDocumentFragment(), node, lastNode;
+ while ((node = el.firstChild))
+ {
+ lastNode = frag.appendChild(node);
+ }
+
+ range.insertNode(frag);
+
+ if (lastNode)
+ {
+ range = range.cloneRange();
+ range.setStartAfter(lastNode);
+ range.collapse(true);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+
+ if (sync !== false)
+ {
+ this.sync();
+ }
+
+ },
+ insertBeforeCursor: function(html)
+ {
+ html = this.setSpansVerifiedHtml(html);
+
+ var node = $(html);
+
+ var space = document.createElement("span");
+ space.innerHTML = "\u200B";
+
+ var range = this.getRange();
+ range.insertNode(space);
+ range.insertNode(node[0]);
+ range.collapse(false);
+
+ var sel = this.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+
+ this.sync();
+ },
+ insertText: function(html)
+ {
+ var $html = $($.parseHTML(html));
+
+ if ($html.length) html = $html.text();
+
+ this.focusWithSaveScroll();
+
+ if (this.browser('msie'))
+ {
+ if (!this.isIe11())
+ {
+ this.document.selection.createRange().pasteHTML(html);
+ }
+ else
+ {
+ this.execPasteFrag(html);
+ }
+ }
+ else
+ {
+ this.document.execCommand('inserthtml', false, html);
+ }
+
+ this.sync();
+ },
+ insertNode: function(node)
+ {
+ node = node[0] || node;
+
+ if (node.tagName == 'SPAN')
+ {
+ var replacementTag = 'inline';
+
+ var outer = node.outerHTML;
+
+ // Replace opening tag
+ var regex = new RegExp('<' + node.tagName, 'i');
+ var newTag = outer.replace(regex, '<' + replacementTag);
+
+ // Replace closing tag
+ regex = new RegExp('' + node.tagName, 'i');
+ newTag = newTag.replace(regex, '' + replacementTag);
+ node = $(newTag)[0];
+ }
+
+ var sel = this.getSelection();
+ if (sel.getRangeAt && sel.rangeCount)
+ {
+ // with delete contents
+ range = sel.getRangeAt(0);
+ range.deleteContents();
+ range.insertNode(node);
+ range.setEndAfter(node);
+ range.setStartAfter(node);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+
+ return node;
+ },
+ insertNodeToCaretPositionFromPoint: function(e, node)
+ {
+ var range;
+ var x = e.clientX, y = e.clientY;
+ if (this.document.caretPositionFromPoint)
+ {
+ var pos = this.document.caretPositionFromPoint(x, y);
+ range = this.getRange();
+ range.setStart(pos.offsetNode, pos.offset);
+ range.collapse(true);
+ range.insertNode(node);
+ }
+ else if (this.document.caretRangeFromPoint)
+ {
+ range = this.document.caretRangeFromPoint(x, y);
+ range.insertNode(node);
+ }
+ else if (typeof document.body.createTextRange != "undefined")
+ {
+ range = this.document.body.createTextRange();
+ range.moveToPoint(x, y);
+ var endRange = range.duplicate();
+ endRange.moveToPoint(x, y);
+ range.setEndPoint("EndToEnd", endRange);
+ range.select();
+ }
+
+ },
+ insertAfterLastElement: function(element, parent)
+ {
+ if (typeof(parent) != 'undefined') element = parent;
+
+ if (this.isEndOfElement())
+ {
+ if (this.opts.linebreaks)
+ {
+ var contents = $('
').append($.trim(this.$editor.html())).contents();
+ var last = contents.last()[0];
+ if (last.tagName == 'SPAN' && last.innerHTML == '')
+ {
+ last = contents.prev()[0];
+ }
+
+ if (this.outerHtml(last) != this.outerHtml(element))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (this.$editor.contents().last()[0] !== element)
+ {
+ return false;
+ }
+ }
+
+ this.insertingAfterLastElement(element);
+ }
+ },
+ insertingAfterLastElement: function(element)
+ {
+ this.bufferSet();
+
+ if (this.opts.linebreaks === false)
+ {
+ var node = $(this.opts.emptyHtml);
+ $(element).after(node);
+ this.selectionStart(node);
+ }
+ else
+ {
+ var node = $('
' + this.opts.invisibleSpace + ' ', this.document)[0];
+ $(element).after(node);
+ $(node).after(this.opts.invisibleSpace);
+ this.selectionRestore();
+ this.$editor.find('span#selection-marker-1').removeAttr('id');
+ }
+ },
+ insertLineBreak: function(twice)
+ {
+ this.selectionSave();
+
+ var br = '
';
+ if (twice == true)
+ {
+ br = '
';
+ }
+
+ if (this.browser('mozilla'))
+ {
+ var span = $('
').html(this.opts.invisibleSpace);
+ this.$editor.find('#selection-marker-1').before(br).before(span).before(this.opts.invisibleSpace);
+
+ this.setCaretAfter(span[0]);
+ span.remove();
+
+ this.selectionRemoveMarkers();
+ }
+ else
+ {
+ var parent = this.getParent();
+ if (parent && parent.tagName === 'A')
+ {
+ var offset = this.getCaretOffset(parent);
+
+ var text = $.trim($(parent).text()).replace(/\n\r\n/g, '');
+ var len = text.length;
+
+ if (offset == len)
+ {
+ this.selectionRemoveMarkers();
+
+ var node = $('' + this.opts.invisibleSpace + ' ', this.document)[0];
+ $(parent).after(node);
+ $(node).before(br + (this.browser('webkit') ? this.opts.invisibleSpace : ''));
+ this.selectionRestore();
+
+ return true;
+ }
+
+ }
+
+ this.$editor.find('#selection-marker-1').before(br + (this.browser('webkit') ? this.opts.invisibleSpace : ''));
+ this.selectionRestore();
+ }
+ },
+ insertDoubleLineBreak: function()
+ {
+ this.insertLineBreak(true);
+ },
+ replaceLineBreak: function(element)
+ {
+ var node = $(' ' + this.opts.invisibleSpace);
+ $(element).replaceWith(node);
+ this.selectionStart(node);
+ },
+
+ // PASTE
+ pasteClean: function(html)
+ {
+ html = this.callback('pasteBefore', false, html);
+
+ // ie10 fix paste links
+ if (this.browser('msie'))
+ {
+ var tmp = $.trim(html);
+ if (tmp.search(/^(.*?)<\/a>$/i) == 0)
+ {
+ html = html.replace(/^ (.*?)<\/a>$/i, "$2");
+ }
+ }
+
+ if (this.opts.pastePlainText)
+ {
+ var tmp = this.document.createElement('div');
+
+ html = html.replace(/ |<\/H[1-6]>|<\/p>|<\/div>/gi, '\n');
+
+ tmp.innerHTML = html;
+ html = tmp.textContent || tmp.innerText;
+
+ html = $.trim(html);
+ html = html.replace('\n', ' ');
+ html = this.cleanParagraphy(html);
+
+ this.pasteInsert(html);
+ return false;
+ }
+
+ // clean up table
+ var tablePaste = false;
+ if (this.currentOrParentIs('TD'))
+ {
+ tablePaste = true;
+ var blocksElems = this.opts.blockLevelElements;
+ blocksElems.push('tr');
+ blocksElems.push('table');
+ $.each(blocksElems, function(i,s)
+ {
+ html = html.replace(new RegExp('<' + s + '(.*?)>', 'gi'), '');
+ html = html.replace(new RegExp('' + s + '>', 'gi'), ' ');
+ });
+ }
+
+ // clean up pre
+ if (this.currentOrParentIs('PRE'))
+ {
+ html = this.pastePre(html);
+ this.pasteInsert(html);
+ return true;
+ }
+
+ // ms words shapes
+ html = html.replace(/ /gi, '');
+
+ // ms word list
+ html = html.replace(//gi, '
');
+ html = html.replace(//gi, '
');
+ html = html.replace(//gi, '
');
+ // one line
+ html = html.replace(//gi, '
');
+ // remove ms word's bullet
+ html = html.replace(/·/g, '');
+
// remove comments and php tags
html = html.replace(/|<\?(?:php)?[\s\S]*?\?>/gi, '');
// remove nbsp
- html = html.replace(/( ){2,}/gi, ' ');
+ if (this.opts.cleanSpaces === true)
+ {
+ html = html.replace(/( ){2,}/gi, ' ');
+ html = html.replace(/ /gi, ' ');
+ }
// remove google docs marker
html = html.replace(/([\w\W]*?)<\/b>/gi, "$2");
+ html = html.replace(/([\w\W]*?)<\/b>/gi, "$3");
+
+
+ html = html.replace(/]*(font-style: italic; font-weight: bold|font-weight: bold; font-style: italic)[^>]*>/gi, '');
+ html = html.replace(/]*font-style: italic[^>]*>/gi, '');
+ html = html.replace(/]*font-weight: bold[^>]*>/gi, '');
+ html = html.replace(/]*text-decoration: underline[^>]*>/gi, '');
// strip tags
- html = this.stripTags(html);
+ //html = this.cleanStripTags(html);
+
+
// prevert
- html = html.replace(/ <\/td>/gi, '[td]');
+ html = html.replace(/ \u200b*<\/td>/gi, '[td]');
html = html.replace(/ <\/td>/gi, '[td]');
html = html.replace(/ <\/td>/gi, '[td]');
+ html = html.replace(/([\w\W]*?)<\/td>/gi, '[td colspan="$2"]$4[/td]');
+ html = html.replace(/ ([\w\W]*?)<\/td>/gi, '[td rowspan="$2"]$4[/td]');
html = html.replace(/([\w\W]*?)<\/a>/gi, '[a href="$2"]$4[/a]');
html = html.replace(/ ', '', ''];
- for (var i = 0; i < atags.length; ++i)
- {
- var aaa = atags[i];
- html = html.replace(new RegExp(aaa,'gi'),aaa+lb);
- }
-
- return html;
- },
- formatting: function(html)
- {
- html = this.formattingRemove(html);
-
- // empty tags
- html = this.formattingEmptyTags(html);
-
- // add formatting before
- html = this.formattingAddBefore(html);
-
- // add formatting after
- html = this.formattingAddAfter(html);
-
- // indenting
- html = this.formattingIndenting(html);
-
- return html;
- },
-
- // TOGGLE
- toggle: function()
- {
- var html;
-
- if (this.opts.visual)
- {
- var height = this.$editor.innerHeight();
-
- this.$editor.hide();
- this.$content.hide();
-
- html = this.$editor.html();
- //html = $.trim(this.formatting(html));
-
- this.$el.height(height).val(html).show().focus();
-
- this.setBtnActive('html');
- this.opts.visual = false;
- }
- else
- {
- this.$el.hide();
- var html = this.$el.val();
-
- //html = this.savePreCode(html);
-
- // clean up
- //html = this.stripTags(html);
-
- // set code
- this.$editor.html(html).show();
- this.$content.show();
-
- if (this.$editor.html() === '')
- {
- this.setCode(this.opts.emptyHtml);
- }
-
- this.$editor.focus();
-
- this.setBtnInactive('html');
- this.opts.visual = true;
-
- this.observeImages();
- this.observeTables();
- }
- },
-
- // AUTOSAVE
- autoSave: function()
- {
- this.autosaveInterval = setInterval($.proxy(function()
- {
- $.ajax({
- url: this.opts.autosave,
- type: 'post',
- data: this.$el.attr('name') + '=' + escape(encodeURIComponent(this.getCode())),
- success: $.proxy(function(data)
- {
- // callback
- if (typeof this.opts.autosaveCallback === 'function')
- {
- this.opts.autosaveCallback(data, this);
- }
-
- }, this)
- });
-
-
- }, this), this.opts.interval*1000);
- },
-
- // TOOLBAR
- buildToolbar: function()
- {
- if (this.opts.toolbar === false)
- {
- return false;
- }
-
- this.$toolbar = $('
').addClass('redactor_toolbar');
-
- if (this.opts.air)
- {
- $(this.air).append(this.$toolbar);
- $('body').append(this.air);
- }
- else
- {
- if (this.opts.toolbarExternal === false)
- {
- this.$box.prepend(this.$toolbar);
- }
- else
- {
- $(this.opts.toolbarExternal).html(this.$toolbar);
- }
- }
-
- $.each(this.opts.buttons, $.proxy(function(i,key)
- {
-
- if (key !== '|' && typeof this.opts.toolbar[key] !== 'undefined')
- {
- var s = this.opts.toolbar[key];
-
- if (this.opts.fileUpload === false && key === 'file')
- {
- return true;
- }
-
- this.$toolbar.append($('').append(this.buildButton(key, s)));
- }
-
-
- if (key === '|')
- {
- this.$toolbar.append($(' '));
- }
-
- }, this));
-
- },
- buildButton: function(key, s)
- {
- var button = $(' ');
-
- if (typeof s.func === 'undefined')
- {
- button.click($.proxy(function()
- {
- if ($.inArray(key, this.opts.activeButtons) != -1)
- {
- this.inactiveAllButtons();
- this.setBtnActive(key);
- }
-
- if (this.browser('mozilla'))
- {
- this.$editor.focus();
- //this.restoreSelection();
- }
-
- this.execCommand(s.exec, key);
-
- }, this));
- }
- else if (s.func !== 'show')
- {
- button.click($.proxy(function(e) {
-
- this[s.func](e);
+ if (v != null && v.toString().indexOf('#') === 0) v = $(v).val();
+ postData[k] = v;
}, this));
}
- if (typeof s.callback !== 'undefined' && s.callback !== false)
+ return postData;
+ },
+ pasteClipboardUploadMozilla: function()
+ {
+ var imgs = this.$editor.find('img[data-mozilla-paste-image]');
+ $.each(imgs, $.proxy(function(i,s)
{
- button.click($.proxy(function(e) { s.callback(this, e, key); }, this));
- }
+ var $s = $(s);
+ var arr = s.src.split(",");
+ var postData = {
+ 'contentType': arr[0].split(";")[0].split(":")[1],
+ 'data': arr[1] // raw base64
+ };
- // dropdown
- if (key === 'backcolor' || key === 'fontcolor' || typeof(s.dropdown) !== 'undefined')
- {
- var dropdown = $('');
+ // append hidden fields
+ postData = this.pasteClipboardAppendFields(postData);
- if (key === 'backcolor' || key === 'fontcolor')
+ $.post(this.opts.clipboardUploadUrl, postData,
+ $.proxy(function(data)
{
- dropdown = this.buildColorPicker(dropdown, key);
- }
- else
- {
- dropdown = this.buildDropdown(dropdown, s.dropdown);
- }
+ var json = (typeof data === 'string' ? $.parseJSON(data) : data);
+ $s.attr('src', json.filelink);
+ $s.removeAttr('data-mozilla-paste-image');
- this.dropdowns.push(dropdown.appendTo($(document.body)));
+ this.sync();
- // observing dropdown
- this.hdlShowDropDown = $.proxy(function(e) { this.showDropDown(e, dropdown, key); }, this);
+ // upload callback
+ this.callback('imageUpload', $s, json);
- button.click(this.hdlShowDropDown);
- }
-
- return button;
- },
- buildDropdown: function(dropdown, obj)
- {
- $.each(obj, $.proxy(
- function (x, d)
- {
- if (typeof(d.className) === 'undefined')
- {
- d.className = '';
- }
-
- var drop_a;
- if (typeof d.name !== 'undefined' && d.name === 'separator')
- {
- drop_a = $('
');
- }
- else
- {
- drop_a = $(' ' + d.title + ' ');
-
- if (typeof(d.callback) === 'function')
- {
- $(drop_a).click($.proxy(function(e) { d.callback(this, e, x); }, this));
- }
- else 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 (this.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()
- {
- _self.execCommand(mode, $(this).attr('rel'));
-
- if (mode === 'forecolor')
- {
- _self.$editor.find('font').replaceWith(function() {
-
- return $('
' + $(this).html() + ' ');
-
- });
- }
-
- if (_self.browser('msie') && mode === 'BackColor')
- {
- _self.$editor.find('font').replaceWith(function() {
-
- return $('
' + $(this).html() + ' ');
-
- });
- }
-
- });
- }
-
- 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)
- {
- if (this.getBtn(key).hasClass('dropact'))
- {
- this.hideAllDropDown();
- }
- else
- {
- this.hideAllDropDown();
-
- this.setBtnActive(key);
- this.getBtn(key).addClass('dropact');
-
- var left = this.getBtn(key).offset().left;
-
- if (this.opts.air)
- {
- var air_top = this.air.offset().top;
-
- $(dropdown).css({ position: 'absolute', left: left + 'px', top: air_top+30 + 'px' }).show();
- }
- else 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();
- }
- }
-
- var hdlHideDropDown = $.proxy(function(e) { this.hideDropDown(e, dropdown, key); }, this);
-
- $(document).one('click', hdlHideDropDown);
- this.$editor.one('click', hdlHideDropDown);
- this.$content.one('click', hdlHideDropDown);
-
- e.stopPropagation();
-
- },
- hideAllDropDown: function()
- {
- this.$toolbar.find('a.dropact').removeClass('redactor_act').removeClass('dropact');
- $('.redactor_dropdown').hide();
- },
- hideDropDown: function(e, dropdown, key)
- {
- if (!$(e.target).hasClass('dropact'))
- {
- $(dropdown).removeClass('dropact');
- this.showedDropDown = false;
- this.hideAllDropDown();
- }
- },
-
- // BUTTONS MANIPULATIONS
- getBtn: function(key)
- {
- if (this.opts.toolbar === false)
- {
- return false;
- }
-
- return $(this.$toolbar.find('a.redactor_btn_' + key));
- },
- setBtnActive: function(key)
- {
- this.getBtn(key).addClass('redactor_act');
- },
- setBtnInactive: function(key)
- {
- this.getBtn(key).removeClass('redactor_act');
- },
- inactiveAllButtons: function()
- {
- $.each(this.opts.activeButtons, $.proxy(function(i,s)
- {
- this.setBtnInactive(s);
+ }, this));
}, this));
},
- changeBtnIcon: function(key, classname)
+ pasteClipboardUpload: function(e)
{
- this.getBtn(key).addClass('redactor_btn_' + classname);
- },
- removeBtnIcon: function(key, classname)
- {
- this.getBtn(key).removeClass('redactor_btn_' + classname);
- },
+ var result = e.target.result;
+ var arr = result.split(",");
+ var postData = {
+ 'contentType': arr[0].split(";")[0].split(":")[1],
+ 'data': arr[1] // raw base64
+ };
- addBtnSeparator: function()
- {
- this.$toolbar.append($('
'));
- },
- addBtnSeparatorAfter: function(key)
- {
- var $btn = this.getBtn(key);
- $btn.parent().after($('
'));
- },
- addBtnSeparatorBefore: function(key)
- {
- var $btn = this.getBtn(key);
- $btn.parent().before($('
'));
- },
- removeBtnSeparatorAfter: function(key)
- {
- var $btn = this.getBtn(key);
- $btn.parent().next().remove();
- },
- removeBtnSeparatorBefore: function(key)
- {
- var $btn = this.getBtn(key);
- $btn.parent().prev().remove();
- },
- setBtnRight: function(key)
- {
- if (this.opts.toolbar === false)
+ if (this.opts.clipboardUpload)
{
+ // append hidden fields
+ postData = this.pasteClipboardAppendFields(postData);
+
+ $.post(this.opts.clipboardUploadUrl, postData,
+ $.proxy(function(data)
+ {
+ var json = (typeof data === 'string' ? $.parseJSON(data) : data);
+
+ var html = '
';
+ this.execCommand('inserthtml', html, false);
+
+ var image = $(this.$editor.find('img#clipboard-image-marker'));
+
+ if (image.length) image.removeAttr('id');
+ else image = false;
+
+ this.sync();
+
+ // upload callback
+ if (image)
+ {
+ this.callback('imageUpload', image, json);
+ }
+
+
+ }, this));
+ }
+ else
+ {
+ this.insertHtml('
');
+ }
+ },
+
+ // BUFFER
+ bufferSet: function(selectionSave)
+ {
+ if (selectionSave !== false)
+ {
+ this.selectionSave();
+ }
+
+ this.opts.buffer.push(this.$editor.html());
+
+ if (selectionSave !== false)
+ {
+ this.selectionRemoveMarkers('buffer');
+ }
+
+ },
+ bufferUndo: function()
+ {
+ if (this.opts.buffer.length === 0)
+ {
+ this.focusWithSaveScroll();
+ return;
+ }
+
+ // rebuffer
+ this.selectionSave();
+ this.opts.rebuffer.push(this.$editor.html());
+ this.selectionRestore(false, true);
+
+ this.$editor.html(this.opts.buffer.pop());
+
+ this.selectionRestore();
+ setTimeout($.proxy(this.observeStart, this), 100);
+ },
+ bufferRedo: function()
+ {
+ if (this.opts.rebuffer.length === 0)
+ {
+ this.focusWithSaveScroll();
return false;
}
- this.getBtn(key).parent().addClass('redactor_btn_right');
+ // buffer
+ this.selectionSave();
+ this.opts.buffer.push(this.$editor.html());
+ this.selectionRestore(false, true);
+
+ this.$editor.html(this.opts.rebuffer.pop());
+ this.selectionRestore(true);
+ setTimeout($.proxy(this.observeStart, this), 4);
},
- setBtnLeft: function(key)
+
+ // OBSERVE
+ observeStart: function()
{
- if (this.opts.toolbar === false)
+ this.observeImages();
+
+ if (this.opts.observeLinks) this.observeLinks();
+ },
+ observeLinks: function()
+ {
+ this.$editor.find('a').on('click', $.proxy(this.linkObserver, this));
+
+ this.$editor.on('click.redactor', $.proxy(function(e)
{
- return false;
+ this.linkObserverTooltipClose(e);
+
+ }, this));
+
+ $(document).on('click.redactor', $.proxy(function(e)
+ {
+ this.linkObserverTooltipClose(e);
+
+ }, this));
+ },
+ observeImages: function()
+ {
+ if (this.opts.observeImages === false) return false;
+
+ this.$editor.find('img').each($.proxy(function(i, elem)
+ {
+ if (this.browser('msie')) $(elem).attr('unselectable', 'on');
+
+ var parent = $(elem).parent();
+ if (!parent.hasClass('royalSlider') && !parent.hasClass('fotorama'))
+ {
+ this.imageResize(elem);
+ }
+
+ }, this));
+
+ // royalSlider and fotorama
+ this.$editor.find('.fotorama, .royalSlider').on('click', $.proxy(this.editGallery, this));
+
+ },
+ linkObserver: function(e)
+ {
+ var $link = $(e.target);
+
+ var parent = $(e.target).parent();
+ if (parent.hasClass('royalSlider') || parent.hasClass('fotorama'))
+ {
+ return;
}
- this.getBtn(key).parent().removeClass('redactor_btn_right');
- },
- addBtn: function(key, title, callback, dropdown)
- {
- if (this.opts.toolbar === false)
+ if ($link.size() == 0 || $link[0].tagName !== 'A') return;
+
+ var pos = $link.offset();
+ if (this.opts.iframe)
{
- return false;
+ var posFrame = this.$frame.offset();
+ pos.top = posFrame.top + (pos.top - $(this.document).scrollTop());
+ pos.left += posFrame.left;
}
- var btn = this.buildButton(key, { title: title, callback: callback, dropdown: dropdown });
- this.$toolbar.append($('
').append(btn));
- },
- addBtnFirst: function(key, title, callback, dropdown)
- {
- if (this.opts.toolbar === false)
+ var tooltip = $(' ');
+
+ var href = $link.attr('href');
+ if (href === undefined)
{
- return false;
+ href = '';
}
- var btn = this.buildButton(key, { title: title, callback: callback, dropdown: dropdown });
- this.$toolbar.prepend($(' ').append(btn));
- },
- addBtnAfter: function(afterkey, key, title, callback, dropdown)
- {
- if (this.opts.toolbar === false)
+ if (href.length > 24) href = href.substring(0, 24) + '...';
+
+ var aLink = $('' + href + ' ').on('click', $.proxy(function(e)
{
- return false;
+ this.linkObserverTooltipClose(false);
+ }, this));
+
+ var aEdit = $('' + this.opts.curLang.edit + ' ').on('click', $.proxy(function(e)
+ {
+ e.preventDefault();
+ this.linkShow();
+ this.linkObserverTooltipClose(false);
+
+ }, this));
+
+ var aUnlink = $('' + this.opts.curLang.unlink + ' ').on('click', $.proxy(function(e)
+ {
+ e.preventDefault();
+ this.execCommand('unlink');
+ this.linkObserverTooltipClose(false);
+
+ }, this));
+
+
+ tooltip.append(aLink);
+ tooltip.append(' | ');
+ tooltip.append(aEdit);
+ tooltip.append(' | ');
+ tooltip.append(aUnlink);
+ tooltip.css({
+ top: (pos.top + 20) + 'px',
+ left: pos.left + 'px'
+ });
+
+ $('.redactor-link-tooltip').remove();
+ $('body').append(tooltip);
+ },
+ linkObserverTooltipClose: function(e)
+ {
+ if (e !== false && e.target.tagName == 'A') return false;
+ $('.redactor-link-tooltip').remove();
+ },
+
+ // SELECTION
+ getSelection: function()
+ {
+ if (!this.opts.rangy) return this.document.getSelection();
+ else // rangy
+ {
+ if (!this.opts.iframe) return rangy.getSelection();
+ else return rangy.getSelection(this.$frame[0]);
+ }
+ },
+ getRange: function()
+ {
+ if (!this.opts.rangy)
+ {
+ if (this.document.getSelection)
+ {
+ var sel = this.getSelection();
+ if (sel.getRangeAt && sel.rangeCount) return sel.getRangeAt(0);
+ }
+
+ return this.document.createRange();
+ }
+ else // rangy
+ {
+ if (!this.opts.iframe) return rangy.createRange();
+ else return rangy.createRange(this.iframeDoc());
+ }
+ },
+ selectionElement: function(node)
+ {
+ this.setCaret(node);
+ },
+ selectionStart: function(node)
+ {
+ this.selectionSet(node[0] || node, 0, null, 0);
+ },
+ selectionEnd: function(node)
+ {
+ this.selectionSet(node[0] || node, 1, null, 1);
+ },
+ selectionSet: function(orgn, orgo, focn, foco)
+ {
+ if (focn == null) focn = orgn;
+ if (foco == null) foco = orgo;
+
+ var sel = this.getSelection();
+ if (!sel) return;
+
+ if (orgn.tagName == 'P' && orgn.innerHTML == '')
+ {
+ orgn.innerHTML = this.opts.invisibleSpace;
}
- var btn = this.buildButton(key, { title: title, callback: callback, dropdown: dropdown });
- var $btn = this.getBtn(afterkey);
- $btn.parent().after($(' ').append(btn));
- },
- addBtnBefore: function(beforekey, key, title, callback, dropdown)
- {
- if (this.opts.toolbar === false)
+ if (orgn.tagName == 'BR' && this.opts.linebreaks === false)
{
- return false;
+ var par = $(this.opts.emptyHtml)[0];
+ $(orgn).replaceWith(par);
+ orgn = par;
+ focn = orgn;
}
- var btn = this.buildButton(key, { title: title, callback: callback, dropdown: dropdown });
- var $btn = this.getBtn(beforekey);
- $btn.parent().before($(' ').append(btn));
- },
- removeBtn: function(key, separator)
- {
- var $btn = this.getBtn(key);
+ var range = this.getRange();
+ range.setStart(orgn, orgo);
+ range.setEnd(focn, foco );
- if (separator === true)
+ try {
+ sel.removeAllRanges();
+ } catch (e) {}
+
+ sel.addRange(range);
+ },
+ selectionWrap: function(tag)
+ {
+ tag = tag.toLowerCase();
+
+ var block = this.getBlock();
+ if (block)
{
- $btn.parent().next().remove();
+ var wrapper = this.formatChangeTag(block, tag);
+ this.sync();
+ return wrapper;
}
- $btn.parent().removeClass('redactor_btn_right');
- $btn.remove();
- },
+ var sel = this.getSelection();
+ var range = sel.getRangeAt(0);
+ var wrapper = document.createElement(tag);
+ wrapper.appendChild(range.extractContents());
+ range.insertNode(wrapper);
+ this.selectionElement(wrapper);
- // SELECTION AND NODE MANIPULATION
- getFragmentHtml: function (fragment)
- {
- var cloned = fragment.cloneNode(true);
- var div = this.document.createElement('div');
- div.appendChild(cloned);
- return div.innerHTML;
+ return wrapper;
},
- extractContent: function()
+ selectionAll: function()
{
- var node = this.$editor.get(0);
- var frag = this.document.createDocumentFragment(), child;
- while ((child = node.firstChild))
+ var range = this.getRange();
+ range.selectNodeContents(this.$editor[0]);
+
+ var sel = this.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ },
+ selectionRemove: function()
+ {
+ this.getSelection().removeAllRanges();
+ },
+ getCaretOffset: function (element)
+ {
+ var caretOffset = 0;
+
+ var range = this.getRange();
+ var preCaretRange = range.cloneRange();
+ preCaretRange.selectNodeContents(element);
+ preCaretRange.setEnd(range.endContainer, range.endOffset);
+ caretOffset = $.trim(preCaretRange.toString()).length;
+
+ return caretOffset;
+ },
+ getCaretOffsetRange: function()
+ {
+ return new Range(this.getSelection().getRangeAt(0));
+ },
+ setCaret: function (el, start, end)
+ {
+ if (typeof end === 'undefined') end = start;
+ el = el[0] || el;
+
+ var range = this.getRange();
+ range.selectNodeContents(el);
+
+ var textNodes = this.getTextNodesIn(el);
+ var foundStart = false;
+ var charCount = 0, endCharCount;
+
+ if (textNodes.length == 1 && start)
{
- frag.appendChild(child);
+ range.setStart(textNodes[0], start);
+ range.setEnd(textNodes[0], end);
+ }
+ else
+ {
+ for (var i = 0, textNode; textNode = textNodes[i++];)
+ {
+ endCharCount = charCount + textNode.length;
+ if (!foundStart && start >= charCount && (start < endCharCount || (start == endCharCount && i < textNodes.length)))
+ {
+ range.setStart(textNode, start - charCount);
+ foundStart = true;
+ }
+
+ if (foundStart && end <= endCharCount)
+ {
+ range.setEnd( textNode, end - charCount );
+ break;
+ }
+
+ charCount = endCharCount;
+ }
}
- return frag;
+ var sel = this.getSelection();
+ sel.removeAllRanges();
+ sel.addRange( range );
},
-
- // Save and Restore Selection
- saveSelection: function()
+ setCaretAfter: function(node)
{
this.$editor.focus();
- this.savedSel = this.getOrigin();
- this.savedSelObj = this.getFocus();
+ node = node[0] || node;
+
+ var range = this.document.createRange()
+
+ var start = 1;
+ var end = -1;
+
+ range.setStart(node, start)
+ range.setEnd(node, end + 2)
+
+
+ var selection = this.window.getSelection()
+ var cursorRange = this.document.createRange()
+
+ var emptyElement = this.document.createTextNode('\u200B')
+ $(node).after(emptyElement)
+
+ cursorRange.setStartAfter(emptyElement)
+
+ selection.removeAllRanges()
+ selection.addRange(cursorRange)
+ $(emptyElement).remove();
},
- restoreSelection: function()
+ getTextNodesIn: function (node)
{
- if (typeof this.savedSel !== 'undefined' && this.savedSel !== null && this.savedSelObj !== null && this.savedSel[0].tagName !== 'BODY')
- {
- if (this.opts.iframe === false && $(this.savedSel[0]).closest('.redactor_editor').size() == 0)
- {
- this.$editor.focus();
- }
- else
- {
- if (this.browser('opera'))
- {
- this.$editor.focus();
- }
+ var textNodes = [];
- this.setSelection(this.savedSel[0], this.savedSel[1], this.savedSelObj[0], this.savedSelObj[1]);
-
- if (this.browser('mozilla'))
- {
- this.$editor.focus();
- }
- }
- }
+ if (node.nodeType == 3) textNodes.push(node);
else
{
- this.$editor.focus();
+ var children = node.childNodes;
+ for (var i = 0, len = children.length; i < len; ++i)
+ {
+ textNodes.push.apply(textNodes, this.getTextNodesIn(children[i]));
+ }
}
+
+ return textNodes;
},
- // Selection
- getSelection: function()
+ // GET ELEMENTS
+ getCurrent: function()
{
- var doc = this.document;
+ var el = false;
+ var sel = this.getSelection();
- if (this.window.getSelection)
+ if (sel && sel.rangeCount > 0)
{
- return this.window.getSelection();
+ el = sel.getRangeAt(0).startContainer;
+ //el = sel.getRangeAt(0).commonAncestorContainer;
}
- else if (doc.getSelection)
+
+ return this.isParentRedactor(el);
+ },
+ getParent: function(elem)
+ {
+ elem = elem || this.getCurrent();
+ if (elem) return this.isParentRedactor( $( elem ).parent()[0] );
+ else return false;
+ },
+ getBlock: function(node)
+ {
+ if (typeof node === 'undefined') node = this.getCurrent();
+
+ while (node)
{
- return doc.getSelection();
- }
- else // IE
- {
- return doc.selection.createRange();
+ if (this.nodeTestBlocks(node))
+ {
+ if ($(node).hasClass('redactor_editor')) return false;
+ return node;
+ }
+
+ node = node.parentNode;
}
return false;
},
- hasSelection: function()
+ getBlocks: function(nodes)
{
- if (!this.oldIE())
+ var newnodes = [];
+ if (typeof nodes == 'undefined')
{
- var sel;
- return (sel = this.getSelection()) && (sel.focusNode != null) && (sel.anchorNode != null);
+ var range = this.getRange();
+ if (range && range.collapsed === true) return [this.getBlock()];
+ var nodes = this.getNodes(range);
}
- else // IE8
+
+ $.each(nodes, $.proxy(function(i,node)
{
- var node = this.$editor.get(0);
+ if (this.opts.iframe === false && $(node).parents('div.redactor_editor').size() == 0) return false;
+ if (this.nodeTestBlocks(node)) newnodes.push(node);
- var range;
- node.focus();
- if (!node.document.selection)
- {
- return false;
- }
+ }, this));
- range = node.document.selection.createRange();
- return range && range.parentElement().document === node.document;
- }
+ if (newnodes.length === 0) newnodes = [this.getBlock()];
+
+ return newnodes;
},
- getOrigin: function()
+ isInlineNode: function(node)
{
- if (!this.oldIE())
- {
- var sel;
- if (!((sel = this.getSelection()) && (sel.anchorNode != null)))
- {
- return null;
- }
+ if (node.nodeType != 1) return false;
- return [sel.anchorNode, sel.anchorOffset];
- }
- else
- {
- var node = this.$editor.get(0);
-
- var range;
- node.focus();
- if (!this.hasSelection())
- {
- return null;
- }
-
- range = node.document.selection.createRange();
- return this._getBoundary(node.document, range, true);
- }
+ return !this.rTestBlock.test(node.nodeName);
},
- getFocus: function()
+ nodeTestBlocks: function(node)
{
- if (!this.oldIE())
- {
- var sel;
- if (!((sel = this.getSelection()) && (sel.focusNode != null)))
- {
- return null;
- }
-
- return [sel.focusNode, sel.focusOffset];
- }
- else
- {
- var node = this.$editor.get(0);
-
- var range;
- node.focus();
- if (!this.hasSelection())
- {
- return null;
- }
-
- range = node.document.selection.createRange();
- return this._getBoundary(node.document, range, false);
-
- }
+ return node.nodeType == 1 && this.rTestBlock.test(node.nodeName);
},
- setSelection: function (orgn, orgo, focn, foco)
+ tagTestBlock: function(tag)
{
- if (focn == null)
- {
- focn = orgn;
- }
-
- if (foco == null)
- {
- foco = orgo;
- }
-
- if (!this.oldIE())
- {
- var sel = this.getSelection();
- if (!sel)
- {
- return;
- }
-
- if (sel.collapse && sel.extend)
- {
- sel.collapse(orgn, orgo);
- sel.extend(focn, foco);
- }
- else // IE9
- {
- r = this.document.createRange();
- r.setStart(orgn, orgo);
- r.setEnd(focn, foco);
-
- try
- {
- sel.removeAllRanges();
- }
- catch (e) {}
-
- sel.addRange(r);
- }
- }
- else
- {
- var node = this.$editor.get(0);
- var range = node.document.body.createTextRange();
-
- this._moveBoundary(node.document, range, false, focn, foco);
- this._moveBoundary(node.document, range, true, orgn, orgo);
- return range.select();
- }
+ return this.rTestBlock.test(tag);
},
-
- // Get elements, html and text
- getCurrentNode: function()
+ getNodes: function(range, tag)
{
- if (typeof this.window.getSelection !== 'undefined')
+ if (typeof range == 'undefined' || range == false) var range = this.getRange();
+ if (range && range.collapsed === true)
{
- return this.getSelectedNode().parentNode;
- }
- else if (typeof this.document.selection !== 'undefined')
- {
- return this.getSelection().parentElement();
- }
- },
- getParentNode: function()
- {
- return $(this.getCurrentNode()).parent()[0]
- },
- getSelectedNode: function()
- {
- if (this.oldIE())
- {
- return this.getSelection().parentElement();
- }
- else if (typeof this.window.getSelection !== 'undefined')
- {
- var s = this.window.getSelection();
- if (s.rangeCount > 0)
+ if (typeof tag === 'undefined' && this.tagTestBlock(tag))
{
- return this.getSelection().getRangeAt(0).commonAncestorContainer;
+ var block = this.getBlock();
+ if (block.tagName == tag) return [block];
+ else return [];
}
else
{
- return false;
+ return [this.getCurrent()];
}
}
- else if (typeof this.document.selection !== 'undefined')
+
+ var nodes = [], finalnodes = [];
+
+ var sel = this.document.getSelection();
+ if (!sel.isCollapsed) nodes = this.getRangeSelectedNodes(sel.getRangeAt(0));
+
+ $.each(nodes, $.proxy(function(i,node)
{
- return this.getSelection();
+ if (this.opts.iframe === false && $(node).parents('div.redactor_editor').size() == 0) return false;
+
+ if (typeof tag === 'undefined')
+ {
+ if ($.trim(node.textContent) != '')
+ {
+ finalnodes.push(node);
+ }
+ }
+ else if (node.tagName == tag)
+ {
+ finalnodes.push(node);
+ }
+
+ }, this));
+
+ if (finalnodes.length == 0)
+ {
+ if (typeof tag === 'undefined' && this.tagTestBlock(tag))
+ {
+ var block = this.getBlock();
+ if (block.tagName == tag) return finalnodes.push(block);
+ else return [];
+ }
+ else
+ {
+ finalnodes.push(this.getCurrent());
+ }
+ }
+
+ // last element filtering
+ var last = finalnodes[finalnodes.length-1];
+ if (this.nodeTestBlocks(last))
+ {
+ finalnodes = finalnodes.slice(0, -1);
+ }
+
+ return finalnodes;
+ },
+ getElement: function(node)
+ {
+ if (!node) node = this.getCurrent();
+ while (node)
+ {
+ if (node.nodeType == 1)
+ {
+ if ($(node).hasClass('redactor_editor')) return false;
+ return node;
+ }
+
+ node = node.parentNode;
+ }
+
+ return false;
+ },
+ getRangeSelectedNodes: function(range)
+ {
+ range = range || this.getRange();
+ var node = range.startContainer;
+ var endNode = range.endContainer;
+
+ if (node == endNode) return [node];
+
+ var rangeNodes = [];
+ while (node && node != endNode)
+ {
+ rangeNodes.push(node = this.nextNode(node));
+ }
+
+ node = range.startContainer;
+ while (node && node != range.commonAncestorContainer)
+ {
+ rangeNodes.unshift(node);
+ node = node.parentNode;
+ }
+
+ return rangeNodes;
+ },
+ nextNode: function(node)
+ {
+ if (node.hasChildNodes()) return node.firstChild;
+ else
+ {
+ while (node && !node.nextSibling)
+ {
+ node = node.parentNode;
+ }
+
+ if (!node) return null;
+ return node.nextSibling;
}
},
-
- // IE8 specific selection
- _getBoundary: function(doc, textRange, bStart)
+ // GET SELECTION HTML OR TEXT
+ getSelectionText: function()
{
- var cursor, cursorNode, node, offset, parent;
+ return this.getSelection().toString();
+ },
+ getSelectionHtml: function()
+ {
+ var html = '';
- cursorNode = doc.createElement('a');
- cursor = textRange.duplicate();
- cursor.collapse(bStart);
- parent = cursor.parentElement();
- while (true)
+ var sel = this.getSelection();
+ if (sel.rangeCount)
{
- parent.insertBefore(cursorNode, cursorNode.previousSibling);
- cursor.moveToElementText(cursorNode);
- if (!(cursor.compareEndPoints((bStart ? 'StartToStart' : 'StartToEnd'), textRange) > 0 && (cursorNode.previousSibling != null)))
+ var container = this.document.createElement( "div" );
+ var len = sel.rangeCount;
+ for (var i = 0; i < len; ++i)
{
- break;
+ container.appendChild(sel.getRangeAt(i).cloneContents());
}
+
+ html = container.innerHTML;
}
- if (cursor.compareEndPoints((bStart ? 'StartToStart' : 'StartToEnd'), textRange) === -1 && cursorNode.nextSibling)
+ return this.syncClean(html);
+ },
+
+ // SAVE & RESTORE
+ selectionSave: function()
+ {
+ if (!this.isFocused())
{
- cursor.setEndPoint((bStart ? 'EndToStart' : 'EndToEnd'), textRange);
- node = cursorNode.nextSibling;
- offset = cursor.text.length;
+ this.focusWithSaveScroll();
+ }
+
+ if (!this.opts.rangy)
+ {
+ this.selectionCreateMarker(this.getRange());
+ }
+ // rangy
+ else
+ {
+ this.savedSel = rangy.saveSelection();
+ }
+ },
+ selectionCreateMarker: function(range, remove)
+ {
+ if (!range) return;
+
+ var node1 = $('' + this.opts.invisibleSpace + ' ', this.document)[0];
+ var node2 = $('' + this.opts.invisibleSpace + ' ', this.document)[0];
+
+ if (range.collapsed === true)
+ {
+ this.selectionSetMarker(range, node1, true);
}
else
{
- node = cursorNode.parentNode;
- offset = this._getChildIndex(cursorNode);
+ this.selectionSetMarker(range, node1, true);
+ this.selectionSetMarker(range, node2, false);
}
- cursorNode.parentNode.removeChild(cursorNode);
- return [node, offset];
+ this.savedSel = this.$editor.html();
+
+ this.selectionRestore(false, false);
},
- _moveBoundary: function(doc, textRange, bStart, node, offset)
+ selectionSetMarker: function(range, node, type)
{
- var anchorNode, anchorParent, cursor, cursorNode, textOffset;
+ var boundaryRange = range.cloneRange();
- textOffset = 0;
- anchorNode = this._isText(node) ? node : node.childNodes[offset];
- anchorParent = this._isText(node) ? node.parentNode : node;
-
- if (this._isText(node))
+ try {
+ boundaryRange.collapse(type);
+ boundaryRange.insertNode(node);
+ boundaryRange.detach();
+ }
+ catch (e)
{
- textOffset = offset;
+ var html = this.opts.emptyHtml;
+ if (this.opts.linebreaks) html = ' ';
+
+ this.$editor.prepend(html);
+ this.focus();
}
-
- cursorNode = doc.createElement('a');
- anchorParent.insertBefore(cursorNode, anchorNode || null);
- cursor = doc.body.createTextRange();
- cursor.moveToElementText(cursorNode);
- cursorNode.parentNode.removeChild(cursorNode);
-
- textRange.setEndPoint((bStart ? 'StartToStart' : 'EndToEnd'), cursor);
- return textRange[bStart ? 'moveStart' : 'moveEnd']('character', textOffset);
},
- _isText: function (d)
+ selectionRestore: function(replace, remove)
{
- return (d != null ? d.nodeType == 3 : false);
- },
- _getChildIndex: function (e)
- {
- var k = 0;
- while (e = e.previousSibling) {
- k++;
- }
- return k;
- },
-
- insertNodeAfterCaret: function(node)
- {
- this.saveSelection();
- this.insertNodeAtCaret(node);
- this.restoreSelection();
- },
-
- insertNodeAtCaret: function(node)
- {
- if (this.window.getSelection)
+ if (!this.opts.rangy)
{
- var sel = this.getSelection();
- if (sel.rangeCount)
+ if (replace === true && this.savedSel)
{
- 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);
+ this.$editor.html(this.savedSel);
+ }
+
+ var node1 = this.$editor.find('span#selection-marker-1');
+ var node2 = this.$editor.find('span#selection-marker-2');
+
+ if (this.browser('mozilla'))
+ {
+ this.$editor.focus();
+ }
+ else if (!this.isFocused())
+ {
+ this.focusWithSaveScroll();
+ }
+
+ if (node1.length != 0 && node2.length != 0)
+ {
+ this.selectionSet(node1[0], 0, node2[0], 0);
+ }
+ else if (node1.length != 0)
+ {
+ this.selectionSet(node1[0], 0, null, 0);
+ }
+
+ if (remove !== false)
+ {
+ this.selectionRemoveMarkers();
+ this.savedSel = false;
}
}
- else if (this.document.selection)
+ // rangy
+ else
{
- 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 = this.document.getElementById(id);
- textRange.moveToElementText(markerSpan);
- textRange.select();
- markerSpan.parentNode.removeChild(markerSpan);
+ rangy.restoreSelection(this.savedSel);
}
},
- getSelectedHtml: function()
+ selectionRemoveMarkers: function(type)
{
- var html = '';
- if (this.window.getSelection)
+ if (!this.opts.rangy)
{
- var sel = this.window.getSelection();
- if (sel.rangeCount)
+ $.each(this.$editor.find('span.redactor-selection-marker'), function()
{
- var container = this.document.createElement("div");
- for (var i = 0, len = sel.rangeCount; i < len; ++i)
+ var html = $.trim($(this).html().replace(/[^\u0000-\u1C7F]/g, ''));
+ if (html == '')
{
- container.appendChild(sel.getRangeAt(i).cloneContents());
+ $(this).remove();
}
-
- html = container.innerHTML;
-
- }
- }
- else if (this.document.selection)
- {
- if (this.document.selection.type === "Text")
- {
- html = this.document.selection.createRange().htmlText;
- }
- }
-
- return html;
- },
-
- // RESIZE IMAGES
- resizeImage: function(resize)
- {
- var clicked = false;
- var clicker = false;
- var start_x;
- var start_y;
- var ratio = $(resize).width()/$(resize).height();
- var min_w = 10;
- var min_h = 10;
-
- $(resize).off('hover mousedown mouseup click mousemove');
- $(resize).hover(function() { $(resize).css('cursor', 'nw-resize'); }, function() { $(resize).css('cursor',''); clicked = false; });
-
- $(resize).mousedown(function(e)
- {
- e.preventDefault();
-
- ratio = $(resize).width()/$(resize).height();
-
- 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;
- $(resize).css('cursor','');
- 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, 10) + mouse_y;
- var new_w = new_h*ratio;
-
- if (new_w > min_w)
+ else
{
- $(resize).width(new_w);
+ $(this).removeAttr('class').removeAttr('id');
}
-
- if (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);
- }
- });
+ });
+ }
+ // rangy
+ else
+ {
+ rangy.removeMarkers(this.savedSel);
+ }
},
// TABLE
- showTable: function()
+ tableShow: function()
{
- this.saveSelection();
+ this.selectionSave();
- this.modalInit(RLANG.table, this.opts.modal_table, 300, $.proxy(function()
+ this.modalInit(this.opts.curLang.table, this.opts.modal_table, 300, $.proxy(function()
+ {
+ $('#redactor_insert_table_btn').click($.proxy(this.tableInsert, this));
+
+ setTimeout(function()
{
- $('#redactor_insert_table_btn').click($.proxy(this.insertTable, this));
+ $('#redactor_table_rows').focus();
- setTimeout(function()
+ }, 200);
+
+ }, this));
+ },
+ tableInsert: function()
+ {
+ this.bufferSet(false);
+
+ var rows = $('#redactor_table_rows').val(),
+ columns = $('#redactor_table_columns').val(),
+ $table_box = $('
'),
+ tableId = Math.floor(Math.random() * 99999),
+ $table = $(''),
+ i, $row, z, $column;
+
+ for (i = 0; i < rows; i++)
+ {
+ $row = $(' ');
+
+ for (z = 0; z < columns; z++)
+ {
+ $column = $('' + this.opts.invisibleSpace + ' ');
+
+ // set the focus to the first td
+ if (i === 0 && z === 0)
{
- $('#redactor_table_rows').focus();
- }, 200);
+ $column.append('' + this.opts.invisibleSpace + ' ');
+ }
- }, 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);
+ $($row).append($column);
}
- $(table).append(row);
+
+ $table.append($row);
}
- $(table_box).append(table);
- var html = $(table_box).html() + '
';
+ $table_box.append($table);
+ var html = $table_box.html();
+
+ if (this.opts.linebreaks === false && this.browser('mozilla'))
+ {
+ html += '' + this.opts.invisibleSpace + '
';
+ }
- this.restoreSelection();
- this.execCommand('inserthtml', html);
this.modalClose();
- this.observeTables();
+ this.selectionRestore();
- },
- tableObserver: function(e)
- {
- this.$table = $(e.target).closest('table');
+ var current = this.getBlock() || this.getCurrent();
- this.$table_tr = this.$table.find('tr');
- this.$table_td = this.$table.find('td');
-
- this.$tbody = $(e.target).closest('tbody');
- this.$thead = $(this.$table).find('thead');
-
- this.$current_td = $(e.target);
- this.$current_tr = $(e.target).closest('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()
+ if (current && current.tagName != 'BODY')
{
- $(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_tr.find('td').each($.proxy(function(i,s)
- {
- if ($(s)[0] === this.$current_td[0])
+ if (current.tagName == 'LI')
{
- index = i;
+ var current = $(current).closest('ul, ol');
}
+
+ $(current).after(html)
+ }
+ else
+ {
+ this.insertHtmlAdvanced(html, false);
+ }
+
+ this.selectionRestore();
+
+ var table = this.$editor.find('#table' + tableId);
+ this.buttonActiveObserver();
+
+ table.find('span#selection-marker-1, inline#selection-marker-1').remove();
+ table.removeAttr('id');
+
+ this.sync();
+ },
+ tableDeleteTable: function()
+ {
+ var $table = $(this.getParent()).closest('table');
+ if (!this.isParentRedactor($table)) return false;
+ if ($table.size() == 0) return false;
+
+ this.bufferSet();
+
+ $table.remove();
+ this.sync();
+ },
+ tableDeleteRow: function()
+ {
+ var parent = this.getParent();
+ var $table = $(parent).closest('table');
+
+
+ if (!this.isParentRedactor($table)) return false;
+ if ($table.size() == 0) return false;
+
+ this.bufferSet();
+
+ var $current_tr = $(parent).closest('tr');
+ var $focus_tr = $current_tr.prev().length ? $current_tr.prev() : $current_tr.next();
+ if ($focus_tr.length)
+ {
+ var $focus_td = $focus_tr.children('td' ).first();
+ if ($focus_td.length)
+ {
+ $focus_td.prepend('' + this.opts.invisibleSpace + ' ');
+ }
+ }
+
+ $current_tr.remove();
+ this.selectionRestore();
+ $table.find('span#selection-marker-1').remove();
+ this.sync();
+ },
+ tableDeleteColumn: function()
+ {
+ var parent = this.getParent();
+ var $table = $(parent).closest('table');
+
+ if (!this.isParentRedactor($table)) return false;
+ if ($table.size() == 0) return false;
+
+ this.bufferSet();
+
+ var $current_td = $(parent).closest('td');
+ if (!($current_td.is('td')))
+ {
+ $current_td = $current_td.closest('td');
+ }
+
+ var index = $current_td.get(0).cellIndex;
+
+ // Set the focus correctly
+ $table.find('tr').each($.proxy(function(i, elem)
+ {
+ var focusIndex = index - 1 < 0 ? index + 1 : index - 1;
+ if (i === 0)
+ {
+ $(elem).find('td').eq(focusIndex).prepend('' + this.opts.invisibleSpace + ' ');
+ }
+
+ $(elem).find('td').eq(index).remove();
+
}, this));
- 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();
+ this.selectionRestore();
+ $table.find('span#selection-marker-1').remove();
+ this.sync();
},
-
- // INSERT VIDEO
- showVideo: function()
+ tableAddHead: function()
{
- this.saveSelection();
- this.modalInit(RLANG.video, this.opts.modal_video, 600, $.proxy(function()
- {
- $('#redactor_insert_video_btn').click($.proxy(this.insertVideo, this));
+ var $table = $(this.getParent()).closest('table');
+ if (!this.isParentRedactor($table)) return false;
+ if ($table.size() == 0) return false;
- setTimeout(function()
- {
- $('#redactor_insert_video_area').focus();
- }, 200);
+ this.bufferSet();
- }, this)
- );
+ if ($table.find('thead').size() !== 0) this.tableDeleteHead();
+ else
+ {
+ var tr = $table.find('tr').first().clone();
+ tr.find('td').html(this.opts.invisibleSpace);
+ $thead = $(' ');
+ $thead.append(tr);
+ $table.prepend($thead);
+
+ this.sync();
+ }
},
- insertVideo: function()
+ tableDeleteHead: function()
+ {
+ var $table = $(this.getParent()).closest('table');
+ if (!this.isParentRedactor($table)) return false;
+ var $thead = $table.find('thead');
+
+ if ($thead.size() == 0) return false;
+
+ this.bufferSet();
+
+ $thead.remove();
+ this.sync();
+ },
+ tableAddRowAbove: function()
+ {
+ this.tableAddRow('before');
+ },
+ tableAddRowBelow: function()
+ {
+ this.tableAddRow('after');
+ },
+ tableAddColumnLeft: function()
+ {
+ this.tableAddColumn('before');
+ },
+ tableAddColumnRight: function()
+ {
+ this.tableAddColumn('after');
+ },
+ tableAddRow: function(type)
+ {
+ var $table = $(this.getParent()).closest('table');
+ if (!this.isParentRedactor($table)) return false;
+ if ($table.size() == 0) return false;
+
+ this.bufferSet();
+
+ var $current_tr = $(this.getParent()).closest('tr');
+ var new_tr = $current_tr.clone();
+ new_tr.find('td').html(this.opts.invisibleSpace);
+
+ if (type === 'after') $current_tr.after(new_tr);
+ else $current_tr.before(new_tr);
+
+ this.sync();
+ },
+ tableAddColumn: function (type)
+ {
+ var parent = this.getParent();
+ var $table = $(parent).closest('table');
+
+ if (!this.isParentRedactor($table)) return false;
+ if ($table.size() == 0) return false;
+
+ this.bufferSet();
+
+ var index = 0;
+
+ var current = this.getCurrent();
+ var $current_tr = $(current).closest('tr');
+ var $current_td = $(current).closest('td');
+
+ $current_tr.find('td').each($.proxy(function(i, elem)
+ {
+ if ($(elem)[0] === $current_td[0]) index = i;
+
+ }, this));
+
+ $table.find('tr').each($.proxy(function(i, elem)
+ {
+ var $current = $(elem).find('td').eq(index);
+
+ var td = $current.clone();
+ td.html(this.opts.invisibleSpace);
+
+ type === 'after' ? $current.after(td) : $current.before(td);
+
+ }, this));
+
+ this.sync();
+ },
+
+ // VIDEO
+ videoShow: function()
+ {
+ this.selectionSave();
+
+ this.modalInit(this.opts.curLang.video, this.opts.modal_video, 600, $.proxy(function()
+ {
+ $('#redactor_insert_video_btn').click($.proxy(this.videoInsert, this));
+
+ setTimeout(function()
+ {
+ $('#redactor_insert_video_area').focus();
+
+ }, 200);
+
+ }, this));
+ },
+ videoInsert: function ()
{
var data = $('#redactor_insert_video_area').val();
- data = this.stripTags(data);
+ data = this.cleanStripTags(data);
- this.restoreSelection();
- this.execCommand('inserthtml', data);
+ // parse if it is link on youtube & vimeo
+ var iframeStart = ' ';
+
+ if (data.match(reUrlYoutube))
+ {
+ data = data.replace(reUrlYoutube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
+ }
+ else if (data.match(reUrlVimeo))
+ {
+ data = data.replace(reUrlVimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
+ }
+
+ this.selectionRestore();
+
+ var current = this.getBlock() || this.getCurrent();
+
+ if (current) $(current).after(data)
+ else this.insertHtmlAdvanced(data, false);
+
+ this.sync();
this.modalClose();
},
- // INSERT IMAGE
- imageEdit: function(e)
+
+ // LINK
+ linkShow: function()
{
- var $el = $(e.target);
- var parent = $el.parent();
+ this.selectionSave();
var callback = $.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')
+ // Predefined links
+ if (this.opts.predefinedLinks !== false)
{
- $('#redactor_file_link').val($(parent).attr('href'));
+ this.predefinedLinksStorage = {};
+ var that = this;
+ $.getJSON(this.opts.predefinedLinks, function(data)
+ {
+ var $select = $('#redactor-predefined-links');
+ $select .html('');
+ $.each(data, function(key, val)
+ {
+ that.predefinedLinksStorage[key] = val;
+ $select.append($('').val(key).html(val.name));
+ });
+
+ $select.on('change', function()
+ {
+ var key = $(this).val();
+ var name = '', url = '';
+ if (key != 0)
+ {
+ name = that.predefinedLinksStorage[key].name;
+ url = that.predefinedLinksStorage[key].url;
+ }
+
+ $('#redactor_link_url').val(url);
+ $('#redactor_link_url_text').val(name);
+
+ });
+
+ $select.show();
+ });
}
- $('#redactor_image_delete_btn').click($.proxy(function() { this.imageDelete($el); }, this));
- $('#redactorSaveBtn').click($.proxy(function() { this.imageSave($el); }, this));
+ this.insert_link_node = false;
+
+ var sel = this.getSelection();
+ var url = '', text = '', target = '';
+
+ var elem = this.getParent();
+ var par = $(elem).parent().get(0);
+ if (par && par.tagName === 'A')
+ {
+ elem = par;
+ }
+
+ if (elem && elem.tagName === 'A')
+ {
+ url = elem.href;
+ text = $(elem).text();
+ target = elem.target;
+
+ this.insert_link_node = elem;
+ }
+ else text = sel.toString();
+
+ $('#redactor_link_url_text').val(text);
+
+ var thref = self.location.href.replace(/\/$/i, '');
+ url = url.replace(thref, '');
+ url = url.replace(/^\/#/, '#');
+ url = url.replace('mailto:', '');
+
+ // remove host from href
+ if (this.opts.linkProtocol === false)
+ {
+ var re = new RegExp('^(http|ftp|https)://' + self.location.host, 'i');
+ url = url.replace(re, '');
+ }
+
+ // set url
+ $('#redactor_link_url').val(url);
+
+ if (target === '_blank')
+ {
+ $('#redactor_link_blank').prop('checked', true);
+ }
+
+ this.linkInsertPressed = false;
+ $('#redactor_insert_link_btn').on('click', $.proxy(this.linkProcess, this));
+
+
+ setTimeout(function()
+ {
+ $('#redactor_link_url').focus();
+
+ }, 200);
}, this);
- this.modalInit(RLANG.image, this.opts.modal_image_edit, 380, callback);
+ this.modalInit(this.opts.curLang.link, this.opts.modal_link, 460, callback);
},
- imageDelete: function(el)
+ linkProcess: function()
{
- $(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')
+ if (this.linkInsertPressed)
{
- $(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' });
+ return;
}
- // as link
- var link = $.trim($('#redactor_file_link').val());
- if (link !== '')
+ this.linkInsertPressed = true;
+ var target = '', targetBlank = '';
+
+ var link = $('#redactor_link_url').val();
+ var text = $('#redactor_link_url_text').val();
+
+ // mailto
+ if (link.search('@') != -1 && /(http|ftp|https):\/\//i.test(link) === false)
{
- if ($(parent).get(0).tagName !== 'A')
+ link = 'mailto:' + link;
+ }
+ // url, not anchor
+ else if (link.search('#') != 0)
+ {
+ if ($('#redactor_link_blank').prop('checked'))
{
- $(el).replaceWith('' + this.outerHTML(el) + ' ');
+ target = ' target="_blank"';
+ targetBlank = '_blank';
+ }
+
+ // test url (add protocol)
+ var pattern = '((xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}';
+ var re = new RegExp('^(http|ftp|https)://' + pattern, 'i');
+ var re2 = new RegExp('^' + pattern, 'i');
+
+ if (link.search(re) == -1 && link.search(re2) == 0 && this.opts.linkProtocol)
+ {
+ link = this.opts.linkProtocol + link;
+ }
+ }
+
+ text = text.replace(/<|>/g, '');
+ var extra = ' ';
+ if (this.browser('mozilla'))
+ {
+ extra = ' ';
+ }
+
+ this.linkInsert('' + text + ' ' + extra, $.trim(text), link, targetBlank);
+
+ },
+ linkInsert: function (a, text, link, target)
+ {
+ this.selectionRestore();
+
+ if (text !== '')
+ {
+ if (this.insert_link_node)
+ {
+ this.bufferSet();
+
+ $(this.insert_link_node).text(text).attr('href', link);
+
+ if (target !== '')
+ {
+ $(this.insert_link_node).attr('target', target);
+ }
+ else
+ {
+ $(this.insert_link_node).removeAttr('target');
+ }
}
else
{
- $(parent).attr('href', link);
+ var $a = $(a).addClass('redactor-added-link');
+ this.exec('inserthtml', this.outerHtml($a), false);
+
+ var link = this.$editor.find('a.redactor-added-link');
+
+ link.removeAttr('style').removeClass('redactor-added-link').each(function()
+ {
+ if (this.className == '') $(this).removeAttr('class');
+ });
+
}
+
+ this.sync();
}
- else
+
+ // link tooltip
+ setTimeout($.proxy(function()
{
- if ($(parent).get(0).tagName === 'A')
+ if (this.opts.observeLinks) this.observeLinks();
+
+ }, this), 5);
+
+ this.modalClose();
+ },
+
+ // FILE
+ fileShow: function ()
+ {
+
+ this.selectionSave();
+
+ var callback = $.proxy(function()
+ {
+ var sel = this.getSelection();
+
+ var text = '';
+ if (this.oldIE()) text = sel.text;
+ else text = sel.toString();
+
+ $('#redactor_filename').val(text);
+
+ // dragupload
+ if (!this.isMobile() && !this.isIPad())
{
- $(parent).replaceWith(this.outerHTML(el));
+ this.draguploadInit('#redactor_file', {
+ url: this.opts.fileUpload,
+ uploadFields: this.opts.uploadFields,
+ success: $.proxy(this.fileCallback, this),
+ error: $.proxy( function(obj, json)
+ {
+ this.callback('fileUploadError', json);
+
+ }, this),
+ uploadParam: this.opts.fileUploadParam
+ });
}
+
+ this.uploadInit('redactor_file', {
+ auto: true,
+ url: this.opts.fileUpload,
+ success: $.proxy(this.fileCallback, this),
+ error: $.proxy(function(obj, json)
+ {
+ this.callback('fileUploadError', json);
+
+ }, this)
+ });
+
+ }, this);
+
+ this.modalInit(this.opts.curLang.file, this.opts.modal_file, 500, callback);
+ },
+ fileCallback: function(json)
+ {
+
+ this.selectionRestore();
+
+ if (json !== false)
+ {
+
+ var text = $('#redactor_filename').val();
+ if (text === '') text = json.filename;
+
+ var link = '' + text + ' ';
+
+ // chrome fix
+ if (this.browser('webkit') && !!this.window.chrome)
+ {
+ link = link + ' ';
+ }
+
+ this.execCommand('inserthtml', link, false);
+
+ var linkmarker = $(this.$editor.find('a#filelink-marker'));
+ if (linkmarker.size() != 0) linkmarker.removeAttr('id');
+ else linkmarker = false;
+
+ this.sync();
+
+ // file upload callback
+ this.callback('fileUpload', linkmarker, json);
}
this.modalClose();
- this.observeImages();
- this.syncCode();
-
},
- showImage: function()
+
+ // IMAGE
+ imageShow: function()
{
- this.saveSelection();
+
+ this.selectionSave();
var callback = $.proxy(function()
{
// json
- if (this.opts.imageGetJson !== false)
+ if (this.opts.imageGetJson)
{
- $.getJSON(this.opts.imageGetJson, $.proxy(function(data) {
- var folders = {};
- var z = 0;
+ $.getJSON(this.opts.imageGetJson, $.proxy(function(data)
+ {
+ var folders = {}, count = 0;
// folders
$.each(data, $.proxy(function(key, val)
{
if (typeof val.folder !== 'undefined')
{
- z++;
- folders[val.folder] = z;
+ count++;
+ folders[val.folder] = count;
}
}, this));
@@ -3184,25 +6608,18 @@ var RLANG = {
{
// title
var thumbtitle = '';
- if (typeof val.title !== 'undefined')
- {
- thumbtitle = val.title;
- }
+ if (typeof val.title !== 'undefined') thumbtitle = val.title;
var folderkey = 0;
if (!$.isEmptyObject(folders) && typeof val.folder !== 'undefined')
{
folderkey = folders[val.folder];
- if (folderclass === false)
- {
- folderclass = '.redactorfolder' + folderkey;
- }
+ if (folderclass === false) folderclass = '.redactorfolder' + folderkey;
}
var img = $(' ');
$('#redactor_image_box').append(img);
- $(img).click($.proxy(this.imageSetThumb, this));
-
+ $(img).click($.proxy(this.imageThumbClick, this));
}, this));
@@ -3216,500 +6633,921 @@ var RLANG = {
{
$('.redactorfolder').hide();
$('.redactorfolder' + $(e.target).val()).show();
- }
+ };
var select = $('');
- $.each(folders, function(k,v)
+ $.each( folders, function(k, v)
{
- select.append($('' + k + ' '));
+ select.append( $('' + k + ' '));
});
$('#redactor_image_box').before(select);
select.change(onchangeFunc);
}
-
}, this));
+
}
else
{
- $('#redactor_tabs a').eq(1).remove();
+ $('#redactor-tab-control-2').remove();
}
- if (this.opts.imageUpload !== false)
+ if (this.opts.imageUpload || this.opts.s3)
{
-
// dragupload
- if (this.opts.uploadCrossDomain === false && this.isMobile() === false)
+ if (!this.isMobile() && !this.isIPad() && this.opts.s3 === false)
{
-
- if ($('#redactor_file').size() !== 0)
+ if ($('#redactor_file' ).length)
{
- $('#redactor_file').dragupload(
- {
+ this.draguploadInit('#redactor_file', {
url: this.opts.imageUpload,
uploadFields: this.opts.uploadFields,
- success: $.proxy(this.imageUploadCallback, this),
- error: $.proxy(this.opts.imageUploadErrorCallback, this)
+ success: $.proxy(this.imageCallback, this),
+ error: $.proxy(function(obj, json)
+ {
+ this.callback('imageUploadError', json);
+
+ }, this),
+ uploadParam: this.opts.imageUploadParam
});
}
}
- // ajax upload
- this.uploadInit('redactor_file',
+ if (this.opts.s3 === false)
{
- auto: true,
- url: this.opts.imageUpload,
- success: $.proxy(this.imageUploadCallback, this),
- error: $.proxy(this.opts.imageUploadErrorCallback, this)
- });
+ // ajax upload
+ this.uploadInit('redactor_file', {
+ auto: true,
+ url: this.opts.imageUpload,
+ success: $.proxy(this.imageCallback, this),
+ error: $.proxy(function(obj, json)
+ {
+ this.callback('imageUploadError', json);
+
+ }, this)
+ });
+ }
+ // s3 upload
+ else
+ {
+ $('#redactor_file').on('change.redactor', $.proxy(this.s3handleFileSelect, this));
+ }
+
}
else
{
$('.redactor_tab').hide();
- if (this.opts.imageGetJson === false)
+ if (!this.opts.imageGetJson)
{
$('#redactor_tabs').remove();
$('#redactor_tab3').show();
}
else
{
- var tabs = $('#redactor_tabs a');
- tabs.eq(0).remove();
- tabs.eq(1).addClass('redactor_tabs_act');
+ $('#redactor-tab-control-1').remove();
+ $('#redactor-tab-control-2').addClass('redactor_tabs_act');
$('#redactor_tab2').show();
}
}
- $('#redactor_upload_btn').click($.proxy(this.imageUploadCallbackLink, this));
+ if (!this.opts.imageTabLink && (this.opts.imageUpload || this.opts.imageGetJson))
+ {
+ $('#redactor-tab-control-3').hide();
+ }
- if (this.opts.imageUpload === false && this.opts.imageGetJson === false)
+ $('#redactor_upload_btn').click($.proxy(this.imageCallbackLink, this));
+
+ if (!this.opts.imageUpload && !this.opts.imageGetJson)
{
setTimeout(function()
{
$('#redactor_file_link').focus();
- }, 200);
+ }, 200);
}
}, this);
- this.modalInit(RLANG.image, this.opts.modal_image, 610, callback);
+ this.modalInit(this.opts.curLang.image, this.opts.modal_image, 610, callback);
},
- imageSetThumb: function(e)
+ imageEdit: function(image)
{
- this._imageSet(' ', true);
- },
- imageUploadCallbackLink: function()
- {
- if ($('#redactor_file_link').val() !== '')
+ var $el = image;
+ var parent = $el.parent().parent();
+
+ var callback = $.proxy(function()
{
- var data = ' ';
- this._imageSet(data, true);
+ $('#redactor_file_alt').val($el.attr('alt'));
+ $('#redactor_image_edit_src').attr('href', $el.attr('src'));
+
+ if ($el.css('display') == 'block' && $el.css('float') == 'none')
+ {
+ $('#redactor_form_image_align').val('center');
+ }
+ else
+ {
+ $('#redactor_form_image_align').val($el.css('float'));
+ }
+
+ if ($(parent).get(0).tagName === 'A')
+ {
+ $('#redactor_file_link').val($(parent).attr('href'));
+
+ if ($(parent).attr('target') == '_blank')
+ {
+ $('#redactor_link_blank').prop('checked', true);
+ }
+ }
+
+ $('#redactor_image_delete_btn').click($.proxy(function()
+ {
+ this.imageRemove($el);
+
+ }, this));
+
+ $('#redactorSaveBtn').click($.proxy(function()
+ {
+ this.imageSave($el);
+
+ }, this));
+
+ }, this);
+
+ this.modalInit(this.opts.curLang.edit, this.opts.modal_image_edit, 380, callback);
+
+ },
+ imageRemove: function(el)
+ {
+ var parentLink = $(el).parent().parent();
+ var parent = $(el).parent();
+ var parentEl = false;
+
+ if (parentLink.length && parentLink[0].tagName === 'A')
+ {
+ parentEl = true;
+ $(parentLink).remove();
+ }
+ else if (parent.length && parent[0].tagName === 'A')
+ {
+ parentEl = true;
+ $(parent).remove();
}
else
{
- this.modalClose();
+ $(el).remove();
+ }
+
+ if (parent.length && parent[0].tagName === 'P')
+ {
+ this.focusWithSaveScroll();
+
+ if (parentEl === false) this.selectionStart(parent);
+ }
+
+ // delete callback
+ this.callback('imageDelete', el);
+
+ this.modalClose();
+ this.sync();
+ },
+ imageSave: function(el)
+ {
+ this.imageResizeHide(false);
+
+ var $el = $(el);
+ var parent = $el.parent();
+
+ $el.attr('alt', $('#redactor_file_alt').val());
+
+ var floating = $('#redactor_form_image_align').val();
+ var margin = '';
+
+ if (floating === 'left')
+ {
+ margin = '0 ' + this.opts.imageFloatMargin + ' ' + this.opts.imageFloatMargin + ' 0';
+ $el.css({ 'float': 'left', 'margin': margin });
+ }
+ else if (floating === 'right')
+ {
+ margin = '0 0 ' + this.opts.imageFloatMargin + ' ' + this.opts.imageFloatMargin + '';
+ $el.css({ 'float': 'right', 'margin': margin });
+ }
+ else if (floating === 'center')
+ {
+ $el.css({ 'float': '', 'display': 'block', 'margin': 'auto' });
+ }
+ else
+ {
+ $el.css({ 'float': '', 'display': '', 'margin': '' });
+ }
+
+ // as link
+ var link = $.trim($('#redactor_file_link').val());
+ if (link !== '')
+ {
+ var target = false;
+ if ($('#redactor_link_blank').prop('checked'))
+ {
+ target = true;
+ }
+
+ if (parent.get(0).tagName !== 'A')
+ {
+ var a = $('' + this.outerHtml(el) + ' ');
+
+ if (target)
+ {
+ a.attr('target', '_blank');
+ }
+
+ $el.replaceWith(a);
+ }
+ else
+ {
+ parent.attr('href', link);
+ if (target)
+ {
+ parent.attr('target', '_blank');
+ }
+ else
+ {
+ parent.removeAttr('target');
+ }
+ }
+ }
+ else
+ {
+ if (parent.get(0).tagName === 'A')
+ {
+ parent.replaceWith(this.outerHtml(el));
+ }
+ }
+
+ this.modalClose();
+ this.observeImages();
+ this.sync();
+
+ },
+ imageResizeHide: function(e)
+ {
+ if (e !== false && $(e.target).parent().size() != 0 && $(e.target).parent()[0].id === 'redactor-image-box')
+ {
+ return false;
+ }
+
+ var imageBox = this.$editor.find('#redactor-image-box');
+ if (imageBox.size() == 0)
+ {
+ return false;
+ }
+
+ this.$editor.find('#redactor-image-editter, #redactor-image-resizer').remove();
+
+ imageBox.find('img').css({
+ marginTop: imageBox[0].style.marginTop,
+ marginBottom: imageBox[0].style.marginBottom,
+ marginLeft: imageBox[0].style.marginLeft,
+ marginRight: imageBox[0].style.marginRight
+ });
+
+ imageBox.css('margin', '');
+
+
+ imageBox.find('img').css('opacity', '');
+ imageBox.replaceWith(function()
+ {
+ return $(this).contents();
+ });
+
+ $(document).off('click.redactor-image-resize-hide');
+ this.$editor.off('click.redactor-image-resize-hide');
+ this.$editor.off('keydown.redactor-image-delete');
+
+ this.sync()
+
+ },
+ imageResize: function(image)
+ {
+ var $image = $(image);
+
+ $image.on('mousedown', $.proxy(function()
+ {
+ this.imageResizeHide(false);
+ }, this));
+
+ $image.on('dragstart', $.proxy(function()
+ {
+ this.$editor.on('drop.redactor-image-inside-drop', $.proxy(function()
+ {
+ setTimeout($.proxy(function()
+ {
+ this.observeImages();
+ this.$editor.off('drop.redactor-image-inside-drop');
+ this.sync();
+
+ }, this), 1);
+
+ },this));
+ }, this));
+
+ $image.on('click', $.proxy(function(e)
+ {
+ if (this.$editor.find('#redactor-image-box').size() != 0)
+ {
+ return false;
+ }
+
+ var clicked = false,
+ start_x,
+ start_y,
+ ratio = $image.width() / $image.height(),
+ min_w = 20,
+ min_h = 10;
+
+ var imageResizer = this.imageResizeControls($image);
+
+ // resize
+ var isResizing = false;
+ if (imageResizer !== false)
+ {
+ imageResizer.on('mousedown', function(e)
+ {
+ isResizing = true;
+ e.preventDefault();
+
+ ratio = $image.width() / $image.height();
+
+ start_x = Math.round(e.pageX - $image.eq(0).offset().left);
+ start_y = Math.round(e.pageY - $image.eq(0).offset().top);
+
+ });
+
+ $(this.document.body).on('mousemove', $.proxy(function(e)
+ {
+ if (isResizing)
+ {
+ var mouse_x = Math.round(e.pageX - $image.eq(0).offset().left) - start_x;
+ var mouse_y = Math.round(e.pageY - $image.eq(0).offset().top) - start_y;
+
+ var div_h = $image.height();
+
+ var new_h = parseInt(div_h, 10) + mouse_y;
+ var new_w = Math.round(new_h * ratio);
+
+ if (new_w > min_w)
+ {
+ $image.width(new_w);
+
+ if (new_w < 100)
+ {
+ this.imageEditter.css({
+ marginTop: '-7px',
+ marginLeft: '-13px',
+ fontSize: '9px',
+ padding: '3px 5px'
+ });
+ }
+ else
+ {
+ this.imageEditter.css({
+ marginTop: '-11px',
+ marginLeft: '-18px',
+ fontSize: '11px',
+ padding: '7px 10px'
+ });
+ }
+ }
+
+ start_x = Math.round(e.pageX - $image.eq(0).offset().left);
+ start_y = Math.round(e.pageY - $image.eq(0).offset().top);
+
+ this.sync()
+ }
+ }, this)).on('mouseup', function()
+ {
+ isResizing = false;
+ });
+ }
+
+
+ this.$editor.on('keydown.redactor-image-delete', $.proxy(function(e)
+ {
+ var key = e.which;
+
+ if (this.keyCode.BACKSPACE == key || this.keyCode.DELETE == key)
+ {
+ this.bufferSet(false);
+ this.imageResizeHide(false);
+ this.imageRemove($image);
+ }
+
+ }, this));
+
+ $(document).on('click.redactor-image-resize-hide', $.proxy(this.imageResizeHide, this));
+ this.$editor.on('click.redactor-image-resize-hide', $.proxy(this.imageResizeHide, this));
+
+
+ }, this));
+ },
+ imageResizeControls: function($image)
+ {
+ var imageBox = $('');
+ imageBox.css({
+ position: 'relative',
+ display: 'inline-block',
+ lineHeight: 0,
+ outline: '1px dashed rgba(0, 0, 0, .6)',
+ 'float': $image.css('float')
+ });
+ imageBox.attr('contenteditable', false);
+
+ if ($image[0].style.margin != 'auto')
+ {
+ imageBox.css({
+ marginTop: $image[0].style.marginTop,
+ marginBottom: $image[0].style.marginBottom,
+ marginLeft: $image[0].style.marginLeft,
+ marginRight: $image[0].style.marginRight
+ });
+
+ $image.css('margin', '');
+ }
+ else
+ {
+ imageBox.css({ 'display': 'block', 'margin': 'auto' });
+ }
+
+ $image.css('opacity', .5).after(imageBox);
+
+ // editter
+ this.imageEditter = $('' + this.opts.curLang.edit + ' ');
+ this.imageEditter.css({
+ position: 'absolute',
+ zIndex: 5,
+ top: '50%',
+ left: '50%',
+ marginTop: '-11px',
+ marginLeft: '-18px',
+ lineHeight: 1,
+ backgroundColor: '#000',
+ color: '#fff',
+ fontSize: '11px',
+ padding: '7px 10px',
+ cursor: 'pointer'
+ });
+ this.imageEditter.attr('contenteditable', false);
+ this.imageEditter.on('click', $.proxy(function()
+ {
+ this.imageEdit($image);
+ }, this));
+ imageBox.append(this.imageEditter);
+
+ // resizer
+ if (this.opts.imageResizable)
+ {
+ var imageResizer = $(' ');
+ imageResizer.css({
+ position: 'absolute',
+ zIndex: 2,
+ lineHeight: 1,
+ cursor: 'nw-resize',
+ bottom: '-4px',
+ right: '-5px',
+ border: '1px solid #fff',
+ backgroundColor: '#000',
+ width: '8px',
+ height: '8px'
+ });
+ imageResizer.attr('contenteditable', false);
+ imageBox.append(imageResizer);
+
+ imageBox.append($image);
+
+ return imageResizer;
+ }
+ else
+ {
+ imageBox.append($image);
+
+ return false;
}
},
- imageUploadCallback: function(data)
+ imageThumbClick: function(e)
{
- this._imageSet(data);
+ var img = ' ';
+
+ var parent = this.getParent();
+ if (this.opts.paragraphy && $(parent).closest('li').size() == 0) img = '' + img + '
';
+
+ this.imageInsert(img, true);
},
- _imageSet: function(json, link)
+ imageCallbackLink: function()
{
- this.restoreSelection();
+ var val = $('#redactor_file_link').val();
+
+ if (val !== '')
+ {
+ var data = ' ';
+ if (this.opts.linebreaks === false) data = '' + data + '
';
+
+ this.imageInsert(data, true);
+
+ }
+ else this.modalClose();
+ },
+ imageCallback: function(data)
+ {
+ this.imageInsert(data);
+ },
+ imageInsert: function(json, link)
+ {
+ this.selectionRestore();
if (json !== false)
{
var html = '';
if (link !== true)
{
- html = '
';
+ html = ' ';
+
+ var parent = this.getParent();
+ if (this.opts.paragraphy && $(parent).closest('li').size() == 0)
+ {
+ html = '' + html + '
';
+ }
}
else
{
html = json;
}
- this.execCommand('inserthtml', html);
+ this.execCommand('inserthtml', html, false);
+
+ var image = $(this.$editor.find('img#image-marker'));
+
+ if (image.length) image.removeAttr('id');
+ else image = false;
+
+ this.sync();
// upload image callback
- if (link !== true && typeof this.opts.imageUploadCallback === 'function')
- {
- this.opts.imageUploadCallback(this, json);
- }
+ link !== true && this.callback('imageUpload', image, json);
}
this.modalClose();
this.observeImages();
},
- // INSERT LINK
- showLink: function()
+ // PROGRESS BAR
+ buildProgressBar: function()
{
- this.saveSelection();
-
- var callback = $.proxy(function()
- {
- this.insert_link_node = false;
- var sel = this.getSelection();
- var url = '', text = '', target = '';
-
- if (this.browser('msie'))
- {
- var parent = this.getParentNode();
- if (parent.nodeName === 'A')
- {
- this.insert_link_node = $(parent);
- text = this.insert_link_node.text();
- url = this.insert_link_node.attr('href');
- target = this.insert_link_node.attr('target');
- }
- else
- {
- if (this.oldIE())
- {
- text = sel.text;
- }
- else
- {
- text = sel.toString();
- }
- }
- }
- else
- {
- if (sel && sel.anchorNode && sel.anchorNode.parentNode.tagName === 'A')
- {
- url = sel.anchorNode.parentNode.href;
- text = sel.anchorNode.parentNode.text;
- target = sel.anchorNode.parentNode.target;
-
- if (sel.toString() === '')
- {
- this.insert_link_node = sel.anchorNode.parentNode;
- }
- }
- else
- {
- text = sel.toString();
- }
- }
-
- $('.redactor_link_text').val(text);
-
- var thref = self.location.href.replace(/\/$/i, '');
- var turl = url.replace(thref, '');
-
- if (url.search('mailto:') === 0)
- {
- this.setModalTab(2);
-
- $('#redactor_tab_selected').val(2);
- $('#redactor_link_mailto').val(url.replace('mailto:', ''));
- }
- else if (turl.search(/^#/gi) === 0)
- {
- this.setModalTab(3);
-
- $('#redactor_tab_selected').val(3);
- $('#redactor_link_anchor').val(turl.replace(/^#/gi, ''));
- }
- else
- {
- $('#redactor_link_url').val(turl);
- }
-
- if (target === '_blank')
- {
- $('#redactor_link_blank').attr('checked', true);
- }
-
- $('#redactor_insert_link_btn').click($.proxy(this.insertLink, this));
-
- setTimeout(function()
- {
- $('#redactor_link_url').focus();
- }, 200);
-
- }, this);
-
- this.modalInit(RLANG.link, this.opts.modal_link, 460, callback);
+ if ($('#redactor-progress').size() != 0) return;
+ this.$progressBar = $('
');
+ $(document.body).append(this.$progressBar);
},
- insertLink: function()
+ showProgressBar: function()
{
- var tab_selected = $('#redactor_tab_selected').val();
- var link = '', text = '', target = '';
-
- if (tab_selected === '1') // url
- {
- link = $('#redactor_link_url').val();
- text = $('#redactor_link_url_text').val();
-
- if ($('#redactor_link_blank').attr('checked'))
- {
- target = ' target="_blank"';
- }
-
- // test url
- var pattern = '/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/';
- //var pattern = '((xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}';
- var re = new RegExp('^(http|ftp|https)://' + pattern,'i');
- var re2 = new RegExp('^' + pattern,'i');
- if (link.search(re) == -1 && link.search(re2) == 0 && this.opts.protocol !== false)
- {
- link = this.opts.protocol + link;
- }
-
- }
- 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, target);
-
+ this.buildProgressBar();
+ this.$progressBar.fadeIn();
},
- _insertLink: function(a, text, link, target)
+ hideProgressBar: function()
{
- this.$editor.focus();
- this.restoreSelection();
-
- if (text !== '')
- {
- if (this.insert_link_node)
- {
- $(this.insert_link_node).text(text);
- $(this.insert_link_node).attr('href', link);
- if (target !== '')
- {
- $(this.insert_link_node).attr('target', target);
- }
- else
- {
- $(this.insert_link_node).removeAttr('target');
- }
-
- this.syncCode();
- }
- else
- {
- this.execCommand('inserthtml', a);
- }
- }
-
- this.modalClose();
+ this.buildProgressBar();
+ this.$progressBar.fadeOut(1500);
},
- // INSERT FILE
- showFile: function()
- {
- this.saveSelection();
-
- var callback = $.proxy(function()
- {
- var sel = this.getSelection();
-
- var text = '';
-
- if (this.oldIE())
- {
- text = sel.text;
- }
- else
- {
- text = sel.toString();
- }
-
- $('#redactor_filename').val(text);
-
- // dragupload
- if (this.opts.uploadCrossDomain === false && this.isMobile() === false)
- {
- $('#redactor_file').dragupload(
- {
- url: this.opts.fileUpload,
- uploadFields: this.opts.uploadFields,
- success: $.proxy(this.fileUploadCallback, this),
- error: $.proxy(this.opts.fileUploadErrorCallback, this)
- });
- }
-
- this.uploadInit('redactor_file',
- {
- auto: true,
- url: this.opts.fileUpload,
- success: $.proxy(this.fileUploadCallback, this),
- error: $.proxy(this.opts.fileUploadErrorCallback, this)
- });
-
- }, this);
-
- this.modalInit(RLANG.file, this.opts.modal_file, 500, callback);
- },
- fileUploadCallback: function(json)
- {
- this.restoreSelection();
-
- if (json !== false)
- {
- var text = $('#redactor_filename').val();
-
- if (text === '')
- {
- text = json.filename;
- }
-
- var link = '' + text + ' ';
-
- // chrome fix
- if (this.browser('webkit') && !!this.window.chrome)
- {
- link = link + ' ';
- }
-
- this.execCommand('inserthtml', link);
-
- // file upload callback
- if (typeof this.opts.fileUploadCallback === 'function')
- {
- this.opts.fileUploadCallback(this, json);
- }
- }
-
- this.modalClose();
- },
-
-
-
// MODAL
+ modalTemplatesInit: function()
+ {
+ $.extend( this.opts,
+ {
+ modal_file: String()
+ + '',
+
+ modal_image_edit: String()
+ + ''
+ + ''
+ + '' + this.opts.curLang._delete + ' '
+ + '' + this.opts.curLang.cancel + ' '
+ + '' + this.opts.curLang.save + ' '
+ + ' ',
+
+ modal_image: String()
+ + ''
+ + ''
+ + '' + this.opts.curLang.cancel + ' '
+ + '' + this.opts.curLang.insert + ' '
+ + ' ',
+
+ modal_link: String()
+ + ''
+ + ''
+ + '' + this.opts.curLang.cancel + ' '
+ + '' + this.opts.curLang.insert + ' '
+ + ' ',
+
+ modal_table: String()
+ + ''
+ + ''
+ + '' + this.opts.curLang.cancel + ' '
+ + '' + this.opts.curLang.insert + ' '
+ + ' ',
+
+ modal_video: String()
+ + ''
+ + ''
+ + '' + this.opts.curLang.cancel + ' '
+ + '' + this.opts.curLang.insert + ' '
+ + ' '
+
+ });
+ },
modalInit: function(title, content, width, callback)
{
- // modal overlay
- if ($('#redactor_modal_overlay').size() === 0)
+ this.modalSetOverlay();
+
+ this.$redactorModalWidth = width;
+ this.$redactorModal = $('#redactor_modal');
+
+ if (!this.$redactorModal.length)
{
- this.overlay = $('
');
- $('body').prepend(this.overlay);
+ this.$redactorModal = $('
');
+ this.$redactorModal.append($('×
'));
+ this.$redactorModal.append($(''));
+ this.$redactorModal.append($('
'));
+ this.$redactorModal.appendTo(document.body);
}
- if (this.opts.overlay)
+ $('#redactor_modal_close').on('click', $.proxy(this.modalClose, this));
+ $(document).keyup($.proxy(this.modalCloseHandler, this));
+ this.$editor.keyup($.proxy(this.modalCloseHandler, this));
+
+ this.modalSetContent(content);
+ this.modalSetTitle(title);
+ this.modalSetDraggable();
+ this.modalLoadTabs();
+ this.modalOnCloseButton();
+ this.modalSetButtonsWidth();
+
+ this.saveModalScroll = this.document.body.scrollTop;
+ if (this.opts.autoresize === false)
{
- $('#redactor_modal_overlay').show();
- $('#redactor_modal_overlay').click($.proxy(this.modalClose, this));
+ this.saveModalScroll = this.$editor.scrollTop();
}
- if ($('#redactor_modal').size() === 0)
- {
- this.modal = $('');
- $('body').append(this.modal);
- }
+ if (this.isMobile() === false) this.modalShowOnDesktop();
+ else this.modalShowOnMobile();
- $('#redactor_modal_close').click($.proxy(this.modalClose, this));
-
- this.hdlModalClose = $.proxy(function(e) { if ( e.keyCode === 27) { this.modalClose(); return false; } }, this);
-
- $(document).keyup(this.hdlModalClose);
- this.$editor.keyup(this.hdlModalClose);
-
- // set content
- if (content.indexOf('#') == 0)
- {
- $('#redactor_modal_inner').empty().append($(content).html());
- }
- else
- {
- $('#redactor_modal_inner').empty().append(content);
- }
-
-
- $('#redactor_modal_header').html(title);
-
- // draggable
- if (typeof $.fn.draggable !== 'undefined')
- {
- $('#redactor_modal').draggable({ handle: '#redactor_modal_header' });
- $('#redactor_modal_header').css('cursor', 'move');
- }
-
- // tabs
- if ($('#redactor_tabs').size() !== 0)
- {
- var that = this;
- $('#redactor_tabs a').each(function(i,s)
- {
- i++;
- $(s).click(function()
- {
- $('#redactor_tabs a').removeClass('redactor_tabs_act');
- $(this).addClass('redactor_tabs_act');
- $('.redactor_tab').hide();
- $('#redactor_tab' + i).show();
- $('#redactor_tab_selected').val(i);
-
- if (that.isMobile() === false)
- {
- var height = $('#redactor_modal').outerHeight();
- $('#redactor_modal').css('margin-top', '-' + (height+10)/2 + 'px');
- }
- });
- });
- }
-
- $('#redactor_modal .redactor_btn_modal_close').click($.proxy(this.modalClose, this));
-
- if (this.isMobile() === false)
- {
- $('#redactor_modal').css({ position: 'fixed', top: '-2000px', left: '50%', width: width + 'px', marginLeft: '-' + (width+60)/2 + 'px' }).show();
-
- this.modalSaveBodyOveflow = $(document.body).css('overflow');
- $(document.body).css('overflow', 'hidden');
- }
- else
- {
- $('#redactor_modal').css({ position: 'fixed', width: '100%', height: '100%', top: '0', left: '0', margin: '0', minHeight: '300px' }).show();
- }
-
- // callback
+ // modal actions callback
if (typeof callback === 'function')
{
callback();
}
- if (this.isMobile() === false)
+ // modal shown callback
+ setTimeout($.proxy(function()
{
- setTimeout(function()
+ this.callback('modalOpened', this.$redactorModal);
+
+ }, this), 11);
+
+ // fix bootstrap modal focus
+ $(document).off('focusin.modal');
+
+ // enter
+ this.$redactorModal.find('input[type=text]').on('keypress', $.proxy(function(e)
+ {
+ if (e.which === 13)
{
- var height = $('#redactor_modal').outerHeight();
- $('#redactor_modal').css({ top: '50%', height: 'auto', minHeight: 'auto', marginTop: '-' + (height+10)/2 + 'px' });
+ this.$redactorModal.find('.redactor_modal_action_btn').click();
+ e.preventDefault();
+ }
+ }, this));
+
+ return this.$redactorModal;
+
+ },
+ modalShowOnDesktop: function()
+ {
+ this.$redactorModal.css({
+ position: 'fixed',
+ top: '-2000px',
+ left: '50%',
+ width: this.$redactorModalWidth + 'px',
+ marginLeft: '-' + (this.$redactorModalWidth / 2) + 'px'
+ }).show();
+
+ this.modalSaveBodyOveflow = $(document.body).css('overflow');
+ $(document.body).css('overflow', 'hidden');
+
+ setTimeout($.proxy(function()
+ {
+ var height = this.$redactorModal.outerHeight();
+ this.$redactorModal.css({
+ top: '50%',
+ height: 'auto',
+ minHeight: 'auto',
+ marginTop: '-' + (height + 10) / 2 + 'px'
+ });
+ }, this), 15);
+ },
+ modalShowOnMobile: function()
+ {
+ this.$redactorModal.css({
+ position: 'fixed',
+ width: '100%',
+ height: '100%',
+ top: '0',
+ left: '0',
+ margin: '0',
+ minHeight: '300px'
+ }).show();
+ },
+ modalSetContent: function(content)
+ {
+ this.modalcontent = false;
+ if (content.indexOf('#') == 0)
+ {
+ this.modalcontent = $(content);
+ $('#redactor_modal_inner').empty().append(this.modalcontent.html());
+ this.modalcontent.html('');
- }, 20);
}
+ else
+ {
+ $('#redactor_modal_inner').empty().append(content);
+ }
+ },
+ modalSetTitle: function(title)
+ {
+ this.$redactorModal.find('#redactor_modal_header').html(title);
+ },
+ modalSetButtonsWidth: function()
+ {
+ var buttons = this.$redactorModal.find('footer button').not('.redactor_modal_btn_hidden');
+ var buttonsSize = buttons.size();
+ if (buttonsSize > 0)
+ {
+ $(buttons).css('width', (this.$redactorModalWidth/buttonsSize) + 'px')
+ }
+ },
+ modalOnCloseButton: function()
+ {
+ this.$redactorModal.find('.redactor_btn_modal_close').on('click', $.proxy(this.modalClose, this));
+ },
+ modalSetOverlay: function()
+ {
+ if (this.opts.modalOverlay)
+ {
+ this.$redactorModalOverlay = $('#redactor_modal_overlay');
+ if (!this.$redactorModalOverlay.length)
+ {
+ this.$redactorModalOverlay = $('
');
+ $('body').prepend(this.$redactorModalOverlay);
+ }
+ this.$redactorModalOverlay.show().on('click', $.proxy(this.modalClose, this));
+ }
+ },
+ modalSetDraggable: function()
+ {
+ if (typeof $.fn.draggable !== 'undefined')
+ {
+ this.$redactorModal.draggable({ handle: '#redactor_modal_header' });
+ this.$redactorModal.find('#redactor_modal_header').css('cursor', 'move');
+ }
+ },
+ modalLoadTabs: function()
+ {
+ var $redactor_tabs = $('#redactor_tabs');
+ if (!$redactor_tabs.length) return false;
+
+ var that = this;
+ $redactor_tabs.find('a').each(function(i, s)
+ {
+ i++;
+ $(s).on('click', function(e)
+ {
+ e.preventDefault();
+
+ $redactor_tabs.find('a').removeClass('redactor_tabs_act');
+ $(this).addClass('redactor_tabs_act');
+ $('.redactor_tab').hide();
+ $('#redactor_tab' + i ).show();
+ $('#redactor_tab_selected').val(i);
+
+ if (that.isMobile() === false)
+ {
+ var height = that.$redactorModal.outerHeight();
+ that.$redactorModal.css('margin-top', '-' + (height + 10) / 2 + 'px');
+ }
+ });
+ });
+
+ },
+ modalCloseHandler: function(e)
+ {
+ if (e.keyCode === this.keyCode.ESC)
+ {
+ this.modalClose();
+ return false;
+ }
},
modalClose: function()
{
- $('#redactor_modal_close').unbind('click', this.modalClose);
+ $('#redactor_modal_close').off('click', this.modalClose);
$('#redactor_modal').fadeOut('fast', $.proxy(function()
{
- $('#redactor_modal_inner').html('');
+ var redactorModalInner = $('#redactor_modal_inner');
- if (this.opts.overlay)
+ if (this.modalcontent !== false)
{
- $('#redactor_modal_overlay').hide();
- $('#redactor_modal_overlay').unbind('click', this.modalClose);
+ this.modalcontent.html(redactorModalInner.html());
+ this.modalcontent = false;
+ }
+
+ redactorModalInner.html('');
+
+ if (this.opts.modalOverlay)
+ {
+ $('#redactor_modal_overlay').hide().off('click', this.modalClose);
}
$(document).unbind('keyup', this.hdlModalClose);
this.$editor.unbind('keyup', this.hdlModalClose);
+ this.selectionRestore();
+
+ // restore scroll
+ if (this.opts.autoresize && this.saveModalScroll)
+ {
+ $(this.document.body).scrollTop(this.saveModalScroll);
+ }
+ else if (this.opts.autoresize === false && this.saveModalScroll)
+ {
+ this.$editor.scrollTop(this.saveModalScroll);
+ }
+
+ this.callback('modalClosed');
+
}, this));
@@ -3719,21 +7557,157 @@ var RLANG = {
}
return false;
-
},
- setModalTab: function(num)
+ modalSetTab: function(num)
{
$('.redactor_tab').hide();
- var tabs = $('#redactor_tabs a');
- tabs.removeClass('redactor_tabs_act');
- tabs.eq(num-1).addClass('redactor_tabs_act');
+ $('#redactor_tabs').find('a').removeClass('redactor_tabs_act').eq(num - 1).addClass('redactor_tabs_act');
$('#redactor_tab' + num).show();
},
- // UPLOAD
- uploadInit: function(element, options)
+ // S3
+ s3handleFileSelect: function(e)
+ {
+ var files = e.target.files;
+
+ for (var i = 0, f; f = files[i]; i++)
+ {
+ this.s3uploadFile(f);
+ }
+ },
+ s3uploadFile: function(file)
+ {
+ this.s3executeOnSignedUrl(file, $.proxy(function(signedURL)
+ {
+ this.s3uploadToS3(file, signedURL);
+ }, this));
+ },
+ s3executeOnSignedUrl: function(file, callback)
+ {
+ var xhr = new XMLHttpRequest();
+
+ var mark = '?';
+ if (this.opts.s3.search(/\?/) != '-1') mark = '&';
+
+ xhr.open('GET', this.opts.s3 + mark + 'name=' + file.name + '&type=' + file.type, true);
+
+ // Hack to pass bytes through unprocessed.
+ if (xhr.overrideMimeType) xhr.overrideMimeType('text/plain; charset=x-user-defined');
+
+ var that = this;
+ xhr.onreadystatechange = function(e)
+ {
+ if (this.readyState == 4 && this.status == 200)
+ {
+ that.showProgressBar();
+ callback(decodeURIComponent(this.responseText));
+ }
+ else if(this.readyState == 4 && this.status != 200)
+ {
+ //setProgress(0, 'Could not contact signing script. Status = ' + this.status);
+ }
+ };
+
+ xhr.send();
+ },
+ s3createCORSRequest: function(method, url)
+ {
+ var xhr = new XMLHttpRequest();
+ if ("withCredentials" in xhr)
+ {
+ xhr.open(method, url, true);
+ }
+ else if (typeof XDomainRequest != "undefined")
+ {
+ xhr = new XDomainRequest();
+ xhr.open(method, url);
+ }
+ else
+ {
+ xhr = null;
+ }
+
+ return xhr;
+ },
+ s3uploadToS3: function(file, url)
+ {
+ var xhr = this.s3createCORSRequest('PUT', url);
+ if (!xhr)
+ {
+ //setProgress(0, 'CORS not supported');
+ }
+ else
+ {
+ xhr.onload = $.proxy(function()
+ {
+ if (xhr.status == 200)
+ {
+ //setProgress(100, 'Upload completed.');
+
+ this.hideProgressBar();
+
+ var s3image = url.split('?');
+
+ if (!s3image[0])
+ {
+ // url parsing is fail
+ return false;
+ }
+
+ this.selectionRestore();
+
+ var html = '';
+ html = ' ';
+ if (this.opts.paragraphy) html = '' + html + '
';
+
+ this.execCommand('inserthtml', html, false);
+
+ var image = $(this.$editor.find('img#image-marker'));
+
+ if (image.length) image.removeAttr('id');
+ else image = false;
+
+ this.sync();
+
+ // upload image callback
+ this.callback('imageUpload', image, false);
+
+ this.modalClose();
+ this.observeImages();
+
+ }
+ else
+ {
+ //setProgress(0, 'Upload error: ' + xhr.status);
+ }
+ }, this);
+
+ xhr.onerror = function()
+ {
+ //setProgress(0, 'XHR error.');
+ };
+
+ xhr.upload.onprogress = function(e)
+ {
+ /*
+ if (e.lengthComputable)
+ {
+ var percentLoaded = Math.round((e.loaded / e.total) * 100);
+ setProgress(percentLoaded, percentLoaded == 100 ? 'Finalizing.' : 'Uploading.');
+ }
+ */
+ };
+
+ xhr.setRequestHeader('Content-Type', file.type);
+ xhr.setRequestHeader('x-amz-acl', 'public-read');
+
+ xhr.send(file);
+ }
+ },
+
+ // UPLOAD
+ uploadInit: function(el, options)
{
- // Upload Options
this.uploadOptions = {
url: false,
success: false,
@@ -3746,26 +7720,30 @@ var RLANG = {
$.extend(this.uploadOptions, options);
- // Test input or form
- if ($('#' + element).size() !== 0 && $('#' + element).get(0).tagName === 'INPUT')
- {
- this.uploadOptions.input = $('#' + element);
- this.element = $($('#' + element).get(0).form);
- }
- else
- {
- this.element = $('#' + element);
- }
+ var $el = $('#' + el);
- this.element_action = this.element.attr('action');
+ // Test input or form
+ if ($el.length && $el[0].tagName === 'INPUT')
+ {
+ this.uploadOptions.input = $el;
+ this.el = $($el[0].form);
+ }
+ else this.el = $el;
+
+ this.element_action = this.el.attr('action');
// Auto or trigger
if (this.uploadOptions.auto)
{
- $(this.uploadOptions.input).change($.proxy(function()
+ $(this.uploadOptions.input).change($.proxy(function(e)
{
- this.element.submit(function(e) { return false; });
- this.uploadSubmit();
+ this.el.submit(function(e)
+ {
+ return false;
+ });
+
+ this.uploadSubmit(e);
+
}, this));
}
@@ -3774,48 +7752,50 @@ var RLANG = {
$('#' + this.uploadOptions.trigger).click($.proxy(this.uploadSubmit, this));
}
},
- uploadSubmit : function()
+ uploadSubmit: function(e)
{
+ this.showProgressBar();
this.uploadForm(this.element, this.uploadFrame());
},
- uploadFrame : function()
+ uploadFrame: function()
{
this.id = 'f' + Math.floor(Math.random() * 99999);
var d = this.document.createElement('div');
- var iframe = ' ';
+ var iframe = ' ';
+
d.innerHTML = iframe;
$(d).appendTo("body");
// Start
- if (this.uploadOptions.start)
- {
- this.uploadOptions.start();
- }
+ if (this.uploadOptions.start) this.uploadOptions.start();
- $('#' + this.id).load($.proxy(this.uploadLoaded, this));
+ $( '#' + this.id ).load($.proxy(this.uploadLoaded, this));
return this.id;
},
- uploadForm : function(f, name)
+ uploadForm: function(f, name)
{
if (this.uploadOptions.input)
{
- var formId = 'redactorUploadForm' + this.id;
- var fileId = 'redactorUploadFile' + this.id;
- this.form = $(' ');
+ var formId = 'redactorUploadForm' + this.id,
+ fileId = 'redactorUploadFile' + this.id;
+
+ this.form = $(' ');
// append hidden fields
if (this.opts.uploadFields !== false && typeof this.opts.uploadFields === 'object')
{
- $.each(this.opts.uploadFields, $.proxy(function(k,v)
+ $.each(this.opts.uploadFields, $.proxy(function(k, v)
{
- if (v.toString().indexOf('#') === 0)
- {
- v = $(v).val();
- }
+ if (v != null && v.toString().indexOf('#') === 0) v = $(v).val();
+
+ var hidden = $(' ', {
+ 'type': "hidden",
+ 'name': k,
+ 'value': v
+ });
- var hidden = $(' ', {'type': "hidden", 'name': k, 'value': v});
$(this.form).append(hidden);
}, this));
@@ -3823,59 +7803,52 @@ var RLANG = {
var oldElement = this.uploadOptions.input;
var newElement = $(oldElement).clone();
- $(oldElement).attr('id', fileId);
- $(oldElement).before(newElement);
- $(oldElement).appendTo(this.form);
- $(this.form).css('position', 'absolute');
- $(this.form).css('top', '-2000px');
- $(this.form).css('left', '-2000px');
- $(this.form).appendTo('body');
+
+ $(oldElement).attr('id', fileId).before(newElement).appendTo(this.form);
+
+ $(this.form).css('position', 'absolute')
+ .css('top', '-2000px')
+ .css('left', '-2000px')
+ .appendTo('body');
this.form.submit();
+
}
else
{
- f.attr('target', name);
- f.attr('method', 'POST');
- f.attr('enctype', 'multipart/form-data');
- f.attr('action', this.uploadOptions.url);
+ f.attr('target', name)
+ .attr('method', 'POST')
+ .attr('enctype', 'multipart/form-data')
+ .attr('action', this.uploadOptions.url);
this.element.submit();
}
-
},
- uploadLoaded : function()
+ uploadLoaded: function()
{
- var i = $('#' + this.id)[0];
- var d;
+ var i = $( '#' + this.id)[0], d;
- if (i.contentDocument)
- {
- d = i.contentDocument;
- }
- else if (i.contentWindow)
- {
- d = i.contentWindow.document;
- }
- else
- {
- d = window.frames[this.id].document;
- }
+ if (i.contentDocument) d = i.contentDocument;
+ else if (i.contentWindow) d = i.contentWindow.document;
+ else d = window.frames[this.id].document;
// Success
if (this.uploadOptions.success)
{
+ this.hideProgressBar();
+
if (typeof d !== 'undefined')
{
// Remove bizarre tag wrappers around our json data:
var rawString = d.body.innerHTML;
var jsonString = rawString.match(/\{(.|\n)*\}/)[0];
+
+ jsonString = jsonString.replace(/^\[/, '');
+ jsonString = jsonString.replace(/\]$/, '');
+
var json = $.parseJSON(jsonString);
- if (typeof json.error == 'undefined')
- {
- this.uploadOptions.success(json);
- }
+ if (typeof json.error == 'undefined') this.uploadOptions.success(json);
else
{
this.uploadOptions.error(this, json);
@@ -3884,327 +7857,415 @@ var RLANG = {
}
else
{
- alert('Upload failed!');
this.modalClose();
+ alert('Upload failed!');
}
}
- this.element.attr('action', this.element_action);
- this.element.attr('target', '');
-
+ this.el.attr('action', this.element_action);
+ this.el.attr('target', '');
},
- // UTILITY
- browser: function(browser)
+ // DRAGUPLOAD
+ draguploadInit: function (el, options)
{
- var ua = navigator.userAgent.toLowerCase();
- var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
+ this.draguploadOptions = $.extend({
+ url: false,
+ success: false,
+ error: false,
+ preview: false,
+ uploadFields: false,
+ text: this.opts.curLang.drop_file_here,
+ atext: this.opts.curLang.or_choose,
+ uploadParam: false
+ }, options);
- if (browser == 'version')
+ if (window.FormData === undefined) return false;
+
+ this.droparea = $('
');
+ this.dropareabox = $('' + this.draguploadOptions.text + '
');
+ this.dropalternative = $('' + this.draguploadOptions.atext + '
');
+
+ this.droparea.append(this.dropareabox);
+
+ $(el).before(this.droparea);
+ $(el).before(this.dropalternative);
+
+ // drag over
+ this.dropareabox.on('dragover', $.proxy(function()
{
- return match[2];
+ return this.draguploadOndrag();
+
+ }, this));
+
+ // drag leave
+ this.dropareabox.on('dragleave', $.proxy(function()
+ {
+ return this.draguploadOndragleave();
+
+ }, this));
+
+ // drop
+ this.dropareabox.get(0).ondrop = $.proxy(function(e)
+ {
+ e.preventDefault();
+
+ this.dropareabox.removeClass('hover').addClass('drop');
+ this.showProgressBar();
+ this.dragUploadAjax(this.draguploadOptions.url, e.dataTransfer.files[0], false, e, this.draguploadOptions.uploadParam);
+
+ }, this );
+ },
+ dragUploadAjax: function(url, file, directupload, e, uploadParam)
+ {
+ if (!directupload)
+ {
+ var xhr = $.ajaxSettings.xhr();
+ if (xhr.upload)
+ {
+ xhr.upload.addEventListener('progress', $.proxy(this.uploadProgress, this), false);
+ }
+
+ $.ajaxSetup({
+ xhr: function () { return xhr; }
+ });
}
- if (browser == 'webkit')
- {
- return (match[1] == 'chrome' || match[1] == 'webkit');
- }
+ // drop callback
+ this.callback('drop', e);
- return match[1] == browser;
- },
- oldIE: function()
- {
- if (this.browser('msie') && parseInt(this.browser('version'), 10) < 9)
- {
- return true;
- }
+ var fd = new FormData();
- return false;
- },
- outerHTML: function(s)
- {
- return $("").append($(s).eq(0).clone()).html();
- },
- normalize: function(str)
- {
- return parseInt(str.replace('px',''), 10);
- },
- isMobile: function(ipad)
- {
- if (ipad === true && /(iPhone|iPod|iPad|BlackBerry|Android)/.test(navigator.userAgent))
+ // append file data
+ if (uploadParam !== false)
{
- return true;
- }
- else if (/(iPhone|iPod|BlackBerry|Android)/.test(navigator.userAgent))
- {
- return true;
+ fd.append(uploadParam, file);
}
else
{
- return false;
+ fd.append('file', file);
}
- }
- };
-
-
- // API
- $.fn.getObject = function()
- {
- return this.data('redactor');
- };
-
- $.fn.getEditor = function()
- {
- return this.data('redactor').$editor;
- };
-
- $.fn.getCode = function()
- {
- return $.trim(this.data('redactor').getCode());
- };
-
- $.fn.getText = function()
- {
- return this.data('redactor').$editor.text();
- };
-
- $.fn.getSelected = function()
- {
- return this.data('redactor').getSelectedHtml();
- };
-
- $.fn.setCode = function(html)
- {
- this.data('redactor').setCode(html);
- };
-
- $.fn.insertHtml = function(html)
- {
- this.data('redactor').insertHtml(html);
- };
-
- $.fn.destroyEditor = function()
- {
- this.each(function()
- {
- if (typeof $(this).data('redactor') != 'undefined')
+ // append hidden fields
+ if (this.opts.uploadFields !== false && typeof this.opts.uploadFields === 'object')
{
- $(this).data('redactor').destroy();
- $(this).removeData('redactor');
+ $.each(this.opts.uploadFields, $.proxy(function(k, v)
+ {
+ if (v != null && v.toString().indexOf('#') === 0) v = $(v).val();
+ fd.append(k, v);
+
+ }, this));
}
- });
- };
- $.fn.setFocus = function()
- {
- this.data('redactor').$editor.focus();
- };
-
- $.fn.execCommand = function(cmd, param)
- {
- this.data('redactor').execCommand(cmd, param);
- };
-
-})(jQuery);
-
-/*
- Plugin Drag and drop Upload v1.0.2
- http://imperavi.com/
- Copyright 2012, Imperavi Inc.
-*/
-(function($){
-
- "use strict";
-
- // Initialization
- $.fn.dragupload = function(options)
- {
- return this.each(function() {
- var obj = new Construct(this, options);
- obj.init();
- });
- };
-
- // Options and variables
- function Construct(el, options) {
-
- this.opts = $.extend({
-
- url: false,
- success: false,
- error: false,
- preview: false,
- uploadFields: false,
-
- text: RLANG.drop_file_here,
- atext: RLANG.or_choose
-
- }, options);
-
- this.$el = $(el);
- }
-
- // Functionality
- Construct.prototype = {
- init: function()
- {
- if (navigator.userAgent.search("MSIE") === -1)
- {
- this.droparea = $('
');
- this.dropareabox = $('' + this.opts.text + '
');
- this.dropalternative = $('' + this.opts.atext + '
');
-
- this.droparea.append(this.dropareabox);
-
- this.$el.before(this.droparea);
- this.$el.before(this.dropalternative);
-
- // drag over
- this.dropareabox.bind('dragover', $.proxy(function() { return this.ondrag(); }, this));
-
- // drag leave
- this.dropareabox.bind('dragleave', $.proxy(function() { return this.ondragleave(); }, this));
-
- var uploadProgress = $.proxy(function(e)
+ $.ajax({
+ url: url,
+ dataType: 'html',
+ data: fd,
+ cache: false,
+ contentType: false,
+ processData: false,
+ type: 'POST',
+ success: $.proxy(function(data)
{
- var percent = parseInt(e.loaded / e.total * 100, 10);
- this.dropareabox.text('Loading ' + percent + '%');
+ data = data.replace(/^\[/, '');
+ data = data.replace(/\]$/, '');
- }, this);
+ var json = (typeof data === 'string' ? $.parseJSON(data) : data);
- var xhr = jQuery.ajaxSettings.xhr();
+ this.hideProgressBar();
- if (xhr.upload)
- {
- xhr.upload.addEventListener('progress', uploadProgress, false);
- }
-
- var provider = function () { return xhr; };
-
- // drop
- this.dropareabox.get(0).ondrop = $.proxy(function(event)
- {
- event.preventDefault();
-
- this.dropareabox.removeClass('hover').addClass('drop');
-
- var file = event.dataTransfer.files[0];
- var fd = new FormData();
-
- // append hidden fields
- if (this.opts.uploadFields !== false && typeof this.opts.uploadFields === 'object')
+ if (directupload)
{
- $.each(this.opts.uploadFields, $.proxy(function(k,v)
+ var $img = $(' ');
+ $img.attr('src', json.filelink).attr('id', 'drag-image-marker');
+
+ this.insertNodeToCaretPositionFromPoint(e, $img[0]);
+
+ var image = $(this.$editor.find('img#drag-image-marker'));
+ if (image.length) image.removeAttr('id');
+ else image = false;
+
+ this.sync();
+ this.observeImages();
+
+ // upload callback
+ if (image) this.callback('imageUpload', image, json);
+
+ // error callback
+ if (typeof json.error !== 'undefined') this.callback('imageUploadError', json);
+ }
+ else
+ {
+ if (typeof json.error == 'undefined')
{
- if (v.toString().indexOf('#') === 0)
- {
- v = $(v).val();
- }
-
- fd.append(k, v);
-
- }, this));
+ this.draguploadOptions.success(json);
+ }
+ else
+ {
+ this.draguploadOptions.error(this, json);
+ this.draguploadOptions.success(false);
+ }
}
- // append file data
- fd.append('file', file);
-
- $.ajax({
- url: this.opts.url,
- dataType: 'html',
- data: fd,
- xhr: provider,
- cache: false,
- contentType: false,
- processData: false,
- type: 'POST',
- success: $.proxy(function(data)
- {
- var json = $.parseJSON(data);
-
- if (typeof json.error == 'undefined')
- {
- this.opts.success(json);
- }
- else
- {
- this.opts.error(this, json);
- this.opts.success(false);
- }
-
- }, this)
- });
-
-
- }, this);
- }
+ }, this)
+ });
},
- ondrag: function()
+ draguploadOndrag: function()
{
this.dropareabox.addClass('hover');
return false;
},
- ondragleave: function()
+ draguploadOndragleave: function()
{
this.dropareabox.removeClass('hover');
return false;
+ },
+ uploadProgress: function(e, text)
+ {
+ var percent = e.loaded ? parseInt(e.loaded / e.total * 100, 10) : e;
+ this.dropareabox.text('Loading ' + percent + '% ' + (text || ''));
+ },
+
+ // UTILS
+ isMobile: function()
+ {
+ return /(iPhone|iPod|BlackBerry|Android)/.test(navigator.userAgent);
+ },
+ isIPad: function()
+ {
+ return /iPad/.test(navigator.userAgent);
+ },
+ normalize: function(str)
+ {
+ if (typeof(str) === 'undefined') return 0;
+ return parseInt(str.replace('px',''), 10);
+ },
+ outerHtml: function(el)
+ {
+ return $('').append($(el).eq(0).clone()).html();
+ },
+ stripHtml: function(html)
+ {
+ var tmp = document.createElement("DIV");
+ tmp.innerHTML = html;
+ return tmp.textContent || tmp.innerText || "";
+ },
+ isString: function(obj)
+ {
+ return Object.prototype.toString.call(obj) == '[object String]';
+ },
+ isEmpty: function(html)
+ {
+ html = html.replace(/|
|
| /gi, '');
+ html = html.replace(/\s/g, '');
+ html = html.replace(/^
[^\W\w\D\d]*?<\/p>$/i, '');
+
+ return html == '';
+ },
+ getInternetExplorerVersion: function()
+ {
+ var rv = false;
+ if (navigator.appName == 'Microsoft Internet Explorer')
+ {
+ var ua = navigator.userAgent;
+ var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
+ if (re.exec(ua) != null)
+ {
+ rv = parseFloat(RegExp.$1);
+ }
+ }
+
+ return rv;
+ },
+ isIe11: function()
+ {
+ return !!navigator.userAgent.match(/Trident\/7\./);
+ },
+ browser: function(browser)
+ {
+ var ua = navigator.userAgent.toLowerCase();
+ var match = /(opr)[\/]([\w.]+)/.exec( ua ) ||
+ /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+ /(webkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+ [];
+
+ if (browser == 'version') return match[2];
+ if (browser == 'webkit') return (match[1] == 'chrome' || match[1] == 'webkit');
+ if (match[1] == 'rv') return browser == 'msie';
+ if (match[1] == 'opr') return browser == 'webkit';
+
+ return browser == match[1];
+
+ },
+ oldIE: function()
+ {
+ if (this.browser('msie') && parseInt(this.browser('version'), 10) < 9) return true;
+ return false;
+ },
+ getFragmentHtml: function (fragment)
+ {
+ var cloned = fragment.cloneNode(true);
+ var div = this.document.createElement('div');
+
+ div.appendChild(cloned);
+ return div.innerHTML;
+ },
+ extractContent: function()
+ {
+ var node = this.$editor[0];
+ var frag = this.document.createDocumentFragment();
+ var child;
+
+ while ((child = node.firstChild))
+ {
+ frag.appendChild(child);
+ }
+
+ return frag;
+ },
+ isParentRedactor: function(el)
+ {
+ if (!el) return false;
+ if (this.opts.iframe) return el;
+
+ if ($(el).parents('div.redactor_editor').length == 0 || $(el).hasClass('redactor_editor')) return false;
+ else return el;
+ },
+ currentOrParentIs: function(tagName)
+ {
+ var parent = this.getParent(), current = this.getCurrent();
+ return parent && parent.tagName === tagName ? parent : current && current.tagName === tagName ? current : false;
+ },
+ isEndOfElement: function()
+ {
+ var current = this.getBlock();
+ var offset = this.getCaretOffset(current);
+
+ var text = $.trim($(current).text()).replace(/\n\r\n/g, '');
+
+ var len = text.length;
+
+ if (offset == len) return true;
+ else return false;
+ },
+ isFocused: function()
+ {
+ var el, sel = this.getSelection();
+
+ if (sel && sel.rangeCount && sel.rangeCount > 0) el = sel.getRangeAt(0).startContainer;
+ if (!el) return false;
+ if (this.opts.iframe)
+ {
+ if (this.getCaretOffsetRange().equals()) return !this.$editor.is(el);
+ else return true;
+ }
+
+ return $(el).closest('div.redactor_editor').length != 0;
+ },
+ removeEmptyAttr: function (el, attr)
+ {
+ if ($(el).attr(attr) == '') $(el).removeAttr(attr);
+ },
+ removeFromArrayByValue: function(array, value)
+ {
+ var index = null;
+
+ while ((index = array.indexOf(value)) !== -1)
+ {
+ array.splice(index, 1);
+ }
+
+ return array;
}
+
};
-})(jQuery);
+ // constructor
+ Redactor.prototype.init.prototype = Redactor.prototype;
+ // LINKIFY
+ $.Redactor.fn.formatLinkify = function(protocol, convertLinks, convertImageLinks, convertVideoLinks, linkSize)
+ {
+ var url = /(((https?|ftps?):\/\/)|www[.][^\s])(.+?\..+?)([.),]?)(\s|\.\s+|\)|$)/gi,
+ rProtocol = /(https?|ftp):\/\//i,
+ urlImage = /(https?:\/\/.*\.(?:png|jpg|jpeg|gif))/gi;
-
-// Define: Linkify plugin from stackoverflow
-(function($){
-
- "use strict";
-
- var protocol = 'http://';
- var url1 = /(^|<|\s)(www\..+?\..+?)(\s|>|$)/g,
- url2 = /(^|<|\s)(((https?|ftp):\/\/|mailto:).+?)(\s|>|$)/g,
-
- linkifyThis = function ()
+ var childNodes = (this.$editor ? this.$editor.get(0) : this).childNodes, i = childNodes.length;
+ while (i--)
{
- var childNodes = this.childNodes,
- i = childNodes.length;
- while(i--)
+ var n = childNodes[i];
+ if (n.nodeType === 3)
{
- var n = childNodes[i];
- if (n.nodeType === 3)
- {
- var html = n.nodeValue;
- if (html)
- {
- html = html.replace(/&/g, '&')
- .replace(//g, '>')
- .replace(url1, '$1$2 $3')
- .replace(url2, '$1$2 $5');
+ var html = n.nodeValue;
+ // youtube & vimeo
+ if (convertVideoLinks && html)
+ {
+ var iframeStart = ' ';
+
+ if (html.match(reUrlYoutube))
+ {
+ html = html.replace(reUrlYoutube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
+ $(n).after(html).remove();
+ }
+ else if (html.match(reUrlVimeo))
+ {
+ html = html.replace(reUrlVimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
$(n).after(html).remove();
}
}
- else if (n.nodeType === 1 && !/^(a|button|textarea)$/i.test(n.tagName))
+
+ // image
+ if (convertImageLinks && html && html.match(urlImage))
{
- linkifyThis.call(n);
+ html = html.replace(urlImage, ' ');
+
+ $(n).after(html).remove();
+ }
+
+ // link
+ if (convertLinks && html && html.match(url))
+ {
+ var matches = html.match(url);
+
+ for (var i in matches)
+ {
+ var href = matches[i];
+ var text = href;
+
+ var space = '';
+ if (href.match(/\s$/) !== null) space = ' ';
+
+ var addProtocol = protocol;
+ if (href.match(rProtocol) !== null) addProtocol = '';
+
+ if (text.length > linkSize) text = text.substring(0, linkSize) + '...';
+
+ text = text.replace(/&/g, '&').replace(//g, '>')
+
+ /*
+ To handle URLs which may have $ characters in them, need to escape $ -> $$ to prevent $1 from getting treated as a backreference.
+ See http://gotofritz.net/blog/code-snippets/escaping-in-replace-strings-in-javascript/
+ */
+ var escapedBackReferences = text.replace('$', '$$$');
+
+ html = html.replace(href, '' + $.trim(escapedBackReferences) + ' ' + space);
+ }
+
+ $(n).after(html).remove();
}
}
- };
-
- $.fn.linkify = function ()
- {
- this.each(linkifyThis);
+ else if (n.nodeType === 1 && !/^(a|button|textarea)$/i.test(n.tagName))
+ {
+ $.Redactor.fn.formatLinkify.call(n, protocol, convertLinks, convertImageLinks, convertVideoLinks, linkSize);
+ }
+ }
};
-})(jQuery);
-
-
-/* jQuery plugin textselect
- * version: 0.9
- * author: Josef Moravec, josef.moravec@gmail.com
- * updated: Imperavi Inc.
- *
- */
-eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(5($){$.1.4.7={t:5(0,v){$(2).0("8",c);$(2).0("r",0);$(2).l(\'g\',$.1.4.7.b)},u:5(0){$(2).w(\'g\',$.1.4.7.b)},b:5(1){9 0=$(2).0("r");9 3=$.1.4.7.f(0).h();6(3!=\'\'){$(2).0("8",x);1.j="7";1.3=3;$.1.i.m(2,k)}},f:5(0){9 3=\'\';6(q.e){3=q.e()}o 6(d.e){3=d.e()}o 6(d.p){3=d.p.B().3}A 3}};$.1.4.a={t:5(0,v){$(2).0("n",0);$(2).0("8",c);$(2).l(\'g\',$.1.4.a.b);$(2).l(\'D\',$.1.4.a.s)},u:5(0){$(2).w(\'g\',$.1.4.a.b)},b:5(1){6($(2).0("8")){9 0=$(2).0("n");9 3=$.1.4.7.f(0).h();6(3==\'\'){$(2).0("8",c);1.j="a";$.1.i.m(2,k)}}},s:5(1){6($(2).0("8")){9 0=$(2).0("n");9 3=$.1.4.7.f(0).h();6((1.y=z)&&(3==\'\')){$(2).0("8",c);1.j="a";$.1.i.m(2,k)}}}}})(C);',40,40,'data|event|this|text|special|function|if|textselect|textselected|var|textunselect|handler|false|rdocument|getSelection|getSelectedText|mouseup|toString|handle|type|arguments|bind|apply|rttt|else|selection|rwindow|ttt|handlerKey|setup|teardown|namespaces|unbind|true|keyCode|27|return|createRange|jQuery|keyup'.split('|'),0,{}))
\ No newline at end of file
+})(jQuery);
\ No newline at end of file
diff --git a/app/assets/stylesheets/admin.css.less b/app/assets/stylesheets/admin.css.scss
similarity index 76%
rename from app/assets/stylesheets/admin.css.less
rename to app/assets/stylesheets/admin.css.scss
index 8bf3a13..8505616 100644
--- a/app/assets/stylesheets/admin.css.less
+++ b/app/assets/stylesheets/admin.css.scss
@@ -1,15 +1,39 @@
-@import "admin/framework/bootstrap.less";
+@import "bootstrap";
-// Font Awesome
@import "fontawesome/font-awesome";
-@import "admin/lesshat";
+//@import "admin/lesshat";
@import "manager";
@import "redactor";
-@import "admin/pane_hover";
+@import "pane_hover";
@import "vendor/select2";
+span.preview{
+img{
+max-width:125px;
+max-height:125px;
+cursor:pointer;
+}
+
+}
+img{
+
+max-width:100%;
+}
+
+html {
+ height: 100%;
+ width: 100%;
+
+}
+
+body {
+ height: 100%;
+ width: 100%;
+
+
+}
#tags .tag_label{
@@ -65,9 +89,7 @@ border:1px solid #0088cc;
display:inline-block;
padding:6px;
border-radius:50%;
-font-size:1.1em;
-width:1.1em;
-height:1.1em;
+
text-align:center;
background:white;
@@ -100,13 +122,13 @@ text-decoration:none;
background:white;
box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);
- background-color: @dropdownBackground;
+ //background-color: @dropdownBackground;
border: 1px solid #ccc; // Fallback for IE7-8
- border: 1px solid @dropdownBorder;
+ //border: 1px solid @dropdownBorder;
*border-right-width: 2px;
*border-bottom-width: 2px;
- .border-radius(6px);
- .box-shadow(0 5px 10px rgba(0,0,0,.2));
+ //.border-radius(6px);
+ //.box-shadow(0 5px 10px rgba(0,0,0,.2));
@@ -155,9 +177,12 @@ text-decoration:none;
#toolbar-text{
position:fixed;
- top:40px;
+ z-index:2;
+
+ top:52px;
left:0px;
- right:0px;
+ right:330px;
+
}
@@ -268,11 +293,29 @@ text-decoration:none;
}
#menu_item_informations{
+
+
+ form{
+
+ .preview{
+
+ img{
+ height:50px;
+
+ }
+ }
+ }
+
position:fixed;
- top:100px;
- right:2em;
+ z-index:3;
+ overflow:auto;
+ box-shadow:rgba(0,0,0,1) 0px 0px 5px;
+ margin-bottom:0px;
+ top:52px;
+ right:0px;
width:330px;
- height:70%;
+ bottom:0px;
+ background:white;
.placeholder{
display:inline-block;
width:91px;
@@ -280,11 +323,7 @@ text-decoration:none;
margin:0px;
}
- .portlet{
- display:inline-block;
-
-
- }
+
}
@@ -301,18 +340,14 @@ text-decoration:none;
}
- .portlet{
-
-
-
- }
+
#menu_item_inspector_container{
.accordion{
- box-shadow:rgba(0,0,0,1) 0px 0px 5px;
+
height:auto;
- background:black;
+
}
.accordion-group{
@@ -349,13 +384,16 @@ text-decoration:none;
}
- .portlet{
+ .content_type{
+ display:inline-block;
img{height:50px;cursor:pointer;}
+
}
}
.btn-toolbar{
display:none;
+ top:-35px;
}
@@ -502,3 +540,101 @@ text-decoration:none;
}
+
+.event_date_form{
+ background:rgba(143,193,46,0.9);
+ margin:0px -10px 20px -10px;
+ padding:10px;
+
+ color:black;
+
+ p{
+ line-height:35px;
+ }
+
+ label{
+ display:inline;
+ }
+
+}
+
+
+.field_with_suppr{
+ display:inline-block;
+ position:relative;
+
+ .suppr{
+
+ display:block;
+ position:absolute;
+ top:7px;
+ right:5px;
+ img{
+ cursor:pointer;
+ }
+
+ }
+
+}
+
+.periodes_form .field, .jockers_form .field{
+border:1px solid #5b94c7;
+margin:0.5em;
+}
+
+
+.table-striped{
+
+ tr:nth-child(odd) {
+ td, th{
+ background:#f9f9f9 !important;
+ }}
+
+}
+
+@media print {
+ .visible-print { display: inherit !important; }
+ .hidden-print { display: none !important; }
+
+
+
+
+}
+
+.portlet_placeholder{
+background:rgba(80,80,80,0.5);
+
+height:5px;
+
+i{
+display:none;
+top:-20px;
+left:-5px;
+font-size:15px;
+
+padding:5px;
+
+
+}
+&:hover{
+background:rgba(80,80,80,1);
+
+i{
+display:block;
+position:absolute;top:-9px;
+}
+}
+
+}
+.portlet{
+cursor:pointer;
+box-sizing: border-box;
+&.active{
+border:3px solid rgba(129,155,237,1);
+}
+
+&.move{
+opacity:0.5;
+}
+
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/admin_auth.css.less b/app/assets/stylesheets/admin_auth.css.scss
similarity index 76%
rename from app/assets/stylesheets/admin_auth.css.less
rename to app/assets/stylesheets/admin_auth.css.scss
index 2d0f52f..c329316 100644
--- a/app/assets/stylesheets/admin_auth.css.less
+++ b/app/assets/stylesheets/admin_auth.css.scss
@@ -1,5 +1,4 @@
-@import "admin/framework/bootstrap.less";
-@import "admin/lesshat";
+@import "bootstrap";
body {
padding:10px;
@@ -12,8 +11,8 @@ padding:10px;
margin: 0 auto 20px;
background-color: #fff;
border: 1px solid #e5e5e5;
- .border-radius(5px);
- .box-shadow(0 1px 2px rgba(0,0,0,.05));
+ border-radius :5px;
+ box-shadow: 0 1px 2px rgba(0,0,0,.05);
}
diff --git a/app/assets/stylesheets/bootstrap.scss b/app/assets/stylesheets/bootstrap.scss
new file mode 100644
index 0000000..e6e336f
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap.scss
@@ -0,0 +1,52 @@
+// Core variables and mixins
+@import "bootstrap/variables";
+@import "bootstrap/mixins";
+
+// Reset
+@import "bootstrap/normalize";
+@import "bootstrap/print";
+
+// Core CSS
+@import "bootstrap/scaffolding";
+@import "bootstrap/type";
+@import "bootstrap/code";
+@import "bootstrap/grid";
+@import "bootstrap/tables";
+@import "bootstrap/forms";
+@import "bootstrap/buttons";
+
+// Components
+@import "bootstrap/component-animations";
+@import "bootstrap/glyphicons";
+@import "bootstrap/dropdowns";
+@import "bootstrap/button-groups";
+@import "bootstrap/input-groups";
+@import "bootstrap/navs";
+@import "bootstrap/navbar";
+@import "bootstrap/breadcrumbs";
+@import "bootstrap/pagination";
+@import "bootstrap/pager";
+@import "bootstrap/labels";
+@import "bootstrap/badges";
+@import "bootstrap/jumbotron";
+@import "bootstrap/thumbnails";
+@import "bootstrap/alerts";
+@import "bootstrap/progress-bars";
+@import "bootstrap/media";
+@import "bootstrap/list-group";
+@import "bootstrap/panels";
+@import "bootstrap/wells";
+@import "bootstrap/close";
+
+// Components w/ JavaScript
+@import "bootstrap/modals";
+@import "bootstrap/tooltip";
+@import "bootstrap/popovers";
+@import "bootstrap/carousel";
+
+// Utility classes
+@import "bootstrap/utilities";
+@import "bootstrap/responsive-utilities";
+
+@import "bootstrap/slider";
+@import "bootstrap/datetimepicker";
diff --git a/app/assets/stylesheets/bootstrap/_alerts.scss b/app/assets/stylesheets/bootstrap/_alerts.scss
new file mode 100644
index 0000000..4685ac3
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_alerts.scss
@@ -0,0 +1,67 @@
+//
+// Alerts
+// --------------------------------------------------
+
+
+// Base styles
+// -------------------------
+
+.alert {
+ padding: $alert-padding;
+ margin-bottom: $line-height-computed;
+ border: 1px solid transparent;
+ border-radius: $alert-border-radius;
+
+ // Headings for larger alerts
+ h4 {
+ margin-top: 0;
+ // Specified for the h4 to prevent conflicts of changing $headings-color
+ color: inherit;
+ }
+ // Provide class for links that match alerts
+ .alert-link {
+ font-weight: $alert-link-font-weight;
+ }
+
+ // Improve alignment and spacing of inner content
+ > p,
+ > ul {
+ margin-bottom: 0;
+ }
+ > p + p {
+ margin-top: 5px;
+ }
+}
+
+// Dismissable alerts
+//
+// Expand the right padding and account for the close button's positioning.
+
+.alert-dismissable {
+ padding-right: ($alert-padding + 20);
+
+ // Adjust close link position
+ .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ color: inherit;
+ }
+}
+
+// Alternate styles
+//
+// Generate contextual modifier classes for colorizing the alert.
+
+.alert-success {
+ @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text);
+}
+.alert-info {
+ @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text);
+}
+.alert-warning {
+ @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text);
+}
+.alert-danger {
+ @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text);
+}
diff --git a/app/assets/stylesheets/bootstrap/_badges.scss b/app/assets/stylesheets/bootstrap/_badges.scss
new file mode 100644
index 0000000..4014a80
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_badges.scss
@@ -0,0 +1,55 @@
+//
+// Badges
+// --------------------------------------------------
+
+
+// Base classes
+.badge {
+ display: inline-block;
+ min-width: 10px;
+ padding: 3px 7px;
+ font-size: $font-size-small;
+ font-weight: $badge-font-weight;
+ color: $badge-color;
+ line-height: $badge-line-height;
+ vertical-align: baseline;
+ white-space: nowrap;
+ text-align: center;
+ background-color: $badge-bg;
+ border-radius: $badge-border-radius;
+
+ // Empty badges collapse automatically (not available in IE8)
+ &:empty {
+ display: none;
+ }
+
+ // Quick fix for badges in buttons
+ .btn & {
+ position: relative;
+ top: -1px;
+ }
+ .btn-xs & {
+ top: 0;
+ padding: 1px 5px;
+ }
+}
+
+// Hover state, but only for links
+a.badge {
+ &:hover,
+ &:focus {
+ color: $badge-link-hover-color;
+ text-decoration: none;
+ cursor: pointer;
+ }
+}
+
+// Account for counters in navs
+a.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+ color: $badge-active-color;
+ background-color: $badge-active-bg;
+}
+.nav-pills > li > a > .badge {
+ margin-left: 3px;
+}
diff --git a/app/assets/stylesheets/bootstrap/_breadcrumbs.scss b/app/assets/stylesheets/bootstrap/_breadcrumbs.scss
new file mode 100644
index 0000000..3641e33
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_breadcrumbs.scss
@@ -0,0 +1,26 @@
+//
+// Breadcrumbs
+// --------------------------------------------------
+
+
+.breadcrumb {
+ padding: $breadcrumb-padding-vertical $breadcrumb-padding-horizontal;
+ margin-bottom: $line-height-computed;
+ list-style: none;
+ background-color: $breadcrumb-bg;
+ border-radius: $border-radius-base;
+
+ > li {
+ display: inline-block;
+
+ + li:before {
+ content: "#{$breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space
+ padding: 0 5px;
+ color: $breadcrumb-color;
+ }
+ }
+
+ > .active {
+ color: $breadcrumb-active-color;
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_button-groups.scss b/app/assets/stylesheets/bootstrap/_button-groups.scss
new file mode 100644
index 0000000..066b4d7
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_button-groups.scss
@@ -0,0 +1,226 @@
+//
+// Button groups
+// --------------------------------------------------
+
+// Make the div behave like a button
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle; // match .btn alignment given font-size hack above
+ > .btn {
+ position: relative;
+ float: left;
+ // Bring the "active" button to the front
+ &:hover,
+ &:focus,
+ &:active,
+ &.active {
+ z-index: 2;
+ }
+ &:focus {
+ // Remove focus outline when dropdown JS adds it after closing the menu
+ outline: none;
+ }
+ }
+}
+
+// Prevent double borders when buttons are next to each other
+.btn-group {
+ .btn + .btn,
+ .btn + .btn-group,
+ .btn-group + .btn,
+ .btn-group + .btn-group {
+ margin-left: -1px;
+ }
+}
+
+// Optional: Group multiple button groups together for a toolbar
+.btn-toolbar {
+ margin-left: -5px; // Offset the first child's margin
+ @include clearfix();
+
+ .btn-group,
+ .input-group {
+ float: left;
+ }
+ > .btn,
+ > .btn-group,
+ > .input-group {
+ margin-left: 5px;
+ }
+}
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0;
+}
+
+// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
+.btn-group > .btn:first-child {
+ margin-left: 0;
+ &:not(:last-child):not(.dropdown-toggle) {
+ @include border-right-radius(0);
+ }
+}
+// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ @include border-left-radius(0);
+}
+
+// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)
+.btn-group > .btn-group {
+ float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group > .btn-group:first-child {
+ > .btn:last-child,
+ > .dropdown-toggle {
+ @include border-right-radius(0);
+ }
+}
+.btn-group > .btn-group:last-child > .btn:first-child {
+ @include border-left-radius(0);
+}
+
+// On active and open, don't show outline
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+
+
+// Sizing
+//
+// Remix the default button sizing classes into new ones for easier manipulation.
+
+.btn-group-xs > .btn { @extend .btn-xs; }
+.btn-group-sm > .btn { @extend .btn-sm; }
+.btn-group-lg > .btn { @extend .btn-lg; }
+
+
+// Split button dropdowns
+// ----------------------
+
+// Give the line between buttons some depth
+.btn-group > .btn + .dropdown-toggle {
+ padding-left: 8px;
+ padding-right: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+ padding-left: 12px;
+ padding-right: 12px;
+}
+
+// The clickable button for toggling the menu
+// Remove the gradient and set the same inset shadow as the :active state
+.btn-group.open .dropdown-toggle {
+ @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
+
+ // Show no shadow for `.btn-link` since it has no other button styles.
+ &.btn-link {
+ @include box-shadow(none);
+ }
+}
+
+
+// Reposition the caret
+.btn .caret {
+ margin-left: 0;
+}
+// Carets in other button sizes
+.btn-lg .caret {
+ border-width: $caret-width-large $caret-width-large 0;
+ border-bottom-width: 0;
+}
+// Upside down carets for .dropup
+.dropup .btn-lg .caret {
+ border-width: 0 $caret-width-large $caret-width-large;
+}
+
+
+// Vertical button groups
+// ----------------------
+
+.btn-group-vertical {
+ > .btn,
+ > .btn-group,
+ > .btn-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ max-width: 100%;
+ }
+
+ // Clear floats so dropdown menus can be properly placed
+ > .btn-group {
+ @include clearfix();
+ > .btn {
+ float: none;
+ }
+ }
+
+ > .btn + .btn,
+ > .btn + .btn-group,
+ > .btn-group + .btn,
+ > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0;
+ }
+}
+
+.btn-group-vertical > .btn {
+ &:not(:first-child):not(:last-child) {
+ border-radius: 0;
+ }
+ &:first-child:not(:last-child) {
+ border-top-right-radius: $border-radius-base;
+ @include border-bottom-radius(0);
+ }
+ &:last-child:not(:first-child) {
+ border-bottom-left-radius: $border-radius-base;
+ @include border-top-radius(0);
+ }
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) {
+ > .btn:last-child,
+ > .dropdown-toggle {
+ @include border-bottom-radius(0);
+ }
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ @include border-top-radius(0);
+}
+
+
+
+// Justified button groups
+// ----------------------
+
+.btn-group-justified {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ border-collapse: separate;
+ > .btn,
+ > .btn-group {
+ float: none;
+ display: table-cell;
+ width: 1%;
+ }
+ > .btn-group .btn {
+ width: 100%;
+ }
+}
+
+
+// Checkbox and radio options
+[data-toggle="buttons"] > .btn > input[type="radio"],
+[data-toggle="buttons"] > .btn > input[type="checkbox"] {
+ display: none;
+}
diff --git a/app/assets/stylesheets/bootstrap/_buttons.scss b/app/assets/stylesheets/bootstrap/_buttons.scss
new file mode 100644
index 0000000..28110b6
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_buttons.scss
@@ -0,0 +1,159 @@
+//
+// Buttons
+// --------------------------------------------------
+
+
+// Base styles
+// --------------------------------------------------
+
+.btn {
+ display: inline-block;
+ margin-bottom: 0; // For input.btn
+ font-weight: $btn-font-weight;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
+ border: 1px solid transparent;
+ white-space: nowrap;
+ @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $border-radius-base);
+ @include user-select(none);
+
+ &,
+ &:active,
+ &.active {
+ &:focus {
+ @include tab-focus();
+ }
+ }
+
+ &:hover,
+ &:focus {
+ color: $btn-default-color;
+ text-decoration: none;
+ }
+
+ &:active,
+ &.active {
+ outline: 0;
+ background-image: none;
+ @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
+ }
+
+ &.disabled,
+ &[disabled],
+ fieldset[disabled] & {
+ cursor: not-allowed;
+ pointer-events: none; // Future-proof disabling of clicks
+ @include opacity(.65);
+ @include box-shadow(none);
+ }
+}
+
+
+// Alternate buttons
+// --------------------------------------------------
+
+.btn-default {
+ @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border);
+}
+.btn-primary {
+ @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border);
+}
+// Success appears as green
+.btn-success {
+ @include button-variant($btn-success-color, $btn-success-bg, $btn-success-border);
+}
+// Info appears as blue-green
+.btn-info {
+ @include button-variant($btn-info-color, $btn-info-bg, $btn-info-border);
+}
+// Warning appears as orange
+.btn-warning {
+ @include button-variant($btn-warning-color, $btn-warning-bg, $btn-warning-border);
+}
+// Danger and error appear as red
+.btn-danger {
+ @include button-variant($btn-danger-color, $btn-danger-bg, $btn-danger-border);
+}
+
+
+// Link buttons
+// -------------------------
+
+// Make a button look and behave like a link
+.btn-link {
+ color: $link-color;
+ font-weight: normal;
+ cursor: pointer;
+ border-radius: 0;
+
+ &,
+ &:active,
+ &[disabled],
+ fieldset[disabled] & {
+ background-color: transparent;
+ @include box-shadow(none);
+ }
+ &,
+ &:hover,
+ &:focus,
+ &:active {
+ border-color: transparent;
+ }
+ &:hover,
+ &:focus {
+ color: $link-hover-color;
+ text-decoration: underline;
+ background-color: transparent;
+ }
+ &[disabled],
+ fieldset[disabled] & {
+ &:hover,
+ &:focus {
+ color: $btn-link-disabled-color;
+ text-decoration: none;
+ }
+ }
+}
+
+
+// Button Sizes
+// --------------------------------------------------
+
+.btn-lg {
+ // line-height: ensure even-numbered height of button next to large input
+ @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large);
+}
+.btn-sm {
+ // line-height: ensure proper height of button next to small input
+ @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small);
+}
+.btn-xs {
+ @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $border-radius-small);
+}
+
+
+// Block button
+// --------------------------------------------------
+
+.btn-block {
+ display: block;
+ width: 100%;
+ padding-left: 0;
+ padding-right: 0;
+}
+
+// Vertically space out multiple block buttons
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+
+// Specificity overrides
+input[type="submit"],
+input[type="reset"],
+input[type="button"] {
+ &.btn-block {
+ width: 100%;
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_carousel.scss b/app/assets/stylesheets/bootstrap/_carousel.scss
new file mode 100644
index 0000000..d8f2364
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_carousel.scss
@@ -0,0 +1,232 @@
+//
+// Carousel
+// --------------------------------------------------
+
+
+// Wrapper for the slide container and indicators
+.carousel {
+ position: relative;
+}
+
+.carousel-inner {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+
+ > .item {
+ display: none;
+ position: relative;
+ @include transition(.6s ease-in-out left);
+
+ // Account for jankitude on images
+ > img,
+ > a > img {
+ @include img-responsive();
+ line-height: 1;
+ }
+ }
+
+ > .active,
+ > .next,
+ > .prev { display: block; }
+
+ > .active {
+ left: 0;
+ }
+
+ > .next,
+ > .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+ }
+
+ > .next {
+ left: 100%;
+ }
+ > .prev {
+ left: -100%;
+ }
+ > .next.left,
+ > .prev.right {
+ left: 0;
+ }
+
+ > .active.left {
+ left: -100%;
+ }
+ > .active.right {
+ left: 100%;
+ }
+
+}
+
+// Left/right controls for nav
+// ---------------------------
+
+.carousel-control {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: $carousel-control-width;
+ @include opacity($carousel-control-opacity);
+ font-size: $carousel-control-font-size;
+ color: $carousel-control-color;
+ text-align: center;
+ text-shadow: $carousel-text-shadow;
+ // We can't have this transition here because WebKit cancels the carousel
+ // animation if you trip this while in the middle of another animation.
+
+ // Set gradients for backgrounds
+ &.left {
+ @include gradient-horizontal($start-color: rgba(0,0,0,.5), $end-color: rgba(0,0,0,.0001));
+ }
+ &.right {
+ left: auto;
+ right: 0;
+ @include gradient-horizontal($start-color: rgba(0,0,0,.0001), $end-color: rgba(0,0,0,.5));
+ }
+
+ // Hover/focus state
+ &:hover,
+ &:focus {
+ outline: none;
+ color: $carousel-control-color;
+ text-decoration: none;
+ @include opacity(.9);
+ }
+
+ // Toggles
+ .icon-prev,
+ .icon-next,
+ .glyphicon-chevron-left,
+ .glyphicon-chevron-right {
+ position: absolute;
+ top: 50%;
+ z-index: 5;
+ display: inline-block;
+ }
+ .icon-prev,
+ .glyphicon-chevron-left {
+ left: 50%;
+ }
+ .icon-next,
+ .glyphicon-chevron-right {
+ right: 50%;
+ }
+ .icon-prev,
+ .icon-next {
+ width: 20px;
+ height: 20px;
+ margin-top: -10px;
+ margin-left: -10px;
+ font-family: serif;
+ }
+
+ .icon-prev {
+ &:before {
+ content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)
+ }
+ }
+ .icon-next {
+ &:before {
+ content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)
+ }
+ }
+}
+
+// Optional indicator pips
+//
+// Add an unordered list with the following class and add a list item for each
+// slide your carousel holds.
+
+.carousel-indicators {
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ z-index: 15;
+ width: 60%;
+ margin-left: -30%;
+ padding-left: 0;
+ list-style: none;
+ text-align: center;
+
+ li {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin: 1px;
+ text-indent: -999px;
+ border: 1px solid $carousel-indicator-border-color;
+ border-radius: 10px;
+ cursor: pointer;
+
+ // IE8-9 hack for event handling
+ //
+ // Internet Explorer 8-9 does not support clicks on elements without a set
+ // `background-color`. We cannot use `filter` since that's not viewed as a
+ // background color by the browser. Thus, a hack is needed.
+ //
+ // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we
+ // set alpha transparency for the best results possible.
+ background-color: #000 \9; // IE8
+ background-color: rgba(0,0,0,0); // IE9
+ }
+ .active {
+ margin: 0;
+ width: 12px;
+ height: 12px;
+ background-color: $carousel-indicator-active-bg;
+ }
+}
+
+// Optional captions
+// -----------------------------
+// Hidden by default for smaller viewports
+.carousel-caption {
+ position: absolute;
+ left: 15%;
+ right: 15%;
+ bottom: 20px;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: $carousel-caption-color;
+ text-align: center;
+ text-shadow: $carousel-text-shadow;
+ & .btn {
+ text-shadow: none; // No shadow for button elements in carousel-caption
+ }
+}
+
+
+// Scale up controls for tablets and up
+@media screen and (min-width: $screen-sm-min) {
+
+ // Scale up the controls a smidge
+ .carousel-control {
+ .glyphicon-chevron-left,
+ .glyphicon-chevron-right,
+ .icon-prev,
+ .icon-next {
+ width: 30px;
+ height: 30px;
+ margin-top: -15px;
+ margin-left: -15px;
+ font-size: 30px;
+ }
+ }
+
+ // Show and left align the captions
+ .carousel-caption {
+ left: 20%;
+ right: 20%;
+ padding-bottom: 30px;
+ }
+
+ // Move up the indicators
+ .carousel-indicators {
+ bottom: 20px;
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_close.scss b/app/assets/stylesheets/bootstrap/_close.scss
new file mode 100644
index 0000000..62ce30f
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_close.scss
@@ -0,0 +1,35 @@
+//
+// Close icons
+// --------------------------------------------------
+
+
+.close {
+ float: right;
+ font-size: ($font-size-base * 1.5);
+ font-weight: $close-font-weight;
+ line-height: 1;
+ color: $close-color;
+ text-shadow: $close-text-shadow;
+ @include opacity(.2);
+
+ &:hover,
+ &:focus {
+ color: $close-color;
+ text-decoration: none;
+ cursor: pointer;
+ @include opacity(.5);
+ }
+
+ // [converter] extracted button& to button.close
+}
+
+// Additional properties for button version
+// iOS requires the button element instead of an anchor tag.
+// If you want the anchor version, it requires `href="#"`.
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
diff --git a/app/assets/stylesheets/bootstrap/_code.scss b/app/assets/stylesheets/bootstrap/_code.scss
new file mode 100644
index 0000000..8953616
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_code.scss
@@ -0,0 +1,63 @@
+//
+// Code (inline and block)
+// --------------------------------------------------
+
+
+// Inline and block code styles
+code,
+kbd,
+pre,
+samp {
+ font-family: $font-family-monospace;
+}
+
+// Inline code
+code {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: $code-color;
+ background-color: $code-bg;
+ white-space: nowrap;
+ border-radius: $border-radius-base;
+}
+
+// User input typically entered via keyboard
+kbd {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: $kbd-color;
+ background-color: $kbd-bg;
+ border-radius: $border-radius-small;
+ box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
+}
+
+// Blocks of code
+pre {
+ display: block;
+ padding: (($line-height-computed - 1) / 2);
+ margin: 0 0 ($line-height-computed / 2);
+ font-size: ($font-size-base - 1); // 14px to 13px
+ line-height: $line-height-base;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: $pre-color;
+ background-color: $pre-bg;
+ border: 1px solid $pre-border-color;
+ border-radius: $border-radius-base;
+
+ // Account for some code outputs that place code tags in pre tags
+ code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border-radius: 0;
+ }
+}
+
+// Enable scrollable blocks of code
+.pre-scrollable {
+ max-height: $pre-scrollable-max-height;
+ overflow-y: scroll;
+}
diff --git a/app/assets/stylesheets/bootstrap/_component-animations.scss b/app/assets/stylesheets/bootstrap/_component-animations.scss
new file mode 100644
index 0000000..86632fd
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_component-animations.scss
@@ -0,0 +1,29 @@
+//
+// Component animations
+// --------------------------------------------------
+
+// Heads up!
+//
+// We don't use the `.opacity()` mixin here since it causes a bug with text
+// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.
+
+.fade {
+ opacity: 0;
+ @include transition(opacity .15s linear);
+ &.in {
+ opacity: 1;
+ }
+}
+
+.collapse {
+ display: none;
+ &.in {
+ display: block;
+ }
+}
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ @include transition(height .35s ease);
+}
diff --git a/app/assets/stylesheets/bootstrap/_datetimepicker.scss b/app/assets/stylesheets/bootstrap/_datetimepicker.scss
new file mode 100755
index 0000000..f9c5a4f
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_datetimepicker.scss
@@ -0,0 +1,229 @@
+/*!
+ * Datetimepicker for Bootstrap v3
+ * https://github.com/Eonasdan/bootstrap-datetimepicker/
+ */
+.bootstrap-datetimepicker-widget {
+ top: 0;
+ left: 0;
+ width: 250px;
+ padding: 4px;
+ margin-top: 1px;
+ z-index: 99999 !important;
+ border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget.timepicker-sbs {
+ width: 600px;
+}
+.bootstrap-datetimepicker-widget.bottom:before {
+ content: '';
+ display: inline-block;
+ border-left: 7px solid transparent;
+ border-right: 7px solid transparent;
+ border-bottom: 7px solid #ccc;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ position: absolute;
+ top: -7px;
+ left: 7px;
+}
+.bootstrap-datetimepicker-widget.bottom:after {
+ content: '';
+ display: inline-block;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid white;
+ position: absolute;
+ top: -6px;
+ left: 8px;
+}
+.bootstrap-datetimepicker-widget.top:before {
+ content: '';
+ display: inline-block;
+ border-left: 7px solid transparent;
+ border-right: 7px solid transparent;
+ border-top: 7px solid #ccc;
+ border-top-color: rgba(0, 0, 0, 0.2);
+ position: absolute;
+ bottom: -7px;
+ left: 6px;
+}
+.bootstrap-datetimepicker-widget.top:after {
+ content: '';
+ display: inline-block;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-top: 6px solid white;
+ position: absolute;
+ bottom: -6px;
+ left: 7px;
+}
+.bootstrap-datetimepicker-widget .dow {
+ width: 14.2857%;
+}
+.bootstrap-datetimepicker-widget.pull-right:before {
+ left: auto;
+ right: 6px;
+}
+.bootstrap-datetimepicker-widget.pull-right:after {
+ left: auto;
+ right: 7px;
+}
+.bootstrap-datetimepicker-widget > ul {
+ list-style-type: none;
+ margin: 0;
+}
+.bootstrap-datetimepicker-widget a[data-action] {
+ padding: 6px 0;
+}
+.bootstrap-datetimepicker-widget .timepicker-hour,
+.bootstrap-datetimepicker-widget .timepicker-minute,
+.bootstrap-datetimepicker-widget .timepicker-second {
+ width: 54px;
+ font-weight: bold;
+ font-size: 1.2em;
+ margin: 0;
+}
+.bootstrap-datetimepicker-widget button[data-action] {
+ padding: 6px;
+}
+.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator {
+ width: 4px;
+ padding: 0;
+ margin: 0;
+}
+.bootstrap-datetimepicker-widget .datepicker > div {
+ display: none;
+}
+.bootstrap-datetimepicker-widget .picker-switch {
+ text-align: center;
+}
+.bootstrap-datetimepicker-widget table {
+ width: 100%;
+ margin: 0;
+}
+.bootstrap-datetimepicker-widget td,
+.bootstrap-datetimepicker-widget th {
+ text-align: center;
+ border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget td {
+ height: 54px;
+ line-height: 54px;
+ width: 54px;
+}
+.bootstrap-datetimepicker-widget td.day {
+ height: 20px;
+ line-height: 20px;
+ width: 20px;
+}
+.bootstrap-datetimepicker-widget td.day:hover,
+.bootstrap-datetimepicker-widget td.hour:hover,
+.bootstrap-datetimepicker-widget td.minute:hover,
+.bootstrap-datetimepicker-widget td.second:hover {
+ background: #eeeeee;
+ cursor: pointer;
+}
+.bootstrap-datetimepicker-widget td.old,
+.bootstrap-datetimepicker-widget td.new {
+ color: #999999;
+}
+.bootstrap-datetimepicker-widget td.today {
+ position: relative;
+}
+.bootstrap-datetimepicker-widget td.today:before {
+ content: '';
+ display: inline-block;
+ border-left: 7px solid transparent;
+ border-bottom: 7px solid #428bca;
+ border-top-color: rgba(0, 0, 0, 0.2);
+ position: absolute;
+ bottom: 4px;
+ right: 4px;
+}
+.bootstrap-datetimepicker-widget td.active,
+.bootstrap-datetimepicker-widget td.active:hover {
+ background-color: #428bca;
+ color: #fff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.bootstrap-datetimepicker-widget td.active.today:before {
+ border-bottom-color: #fff;
+}
+.bootstrap-datetimepicker-widget td.disabled,
+.bootstrap-datetimepicker-widget td.disabled:hover {
+ background: none;
+ color: #999999;
+ cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget td span {
+ display: block;
+ width: 54px;
+ height: 54px;
+ line-height: 54px;
+ float: left;
+ margin: 2px 1.5px;
+ cursor: pointer;
+ border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget td span:hover {
+ background: #eeeeee;
+}
+.bootstrap-datetimepicker-widget td span.active {
+ background-color: #428bca;
+ color: #fff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.bootstrap-datetimepicker-widget td span.old {
+ color: #999999;
+}
+.bootstrap-datetimepicker-widget td span.disabled,
+.bootstrap-datetimepicker-widget td span.disabled:hover {
+ background: none;
+ color: #999999;
+ cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget th {
+ height: 20px;
+ line-height: 20px;
+ width: 20px;
+}
+.bootstrap-datetimepicker-widget th.switch {
+ width: 145px;
+}
+.bootstrap-datetimepicker-widget th.next,
+.bootstrap-datetimepicker-widget th.prev {
+ font-size: 21px;
+}
+.bootstrap-datetimepicker-widget th.disabled,
+.bootstrap-datetimepicker-widget th.disabled:hover {
+ background: none;
+ color: #999999;
+ cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget thead tr:first-child th {
+ cursor: pointer;
+}
+.bootstrap-datetimepicker-widget thead tr:first-child th:hover {
+ background: #eeeeee;
+}
+.input-group.date .input-group-addon span {
+ display: block;
+ cursor: pointer;
+ width: 16px;
+ height: 16px;
+}
+.bootstrap-datetimepicker-widget.left-oriented:before {
+ left: auto;
+ right: 6px;
+}
+.bootstrap-datetimepicker-widget.left-oriented:after {
+ left: auto;
+ right: 7px;
+}
+.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody > tr > td {
+ padding: 0px !important;
+}
+@media screen and (max-width: 767px) {
+ .bootstrap-datetimepicker-widget.timepicker-sbs {
+ width: 283px;
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_dropdowns.scss b/app/assets/stylesheets/bootstrap/_dropdowns.scss
new file mode 100644
index 0000000..526be5b
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_dropdowns.scss
@@ -0,0 +1,213 @@
+//
+// Dropdown menus
+// --------------------------------------------------
+
+
+// Dropdown arrow/caret
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: $caret-width-base solid;
+ border-right: $caret-width-base solid transparent;
+ border-left: $caret-width-base solid transparent;
+}
+
+// The dropdown wrapper (div)
+.dropdown {
+ position: relative;
+}
+
+// Prevent the focus on the dropdown toggle when closing dropdowns
+.dropdown-toggle:focus {
+ outline: 0;
+}
+
+// The dropdown menu (ul)
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: $zindex-dropdown;
+ display: none; // none by default, but block on "open" of the menu
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0; // override default ul
+ list-style: none;
+ font-size: $font-size-base;
+ background-color: $dropdown-bg;
+ border: 1px solid $dropdown-fallback-border; // IE8 fallback
+ border: 1px solid $dropdown-border;
+ border-radius: $border-radius-base;
+ @include box-shadow(0 6px 12px rgba(0,0,0,.175));
+ background-clip: padding-box;
+
+ // Aligns the dropdown menu to right
+ //
+ // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`
+ &.pull-right {
+ right: 0;
+ left: auto;
+ }
+
+ // Dividers (basically an hr) within the dropdown
+ .divider {
+ @include nav-divider($dropdown-divider-bg);
+ }
+
+ // Links within the dropdown menu
+ > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: $line-height-base;
+ color: $dropdown-link-color;
+ white-space: nowrap; // prevent links from randomly breaking onto new lines
+ }
+}
+
+// Hover/Focus state
+.dropdown-menu > li > a {
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ color: $dropdown-link-hover-color;
+ background-color: $dropdown-link-hover-bg;
+ }
+}
+
+// Active state
+.dropdown-menu > .active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $dropdown-link-active-color;
+ text-decoration: none;
+ outline: 0;
+ background-color: $dropdown-link-active-bg;
+ }
+}
+
+// Disabled state
+//
+// Gray out text and ensure the hover/focus state remains gray
+
+.dropdown-menu > .disabled > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $dropdown-link-disabled-color;
+ }
+}
+// Nuke hover/focus effects
+.dropdown-menu > .disabled > a {
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ background-color: transparent;
+ background-image: none; // Remove CSS gradient
+ @include reset-filter();
+ cursor: not-allowed;
+ }
+}
+
+// Open state for the dropdown
+.open {
+ // Show the menu
+ > .dropdown-menu {
+ display: block;
+ }
+
+ // Remove the outline when :focus is triggered
+ > a {
+ outline: 0;
+ }
+}
+
+// Menu positioning
+//
+// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown
+// menu with the parent.
+.dropdown-menu-right {
+ left: auto; // Reset the default from `.dropdown-menu`
+ right: 0;
+}
+// With v3, we enabled auto-flipping if you have a dropdown within a right
+// aligned nav component. To enable the undoing of that, we provide an override
+// to restore the default dropdown menu alignment.
+//
+// This is only for left-aligning a dropdown menu within a `.navbar-right` or
+// `.pull-right` nav component.
+.dropdown-menu-left {
+ left: 0;
+ right: auto;
+}
+
+// Dropdown section headers
+.dropdown-header {
+ display: block;
+ padding: 3px 20px;
+ font-size: $font-size-small;
+ line-height: $line-height-base;
+ color: $dropdown-header-color;
+}
+
+// Backdrop to catch body clicks on mobile, etc.
+.dropdown-backdrop {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ z-index: ($zindex-dropdown - 10);
+}
+
+// Right aligned dropdowns
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+
+// Allow for dropdowns to go bottom up (aka, dropup-menu)
+//
+// Just add .dropup after the standard .dropdown class and you're set, bro.
+// TODO: abstract this so that the navbar fixed styles are not placed here?
+
+.dropup,
+.navbar-fixed-bottom .dropdown {
+ // Reverse the caret
+ .caret {
+ border-top: 0;
+ border-bottom: $caret-width-base solid;
+ content: "";
+ }
+ // Different positioning for bottom up menu
+ .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 1px;
+ }
+}
+
+
+// Component alignment
+//
+// Reiterate per navbar.less and the modified component alignment there.
+
+@media (min-width: $grid-float-breakpoint) {
+ .navbar-right {
+ .dropdown-menu {
+ right: 0; left: auto;
+ }
+ // Necessary for overrides of the default right aligned menu.
+ // Will remove come v4 in all likelihood.
+ .dropdown-menu-left {
+ left: 0; right: auto;
+ }
+ }
+}
+
diff --git a/app/assets/stylesheets/bootstrap/_forms.scss b/app/assets/stylesheets/bootstrap/_forms.scss
new file mode 100644
index 0000000..2628238
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_forms.scss
@@ -0,0 +1,436 @@
+//
+// Forms
+// --------------------------------------------------
+
+
+// Normalize non-controls
+//
+// Restyle and baseline non-control form elements.
+
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,
+ // so we reset that to ensure it behaves more like a standard block element.
+ // See https://github.com/twbs/bootstrap/issues/12359.
+ min-width: 0;
+}
+
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: $line-height-computed;
+ font-size: ($font-size-base * 1.5);
+ line-height: inherit;
+ color: $legend-color;
+ border: 0;
+ border-bottom: 1px solid $legend-border-color;
+}
+
+label {
+ display: inline-block;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+
+
+// Normalize form controls
+//
+// While most of our form styles require extra classes, some basic normalization
+// is required to ensure optimum display with or without those classes to better
+// address browser inconsistencies.
+
+// Override content-box in Normalize (* isn't specific enough)
+input[type="search"] {
+ @include box-sizing(border-box);
+}
+
+// Position radios and checkboxes better
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9; /* IE8-9 */
+ line-height: normal;
+}
+
+// Set the height of file controls to match text inputs
+input[type="file"] {
+ display: block;
+}
+
+// Make range inputs behave like textual form controls
+input[type="range"] {
+ display: block;
+ width: 100%;
+}
+
+// Make multiple select elements height not fixed
+select[multiple],
+select[size] {
+ height: auto;
+}
+
+// Focus for file, radio, and checkbox
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ @include tab-focus();
+}
+
+// Adjust output element
+output {
+ display: block;
+ padding-top: ($padding-base-vertical + 1);
+ font-size: $font-size-base;
+ line-height: $line-height-base;
+ color: $input-color;
+}
+
+
+// Common form controls
+//
+// Shared size and type resets for form controls. Apply `.form-control` to any
+// of the following form controls:
+//
+// 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"]
+
+.form-control {
+ display: block;
+ width: 100%;
+ height: $input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)
+ padding: $padding-base-vertical $padding-base-horizontal;
+ font-size: $font-size-base;
+ line-height: $line-height-base;
+ color: $input-color;
+ background-color: $input-bg;
+ background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
+ border: 1px solid $input-border;
+ border-radius: $input-border-radius;
+ @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
+ @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
+
+ // Customize the `:focus` state to imitate native WebKit styles.
+ @include form-control-focus();
+
+ // Placeholder
+ @include placeholder();
+
+ // Disabled and read-only inputs
+ //
+ // HTML5 says that controls under a fieldset > legend:first-child won't be
+ // disabled if the fieldset is disabled. Due to implementation difficulty, we
+ // don't honor that edge case; we style them as disabled anyway.
+ &[disabled],
+ &[readonly],
+ fieldset[disabled] & {
+ cursor: not-allowed;
+ background-color: $input-bg-disabled;
+ opacity: 1; // iOS fix for unreadable disabled content
+ }
+
+ // [converter] extracted textarea& to textarea.form-control
+}
+
+// Reset height for `textarea`s
+textarea.form-control {
+ height: auto;
+}
+
+
+// Search inputs in iOS
+//
+// This overrides the extra rounded corners on search inputs in iOS so that our
+// `.form-control` class can properly style them. Note that this cannot simply
+// be added to `.form-control` as it's not specific enough. For details, see
+// https://github.com/twbs/bootstrap/issues/11586.
+
+input[type="search"] {
+ -webkit-appearance: none;
+}
+
+
+// Special styles for iOS date input
+//
+// In Mobile Safari, date inputs require a pixel line-height that matches the
+// given height of the input.
+
+input[type="date"] {
+ line-height: $input-height-base;
+}
+
+
+// Form groups
+//
+// Designed to help with the organization and spacing of vertical forms. For
+// horizontal forms, use the predefined grid classes.
+
+.form-group {
+ margin-bottom: 15px;
+}
+
+
+// Checkboxes and radios
+//
+// Indent the labels to position radios/checkboxes as hanging controls.
+
+.radio,
+.checkbox {
+ display: block;
+ min-height: $line-height-computed; // clear the floating input if there is no label text
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding-left: 20px;
+ label {
+ display: inline;
+ font-weight: normal;
+ cursor: pointer;
+ }
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+ float: left;
+ margin-left: -20px;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+ margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing
+}
+
+// Radios and checkboxes on same line
+.radio-inline,
+.checkbox-inline {
+ display: inline-block;
+ padding-left: 20px;
+ margin-bottom: 0;
+ vertical-align: middle;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+ margin-top: 0;
+ margin-left: 10px; // space out consecutive inline controls
+}
+
+// Apply same disabled cursor tweak as for inputs
+//
+// Note: Neither radios nor checkboxes can be readonly.
+input[type="radio"],
+input[type="checkbox"],
+.radio,
+.radio-inline,
+.checkbox,
+.checkbox-inline {
+ &[disabled],
+ fieldset[disabled] & {
+ cursor: not-allowed;
+ }
+}
+
+
+// Form control sizing
+//
+// Build on `.form-control` with modifier classes to decrease or increase the
+// height and font-size of form controls.
+
+@include input-size('.input-sm', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small);
+
+@include input-size('.input-lg', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large);
+
+
+// Form control feedback states
+//
+// Apply contextual and semantic states to individual form controls.
+
+.has-feedback {
+ // Enable absolute positioning
+ position: relative;
+
+ // Ensure icons don't overlap text
+ .form-control {
+ padding-right: ($input-height-base * 1.25);
+ }
+
+ // Feedback icon (requires .glyphicon classes)
+ .form-control-feedback {
+ position: absolute;
+ top: ($line-height-computed + 5); // Height of the `label` and its margin
+ right: 0;
+ display: block;
+ width: $input-height-base;
+ height: $input-height-base;
+ line-height: $input-height-base;
+ text-align: center;
+ }
+}
+
+// Feedback states
+.has-success {
+ @include form-control-validation($state-success-text, $state-success-text, $state-success-bg);
+}
+.has-warning {
+ @include form-control-validation($state-warning-text, $state-warning-text, $state-warning-bg);
+}
+.has-error {
+ @include form-control-validation($state-danger-text, $state-danger-text, $state-danger-bg);
+}
+
+
+// Static form control text
+//
+// Apply class to a `p` element to make any string of text align with labels in
+// a horizontal form layout.
+
+.form-control-static {
+ margin-bottom: 0; // Remove default margin from `p`
+}
+
+
+// Help text
+//
+// Apply to any element you wish to create light text for placement immediately
+// below a form control. Use for general help, formatting, or instructional text.
+
+.help-block {
+ display: block; // account for any element using help-block
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: lighten($text-color, 25%); // lighten the text some for contrast
+}
+
+
+
+// Inline forms
+//
+// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
+// forms begin stacked on extra small (mobile) devices and then go inline when
+// viewports reach <768px.
+//
+// Requires wrapping inputs and labels with `.form-group` for proper display of
+// default HTML form controls and our custom form controls (e.g., input groups).
+//
+// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
+
+.form-inline {
+
+ // Kick in the inline
+ @media (min-width: $screen-sm-min) {
+ // Inline-block all the things for "inline"
+ .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+
+ // In navbar-form, allow folks to *not* use `.form-group`
+ .form-control {
+ display: inline-block;
+ width: auto; // Prevent labels from stacking above inputs in `.form-group`
+ vertical-align: middle;
+ }
+ // Input groups need that 100% width though
+ .input-group > .form-control {
+ width: 100%;
+ }
+
+ .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+
+ // Remove default margin on radios/checkboxes that were used for stacking, and
+ // then undo the floating of radios and checkboxes to match (which also avoids
+ // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).
+ .radio,
+ .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-left: 0;
+ vertical-align: middle;
+ }
+ .radio input[type="radio"],
+ .checkbox input[type="checkbox"] {
+ float: none;
+ margin-left: 0;
+ }
+
+ // Validation states
+ //
+ // Reposition the icon because it's now within a grid column and columns have
+ // `position: relative;` on them. Also accounts for the grid gutter padding.
+ .has-feedback .form-control-feedback {
+ top: 0;
+ }
+ }
+}
+
+
+// Horizontal forms
+//
+// Horizontal forms are built on grid classes and allow you to create forms with
+// labels on the left and inputs on the right.
+
+.form-horizontal {
+
+ // Consistent vertical alignment of labels, radios, and checkboxes
+ .control-label,
+ .radio,
+ .checkbox,
+ .radio-inline,
+ .checkbox-inline {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: ($padding-base-vertical + 1); // Default padding plus a border
+ }
+ // Account for padding we're adding to ensure the alignment and of help text
+ // and other content below items
+ .radio,
+ .checkbox {
+ min-height: ($line-height-computed + ($padding-base-vertical + 1));
+ }
+
+ // Make form groups behave like rows
+ .form-group {
+ @include make-row();
+ }
+
+ .form-control-static {
+ padding-top: ($padding-base-vertical + 1);
+ }
+
+ // Only right align form labels here when the columns stop stacking
+ @media (min-width: $screen-sm-min) {
+ .control-label {
+ text-align: right;
+ }
+ }
+
+ // Validation states
+ //
+ // Reposition the icon because it's now within a grid column and columns have
+ // `position: relative;` on them. Also accounts for the grid gutter padding.
+ .has-feedback .form-control-feedback {
+ top: 0;
+ right: ($grid-gutter-width / 2);
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_glyphicons.scss b/app/assets/stylesheets/bootstrap/_glyphicons.scss
new file mode 100644
index 0000000..c508835
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_glyphicons.scss
@@ -0,0 +1,233 @@
+//
+// Glyphicons for Bootstrap
+//
+// Since icons are fonts, they can be placed anywhere text is placed and are
+// thus automatically sized to match the surrounding child. To use, create an
+// inline element with the appropriate classes, like so:
+//
+// Star
+
+// Import the fonts
+@font-face {
+ font-family: 'Glyphicons Halflings';
+ src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot'), '#{$icon-font-path}#{$icon-font-name}.eot'));
+ src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot?#iefix'), '#{$icon-font-path}#{$icon-font-name}.eot?#iefix')) format('embedded-opentype'),
+ url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.woff'), '#{$icon-font-path}#{$icon-font-name}.woff')) format('woff'),
+ url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.ttf'), '#{$icon-font-path}#{$icon-font-name}.ttf')) format('truetype'),
+ url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}'), '#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}')) format('svg');
+}
+
+// Catchall baseclass
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+// Individual icons
+.glyphicon-asterisk { &:before { content: "\2a"; } }
+.glyphicon-plus { &:before { content: "\2b"; } }
+.glyphicon-euro { &:before { content: "\20ac"; } }
+.glyphicon-minus { &:before { content: "\2212"; } }
+.glyphicon-cloud { &:before { content: "\2601"; } }
+.glyphicon-envelope { &:before { content: "\2709"; } }
+.glyphicon-pencil { &:before { content: "\270f"; } }
+.glyphicon-glass { &:before { content: "\e001"; } }
+.glyphicon-music { &:before { content: "\e002"; } }
+.glyphicon-search { &:before { content: "\e003"; } }
+.glyphicon-heart { &:before { content: "\e005"; } }
+.glyphicon-star { &:before { content: "\e006"; } }
+.glyphicon-star-empty { &:before { content: "\e007"; } }
+.glyphicon-user { &:before { content: "\e008"; } }
+.glyphicon-film { &:before { content: "\e009"; } }
+.glyphicon-th-large { &:before { content: "\e010"; } }
+.glyphicon-th { &:before { content: "\e011"; } }
+.glyphicon-th-list { &:before { content: "\e012"; } }
+.glyphicon-ok { &:before { content: "\e013"; } }
+.glyphicon-remove { &:before { content: "\e014"; } }
+.glyphicon-zoom-in { &:before { content: "\e015"; } }
+.glyphicon-zoom-out { &:before { content: "\e016"; } }
+.glyphicon-off { &:before { content: "\e017"; } }
+.glyphicon-signal { &:before { content: "\e018"; } }
+.glyphicon-cog { &:before { content: "\e019"; } }
+.glyphicon-trash { &:before { content: "\e020"; } }
+.glyphicon-home { &:before { content: "\e021"; } }
+.glyphicon-file { &:before { content: "\e022"; } }
+.glyphicon-time { &:before { content: "\e023"; } }
+.glyphicon-road { &:before { content: "\e024"; } }
+.glyphicon-download-alt { &:before { content: "\e025"; } }
+.glyphicon-download { &:before { content: "\e026"; } }
+.glyphicon-upload { &:before { content: "\e027"; } }
+.glyphicon-inbox { &:before { content: "\e028"; } }
+.glyphicon-play-circle { &:before { content: "\e029"; } }
+.glyphicon-repeat { &:before { content: "\e030"; } }
+.glyphicon-refresh { &:before { content: "\e031"; } }
+.glyphicon-list-alt { &:before { content: "\e032"; } }
+.glyphicon-lock { &:before { content: "\e033"; } }
+.glyphicon-flag { &:before { content: "\e034"; } }
+.glyphicon-headphones { &:before { content: "\e035"; } }
+.glyphicon-volume-off { &:before { content: "\e036"; } }
+.glyphicon-volume-down { &:before { content: "\e037"; } }
+.glyphicon-volume-up { &:before { content: "\e038"; } }
+.glyphicon-qrcode { &:before { content: "\e039"; } }
+.glyphicon-barcode { &:before { content: "\e040"; } }
+.glyphicon-tag { &:before { content: "\e041"; } }
+.glyphicon-tags { &:before { content: "\e042"; } }
+.glyphicon-book { &:before { content: "\e043"; } }
+.glyphicon-bookmark { &:before { content: "\e044"; } }
+.glyphicon-print { &:before { content: "\e045"; } }
+.glyphicon-camera { &:before { content: "\e046"; } }
+.glyphicon-font { &:before { content: "\e047"; } }
+.glyphicon-bold { &:before { content: "\e048"; } }
+.glyphicon-italic { &:before { content: "\e049"; } }
+.glyphicon-text-height { &:before { content: "\e050"; } }
+.glyphicon-text-width { &:before { content: "\e051"; } }
+.glyphicon-align-left { &:before { content: "\e052"; } }
+.glyphicon-align-center { &:before { content: "\e053"; } }
+.glyphicon-align-right { &:before { content: "\e054"; } }
+.glyphicon-align-justify { &:before { content: "\e055"; } }
+.glyphicon-list { &:before { content: "\e056"; } }
+.glyphicon-indent-left { &:before { content: "\e057"; } }
+.glyphicon-indent-right { &:before { content: "\e058"; } }
+.glyphicon-facetime-video { &:before { content: "\e059"; } }
+.glyphicon-picture { &:before { content: "\e060"; } }
+.glyphicon-map-marker { &:before { content: "\e062"; } }
+.glyphicon-adjust { &:before { content: "\e063"; } }
+.glyphicon-tint { &:before { content: "\e064"; } }
+.glyphicon-edit { &:before { content: "\e065"; } }
+.glyphicon-share { &:before { content: "\e066"; } }
+.glyphicon-check { &:before { content: "\e067"; } }
+.glyphicon-move { &:before { content: "\e068"; } }
+.glyphicon-step-backward { &:before { content: "\e069"; } }
+.glyphicon-fast-backward { &:before { content: "\e070"; } }
+.glyphicon-backward { &:before { content: "\e071"; } }
+.glyphicon-play { &:before { content: "\e072"; } }
+.glyphicon-pause { &:before { content: "\e073"; } }
+.glyphicon-stop { &:before { content: "\e074"; } }
+.glyphicon-forward { &:before { content: "\e075"; } }
+.glyphicon-fast-forward { &:before { content: "\e076"; } }
+.glyphicon-step-forward { &:before { content: "\e077"; } }
+.glyphicon-eject { &:before { content: "\e078"; } }
+.glyphicon-chevron-left { &:before { content: "\e079"; } }
+.glyphicon-chevron-right { &:before { content: "\e080"; } }
+.glyphicon-plus-sign { &:before { content: "\e081"; } }
+.glyphicon-minus-sign { &:before { content: "\e082"; } }
+.glyphicon-remove-sign { &:before { content: "\e083"; } }
+.glyphicon-ok-sign { &:before { content: "\e084"; } }
+.glyphicon-question-sign { &:before { content: "\e085"; } }
+.glyphicon-info-sign { &:before { content: "\e086"; } }
+.glyphicon-screenshot { &:before { content: "\e087"; } }
+.glyphicon-remove-circle { &:before { content: "\e088"; } }
+.glyphicon-ok-circle { &:before { content: "\e089"; } }
+.glyphicon-ban-circle { &:before { content: "\e090"; } }
+.glyphicon-arrow-left { &:before { content: "\e091"; } }
+.glyphicon-arrow-right { &:before { content: "\e092"; } }
+.glyphicon-arrow-up { &:before { content: "\e093"; } }
+.glyphicon-arrow-down { &:before { content: "\e094"; } }
+.glyphicon-share-alt { &:before { content: "\e095"; } }
+.glyphicon-resize-full { &:before { content: "\e096"; } }
+.glyphicon-resize-small { &:before { content: "\e097"; } }
+.glyphicon-exclamation-sign { &:before { content: "\e101"; } }
+.glyphicon-gift { &:before { content: "\e102"; } }
+.glyphicon-leaf { &:before { content: "\e103"; } }
+.glyphicon-fire { &:before { content: "\e104"; } }
+.glyphicon-eye-open { &:before { content: "\e105"; } }
+.glyphicon-eye-close { &:before { content: "\e106"; } }
+.glyphicon-warning-sign { &:before { content: "\e107"; } }
+.glyphicon-plane { &:before { content: "\e108"; } }
+.glyphicon-calendar { &:before { content: "\e109"; } }
+.glyphicon-random { &:before { content: "\e110"; } }
+.glyphicon-comment { &:before { content: "\e111"; } }
+.glyphicon-magnet { &:before { content: "\e112"; } }
+.glyphicon-chevron-up { &:before { content: "\e113"; } }
+.glyphicon-chevron-down { &:before { content: "\e114"; } }
+.glyphicon-retweet { &:before { content: "\e115"; } }
+.glyphicon-shopping-cart { &:before { content: "\e116"; } }
+.glyphicon-folder-close { &:before { content: "\e117"; } }
+.glyphicon-folder-open { &:before { content: "\e118"; } }
+.glyphicon-resize-vertical { &:before { content: "\e119"; } }
+.glyphicon-resize-horizontal { &:before { content: "\e120"; } }
+.glyphicon-hdd { &:before { content: "\e121"; } }
+.glyphicon-bullhorn { &:before { content: "\e122"; } }
+.glyphicon-bell { &:before { content: "\e123"; } }
+.glyphicon-certificate { &:before { content: "\e124"; } }
+.glyphicon-thumbs-up { &:before { content: "\e125"; } }
+.glyphicon-thumbs-down { &:before { content: "\e126"; } }
+.glyphicon-hand-right { &:before { content: "\e127"; } }
+.glyphicon-hand-left { &:before { content: "\e128"; } }
+.glyphicon-hand-up { &:before { content: "\e129"; } }
+.glyphicon-hand-down { &:before { content: "\e130"; } }
+.glyphicon-circle-arrow-right { &:before { content: "\e131"; } }
+.glyphicon-circle-arrow-left { &:before { content: "\e132"; } }
+.glyphicon-circle-arrow-up { &:before { content: "\e133"; } }
+.glyphicon-circle-arrow-down { &:before { content: "\e134"; } }
+.glyphicon-globe { &:before { content: "\e135"; } }
+.glyphicon-wrench { &:before { content: "\e136"; } }
+.glyphicon-tasks { &:before { content: "\e137"; } }
+.glyphicon-filter { &:before { content: "\e138"; } }
+.glyphicon-briefcase { &:before { content: "\e139"; } }
+.glyphicon-fullscreen { &:before { content: "\e140"; } }
+.glyphicon-dashboard { &:before { content: "\e141"; } }
+.glyphicon-paperclip { &:before { content: "\e142"; } }
+.glyphicon-heart-empty { &:before { content: "\e143"; } }
+.glyphicon-link { &:before { content: "\e144"; } }
+.glyphicon-phone { &:before { content: "\e145"; } }
+.glyphicon-pushpin { &:before { content: "\e146"; } }
+.glyphicon-usd { &:before { content: "\e148"; } }
+.glyphicon-gbp { &:before { content: "\e149"; } }
+.glyphicon-sort { &:before { content: "\e150"; } }
+.glyphicon-sort-by-alphabet { &:before { content: "\e151"; } }
+.glyphicon-sort-by-alphabet-alt { &:before { content: "\e152"; } }
+.glyphicon-sort-by-order { &:before { content: "\e153"; } }
+.glyphicon-sort-by-order-alt { &:before { content: "\e154"; } }
+.glyphicon-sort-by-attributes { &:before { content: "\e155"; } }
+.glyphicon-sort-by-attributes-alt { &:before { content: "\e156"; } }
+.glyphicon-unchecked { &:before { content: "\e157"; } }
+.glyphicon-expand { &:before { content: "\e158"; } }
+.glyphicon-collapse-down { &:before { content: "\e159"; } }
+.glyphicon-collapse-up { &:before { content: "\e160"; } }
+.glyphicon-log-in { &:before { content: "\e161"; } }
+.glyphicon-flash { &:before { content: "\e162"; } }
+.glyphicon-log-out { &:before { content: "\e163"; } }
+.glyphicon-new-window { &:before { content: "\e164"; } }
+.glyphicon-record { &:before { content: "\e165"; } }
+.glyphicon-save { &:before { content: "\e166"; } }
+.glyphicon-open { &:before { content: "\e167"; } }
+.glyphicon-saved { &:before { content: "\e168"; } }
+.glyphicon-import { &:before { content: "\e169"; } }
+.glyphicon-export { &:before { content: "\e170"; } }
+.glyphicon-send { &:before { content: "\e171"; } }
+.glyphicon-floppy-disk { &:before { content: "\e172"; } }
+.glyphicon-floppy-saved { &:before { content: "\e173"; } }
+.glyphicon-floppy-remove { &:before { content: "\e174"; } }
+.glyphicon-floppy-save { &:before { content: "\e175"; } }
+.glyphicon-floppy-open { &:before { content: "\e176"; } }
+.glyphicon-credit-card { &:before { content: "\e177"; } }
+.glyphicon-transfer { &:before { content: "\e178"; } }
+.glyphicon-cutlery { &:before { content: "\e179"; } }
+.glyphicon-header { &:before { content: "\e180"; } }
+.glyphicon-compressed { &:before { content: "\e181"; } }
+.glyphicon-earphone { &:before { content: "\e182"; } }
+.glyphicon-phone-alt { &:before { content: "\e183"; } }
+.glyphicon-tower { &:before { content: "\e184"; } }
+.glyphicon-stats { &:before { content: "\e185"; } }
+.glyphicon-sd-video { &:before { content: "\e186"; } }
+.glyphicon-hd-video { &:before { content: "\e187"; } }
+.glyphicon-subtitles { &:before { content: "\e188"; } }
+.glyphicon-sound-stereo { &:before { content: "\e189"; } }
+.glyphicon-sound-dolby { &:before { content: "\e190"; } }
+.glyphicon-sound-5-1 { &:before { content: "\e191"; } }
+.glyphicon-sound-6-1 { &:before { content: "\e192"; } }
+.glyphicon-sound-7-1 { &:before { content: "\e193"; } }
+.glyphicon-copyright-mark { &:before { content: "\e194"; } }
+.glyphicon-registration-mark { &:before { content: "\e195"; } }
+.glyphicon-cloud-download { &:before { content: "\e197"; } }
+.glyphicon-cloud-upload { &:before { content: "\e198"; } }
+.glyphicon-tree-conifer { &:before { content: "\e199"; } }
+.glyphicon-tree-deciduous { &:before { content: "\e200"; } }
diff --git a/app/assets/stylesheets/bootstrap/_grid.scss b/app/assets/stylesheets/bootstrap/_grid.scss
new file mode 100644
index 0000000..f71f8b9
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_grid.scss
@@ -0,0 +1,84 @@
+//
+// Grid system
+// --------------------------------------------------
+
+
+// Container widths
+//
+// Set the container width, and override it for fixed navbars in media queries.
+
+.container {
+ @include container-fixed();
+
+ @media (min-width: $screen-sm-min) {
+ width: $container-sm;
+ }
+ @media (min-width: $screen-md-min) {
+ width: $container-md;
+ }
+ @media (min-width: $screen-lg-min) {
+ width: $container-lg;
+ }
+}
+
+
+// Fluid container
+//
+// Utilizes the mixin meant for fixed width containers, but without any defined
+// width for fluid, full width layouts.
+
+.container-fluid {
+ @include container-fixed();
+}
+
+
+// Row
+//
+// Rows contain and clear the floats of your columns.
+
+.row {
+ @include make-row();
+}
+
+
+// Columns
+//
+// Common styles for small and large grid columns
+
+@include make-grid-columns();
+
+
+// Extra small grid
+//
+// Columns, offsets, pushes, and pulls for extra small devices like
+// smartphones.
+
+@include make-grid(xs);
+
+
+// Small grid
+//
+// Columns, offsets, pushes, and pulls for the small device range, from phones
+// to tablets.
+
+@media (min-width: $screen-sm-min) {
+ @include make-grid(sm);
+}
+
+
+// Medium grid
+//
+// Columns, offsets, pushes, and pulls for the desktop device range.
+
+@media (min-width: $screen-md-min) {
+ @include make-grid(md);
+}
+
+
+// Large grid
+//
+// Columns, offsets, pushes, and pulls for the large desktop device range.
+
+@media (min-width: $screen-lg-min) {
+ @include make-grid(lg);
+}
diff --git a/app/assets/stylesheets/bootstrap/_input-groups.scss b/app/assets/stylesheets/bootstrap/_input-groups.scss
new file mode 100644
index 0000000..6c26c1d
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_input-groups.scss
@@ -0,0 +1,162 @@
+//
+// Input groups
+// --------------------------------------------------
+
+// Base styles
+// -------------------------
+.input-group {
+ position: relative; // For dropdowns
+ display: table;
+ border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table
+
+ // Undo padding and float of grid classes
+ &[class*="col-"] {
+ float: none;
+ padding-left: 0;
+ padding-right: 0;
+ }
+
+ .form-control {
+ // Ensure that the input is always above the *appended* addon button for
+ // proper border colors.
+ position: relative;
+ z-index: 2;
+
+ // IE9 fubars the placeholder attribute in text inputs and the arrows on
+ // select elements in input groups. To fix it, we float the input. Details:
+ // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855
+ float: left;
+
+ width: 100%;
+ margin-bottom: 0;
+ }
+}
+
+// Sizing options
+//
+// Remix the default form control sizing classes into new ones for easier
+// manipulation.
+
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn { @extend .input-lg; }
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn { @extend .input-sm; }
+
+
+// Display as table-cell
+// -------------------------
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: table-cell;
+
+ &:not(:first-child):not(:last-child) {
+ border-radius: 0;
+ }
+}
+// Addon and addon wrapper for buttons
+.input-group-addon,
+.input-group-btn {
+ width: 1%;
+ white-space: nowrap;
+ vertical-align: middle; // Match the inputs
+}
+
+// Text input groups
+// -------------------------
+.input-group-addon {
+ padding: $padding-base-vertical $padding-base-horizontal;
+ font-size: $font-size-base;
+ font-weight: normal;
+ line-height: 1;
+ color: $input-color;
+ text-align: center;
+ background-color: $input-group-addon-bg;
+ border: 1px solid $input-group-addon-border-color;
+ border-radius: $border-radius-base;
+
+ // Sizing
+ &.input-sm {
+ padding: $padding-small-vertical $padding-small-horizontal;
+ font-size: $font-size-small;
+ border-radius: $border-radius-small;
+ }
+ &.input-lg {
+ padding: $padding-large-vertical $padding-large-horizontal;
+ font-size: $font-size-large;
+ border-radius: $border-radius-large;
+ }
+
+ // Nuke default margins from checkboxes and radios to vertically center within.
+ input[type="radio"],
+ input[type="checkbox"] {
+ margin-top: 0;
+ }
+}
+
+// Reset rounded corners
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+ @include border-right-radius(0);
+}
+.input-group-addon:first-child {
+ border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+ @include border-left-radius(0);
+}
+.input-group-addon:last-child {
+ border-left: 0;
+}
+
+// Button input groups
+// -------------------------
+.input-group-btn {
+ position: relative;
+ // Jankily prevent input button groups from wrapping with `white-space` and
+ // `font-size` in combination with `inline-block` on buttons.
+ font-size: 0;
+ white-space: nowrap;
+
+ // Negative margin for spacing, position for bringing hovered/focused/actived
+ // element above the siblings.
+ > .btn {
+ position: relative;
+ + .btn {
+ margin-left: -1px;
+ }
+ // Bring the "active" button to the front
+ &:hover,
+ &:focus,
+ &:active {
+ z-index: 2;
+ }
+ }
+
+ // Negative margin to only have a 1px border between the two
+ &:first-child {
+ > .btn,
+ > .btn-group {
+ margin-right: -1px;
+ }
+ }
+ &:last-child {
+ > .btn,
+ > .btn-group {
+ margin-left: -1px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_jumbotron.scss b/app/assets/stylesheets/bootstrap/_jumbotron.scss
new file mode 100644
index 0000000..4e401e7
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_jumbotron.scss
@@ -0,0 +1,44 @@
+//
+// Jumbotron
+// --------------------------------------------------
+
+
+.jumbotron {
+ padding: $jumbotron-padding;
+ margin-bottom: $jumbotron-padding;
+ color: $jumbotron-color;
+ background-color: $jumbotron-bg;
+
+ h1,
+ .h1 {
+ color: $jumbotron-heading-color;
+ }
+ p {
+ margin-bottom: ($jumbotron-padding / 2);
+ font-size: $jumbotron-font-size;
+ font-weight: 200;
+ }
+
+ .container & {
+ border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container
+ }
+
+ .container {
+ max-width: 100%;
+ }
+
+ @media screen and (min-width: $screen-sm-min) {
+ padding-top: ($jumbotron-padding * 1.6);
+ padding-bottom: ($jumbotron-padding * 1.6);
+
+ .container & {
+ padding-left: ($jumbotron-padding * 2);
+ padding-right: ($jumbotron-padding * 2);
+ }
+
+ h1,
+ .h1 {
+ font-size: ($font-size-base * 4.5);
+ }
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_labels.scss b/app/assets/stylesheets/bootstrap/_labels.scss
new file mode 100644
index 0000000..8353eb1
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_labels.scss
@@ -0,0 +1,64 @@
+//
+// Labels
+// --------------------------------------------------
+
+.label {
+ display: inline;
+ padding: .2em .6em .3em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: $label-color;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: .25em;
+
+ // Add hover effects, but only for links
+ &[href] {
+ &:hover,
+ &:focus {
+ color: $label-link-hover-color;
+ text-decoration: none;
+ cursor: pointer;
+ }
+ }
+
+ // Empty labels collapse automatically (not available in IE8)
+ &:empty {
+ display: none;
+ }
+
+ // Quick fix for labels in buttons
+ .btn & {
+ position: relative;
+ top: -1px;
+ }
+}
+
+// Colors
+// Contextual variations (linked labels get darker on :hover)
+
+.label-default {
+ @include label-variant($label-default-bg);
+}
+
+.label-primary {
+ @include label-variant($label-primary-bg);
+}
+
+.label-success {
+ @include label-variant($label-success-bg);
+}
+
+.label-info {
+ @include label-variant($label-info-bg);
+}
+
+.label-warning {
+ @include label-variant($label-warning-bg);
+}
+
+.label-danger {
+ @include label-variant($label-danger-bg);
+}
diff --git a/app/assets/stylesheets/bootstrap/_list-group.scss b/app/assets/stylesheets/bootstrap/_list-group.scss
new file mode 100644
index 0000000..b608991
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_list-group.scss
@@ -0,0 +1,110 @@
+//
+// List groups
+// --------------------------------------------------
+
+
+// Base class
+//
+// Easily usable on
, , or .
+
+.list-group {
+ // No need to set list-style: none; since .list-group-item is block level
+ margin-bottom: 20px;
+ padding-left: 0; // reset padding because ul and ol
+}
+
+
+// Individual list items
+//
+// Use on `li`s or `div`s within the `.list-group` parent.
+
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ // Place the border on the list items and negative margin up for better styling
+ margin-bottom: -1px;
+ background-color: $list-group-bg;
+ border: 1px solid $list-group-border;
+
+ // Round the first and last items
+ &:first-child {
+ @include border-top-radius($list-group-border-radius);
+ }
+ &:last-child {
+ margin-bottom: 0;
+ @include border-bottom-radius($list-group-border-radius);
+ }
+
+ // Align badges within list items
+ > .badge {
+ float: right;
+ }
+ > .badge + .badge {
+ margin-right: 5px;
+ }
+}
+
+
+// Linked list items
+//
+// Use anchor elements instead of `li`s or `div`s to create linked list items.
+// Includes an extra `.active` modifier class for showing selected items.
+
+a.list-group-item {
+ color: $list-group-link-color;
+
+ .list-group-item-heading {
+ color: $list-group-link-heading-color;
+ }
+
+ // Hover state
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ background-color: $list-group-hover-bg;
+ }
+
+ // Active class on item itself, not parent
+ &.active,
+ &.active:hover,
+ &.active:focus {
+ z-index: 2; // Place active items above their siblings for proper border styling
+ color: $list-group-active-color;
+ background-color: $list-group-active-bg;
+ border-color: $list-group-active-border;
+
+ // Force color to inherit for custom content
+ .list-group-item-heading {
+ color: inherit;
+ }
+ .list-group-item-text {
+ color: $list-group-active-text-color;
+ }
+ }
+}
+
+
+// Contextual variants
+//
+// Add modifier classes to change text and background color on individual items.
+// Organizationally, this must come after the `:hover` states.
+
+@include list-group-item-variant(success, $state-success-bg, $state-success-text);
+@include list-group-item-variant(info, $state-info-bg, $state-info-text);
+@include list-group-item-variant(warning, $state-warning-bg, $state-warning-text);
+@include list-group-item-variant(danger, $state-danger-bg, $state-danger-text);
+
+
+// Custom content options
+//
+// Extra classes for creating well-formatted content within `.list-group-item`s.
+
+.list-group-item-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.list-group-item-text {
+ margin-bottom: 0;
+ line-height: 1.3;
+}
diff --git a/app/assets/stylesheets/bootstrap/_media.scss b/app/assets/stylesheets/bootstrap/_media.scss
new file mode 100644
index 0000000..5ad22cd
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_media.scss
@@ -0,0 +1,56 @@
+// Media objects
+// Source: http://stubbornella.org/content/?p=497
+// --------------------------------------------------
+
+
+// Common styles
+// -------------------------
+
+// Clear the floats
+.media,
+.media-body {
+ overflow: hidden;
+ zoom: 1;
+}
+
+// Proper spacing between instances of .media
+.media,
+.media .media {
+ margin-top: 15px;
+}
+.media:first-child {
+ margin-top: 0;
+}
+
+// For images and videos, set to block
+.media-object {
+ display: block;
+}
+
+// Reset margins on headings for tighter default spacing
+.media-heading {
+ margin: 0 0 5px;
+}
+
+
+// Media image alignment
+// -------------------------
+
+.media {
+ > .pull-left {
+ margin-right: 10px;
+ }
+ > .pull-right {
+ margin-left: 10px;
+ }
+}
+
+
+// Media list variation
+// -------------------------
+
+// Undo default ul/ol styles
+.media-list {
+ padding-left: 0;
+ list-style: none;
+}
diff --git a/app/assets/stylesheets/bootstrap/_mixins.scss b/app/assets/stylesheets/bootstrap/_mixins.scss
new file mode 100644
index 0000000..74ccf9f
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_mixins.scss
@@ -0,0 +1,947 @@
+//
+// Mixins
+// --------------------------------------------------
+
+
+// Utilities
+// -------------------------
+
+// Clearfix
+// Source: http://nicolasgallagher.com/micro-clearfix-hack/
+//
+// For modern browsers
+// 1. The space content is one way to avoid an Opera bug when the
+// contenteditable attribute is included anywhere else in the document.
+// Otherwise it causes space to appear at the top and bottom of elements
+// that are clearfixed.
+// 2. The use of `table` rather than `block` is only necessary if using
+// `:before` to contain the top-margins of child elements.
+@mixin clearfix() {
+ &:before,
+ &:after {
+ content: " "; // 1
+ display: table; // 2
+ }
+ &:after {
+ clear: both;
+ }
+}
+
+// WebKit-style focus
+@mixin tab-focus() {
+ // Default
+ outline: thin dotted;
+ // WebKit
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+// Center-align a block level element
+@mixin center-block() {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+// Sizing shortcuts
+@mixin size($width, $height) {
+ width: $width;
+ height: $height;
+}
+@mixin square($size) {
+ @include size($size, $size);
+}
+
+// Placeholder text
+@mixin placeholder($color: $input-color-placeholder) {
+ &::-moz-placeholder { color: $color; // Firefox
+ opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526
+ &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
+ &::-webkit-input-placeholder { color: $color; } // Safari and Chrome
+}
+
+// Text overflow
+// Requires inline-block or block for proper styling
+@mixin text-overflow() {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+// CSS image replacement
+//
+// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for
+// mixins being reused as classes with the same name, this doesn't hold up. As
+// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note
+// that we cannot chain the mixins together in Less, so they are repeated.
+//
+// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
+
+// Deprecated as of v3.0.1 (will be removed in v4)
+@mixin hide-text() {
+ font: #{0/0} a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+// New mixin to use as of v3.0.1
+@mixin text-hide() {
+ @include hide-text();
+}
+
+
+
+// CSS3 PROPERTIES
+// --------------------------------------------------
+
+// Single side border-radius
+@mixin border-top-radius($radius) {
+ border-top-right-radius: $radius;
+ border-top-left-radius: $radius;
+}
+@mixin border-right-radius($radius) {
+ border-bottom-right-radius: $radius;
+ border-top-right-radius: $radius;
+}
+@mixin border-bottom-radius($radius) {
+ border-bottom-right-radius: $radius;
+ border-bottom-left-radius: $radius;
+}
+@mixin border-left-radius($radius) {
+ border-bottom-left-radius: $radius;
+ border-top-left-radius: $radius;
+}
+
+// Drop shadows
+//
+// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's
+// supported browsers that have box shadow capabilities now support the
+// standard `box-shadow` property.
+@mixin box-shadow($shadow...) {
+ -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1
+ box-shadow: $shadow;
+}
+
+// Transitions
+@mixin transition($transition...) {
+ -webkit-transition: $transition;
+ transition: $transition;
+}
+@mixin transition-property($transition-property...) {
+ -webkit-transition-property: $transition-property;
+ transition-property: $transition-property;
+}
+@mixin transition-delay($transition-delay) {
+ -webkit-transition-delay: $transition-delay;
+ transition-delay: $transition-delay;
+}
+@mixin transition-duration($transition-duration...) {
+ -webkit-transition-duration: $transition-duration;
+ transition-duration: $transition-duration;
+}
+@mixin transition-transform($transition...) {
+ -webkit-transition: -webkit-transform $transition;
+ -moz-transition: -moz-transform $transition;
+ -o-transition: -o-transform $transition;
+ transition: transform $transition;
+}
+
+// Transformations
+@mixin rotate($degrees) {
+ -webkit-transform: rotate($degrees);
+ -ms-transform: rotate($degrees); // IE9 only
+ transform: rotate($degrees);
+}
+@mixin scale($scale-args...) {
+ -webkit-transform: scale($scale-args);
+ -ms-transform: scale($scale-args); // IE9 only
+ transform: scale($scale-args);
+}
+@mixin translate($x, $y) {
+ -webkit-transform: translate($x, $y);
+ -ms-transform: translate($x, $y); // IE9 only
+ transform: translate($x, $y);
+}
+@mixin skew($x, $y) {
+ -webkit-transform: skew($x, $y);
+ -ms-transform: skewX($x) skewY($y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+
+ transform: skew($x, $y);
+}
+@mixin translate3d($x, $y, $z) {
+ -webkit-transform: translate3d($x, $y, $z);
+ transform: translate3d($x, $y, $z);
+}
+
+@mixin rotateX($degrees) {
+ -webkit-transform: rotateX($degrees);
+ -ms-transform: rotateX($degrees); // IE9 only
+ transform: rotateX($degrees);
+}
+@mixin rotateY($degrees) {
+ -webkit-transform: rotateY($degrees);
+ -ms-transform: rotateY($degrees); // IE9 only
+ transform: rotateY($degrees);
+}
+@mixin perspective($perspective) {
+ -webkit-perspective: $perspective;
+ -moz-perspective: $perspective;
+ perspective: $perspective;
+}
+@mixin perspective-origin($perspective) {
+ -webkit-perspective-origin: $perspective;
+ -moz-perspective-origin: $perspective;
+ perspective-origin: $perspective;
+}
+@mixin transform-origin($origin) {
+ -webkit-transform-origin: $origin;
+ -moz-transform-origin: $origin;
+ -ms-transform-origin: $origin; // IE9 only
+ transform-origin: $origin;
+}
+
+// Animations
+@mixin animation($animation) {
+ -webkit-animation: $animation;
+ animation: $animation;
+}
+@mixin animation-name($name) {
+ -webkit-animation-name: $name;
+ animation-name: $name;
+}
+@mixin animation-duration($duration) {
+ -webkit-animation-duration: $duration;
+ animation-duration: $duration;
+}
+@mixin animation-timing-function($timing-function) {
+ -webkit-animation-timing-function: $timing-function;
+ animation-timing-function: $timing-function;
+}
+@mixin animation-delay($delay) {
+ -webkit-animation-delay: $delay;
+ animation-delay: $delay;
+}
+@mixin animation-iteration-count($iteration-count) {
+ -webkit-animation-iteration-count: $iteration-count;
+ animation-iteration-count: $iteration-count;
+}
+@mixin animation-direction($direction) {
+ -webkit-animation-direction: $direction;
+ animation-direction: $direction;
+}
+
+// Backface visibility
+// Prevent browsers from flickering when using CSS 3D transforms.
+// Default value is `visible`, but can be changed to `hidden`
+@mixin backface-visibility($visibility){
+ -webkit-backface-visibility: $visibility;
+ -moz-backface-visibility: $visibility;
+ backface-visibility: $visibility;
+}
+
+// Box sizing
+@mixin box-sizing($boxmodel) {
+ -webkit-box-sizing: $boxmodel;
+ -moz-box-sizing: $boxmodel;
+ box-sizing: $boxmodel;
+}
+
+// User select
+// For selecting text on the page
+@mixin user-select($select) {
+ -webkit-user-select: $select;
+ -moz-user-select: $select;
+ -ms-user-select: $select; // IE10+
+ user-select: $select;
+}
+
+// Resize anything
+@mixin resizable($direction) {
+ resize: $direction; // Options: horizontal, vertical, both
+ overflow: auto; // Safari fix
+}
+
+// CSS3 Content Columns
+@mixin content-columns($column-count, $column-gap: $grid-gutter-width) {
+ -webkit-column-count: $column-count;
+ -moz-column-count: $column-count;
+ column-count: $column-count;
+ -webkit-column-gap: $column-gap;
+ -moz-column-gap: $column-gap;
+ column-gap: $column-gap;
+}
+
+// Optional hyphenation
+@mixin hyphens($mode: auto) {
+ word-wrap: break-word;
+ -webkit-hyphens: $mode;
+ -moz-hyphens: $mode;
+ -ms-hyphens: $mode; // IE10+
+ -o-hyphens: $mode;
+ hyphens: $mode;
+}
+
+// Opacity
+@mixin opacity($opacity) {
+ opacity: $opacity;
+ // IE8 filter
+ $opacity-ie: ($opacity * 100);
+ filter: #{alpha(opacity=$opacity-ie)};
+}
+
+
+
+// GRADIENTS
+// --------------------------------------------------
+
+
+
+// Horizontal gradient, from left to right
+//
+// Creates two color stops, start and end, by specifying a color and position for each color stop.
+// Color stops are not available in IE9 and below.
+@mixin gradient-horizontal($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {
+ background-image: -webkit-linear-gradient(left, color-stop($start-color $start-percent), color-stop($end-color $end-percent)); // Safari 5.1-6, Chrome 10+
+ background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down
+}
+
+// Vertical gradient, from top to bottom
+//
+// Creates two color stops, start and end, by specifying a color and position for each color stop.
+// Color stops are not available in IE9 and below.
+@mixin gradient-vertical($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {
+ background-image: -webkit-linear-gradient(top, $start-color $start-percent, $end-color $end-percent); // Safari 5.1-6, Chrome 10+
+ background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down
+}
+
+@mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) {
+ background-repeat: repeat-x;
+ background-image: -webkit-linear-gradient($deg, $start-color, $end-color); // Safari 5.1-6, Chrome 10+
+ background-image: linear-gradient($deg, $start-color, $end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
+}
+@mixin gradient-horizontal-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {
+ background-image: -webkit-linear-gradient(left, $start-color, $mid-color $color-stop, $end-color);
+ background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down, gets no color-stop at all for proper fallback
+}
+@mixin gradient-vertical-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {
+ background-image: -webkit-linear-gradient($start-color, $mid-color $color-stop, $end-color);
+ background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down, gets no color-stop at all for proper fallback
+}
+@mixin gradient-radial($inner-color: #555, $outer-color: #333) {
+ background-image: -webkit-radial-gradient(circle, $inner-color, $outer-color);
+ background-image: radial-gradient(circle, $inner-color, $outer-color);
+ background-repeat: no-repeat;
+}
+@mixin gradient-striped($color: rgba(255,255,255,.15), $angle: 45deg) {
+ background-image: -webkit-linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
+ background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
+}
+
+// Reset filters for IE
+//
+// When you need to remove a gradient background, do not forget to use this to reset
+// the IE filter for IE9 and below.
+@mixin reset-filter() {
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+
+
+
+// Retina images
+//
+// Short retina mixin for setting background-image and -size
+
+@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
+ background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-1x}"), "#{$file-1x}"));
+
+ @media
+ only screen and (-webkit-min-device-pixel-ratio: 2),
+ only screen and ( min--moz-device-pixel-ratio: 2),
+ only screen and ( -o-min-device-pixel-ratio: 2/1),
+ only screen and ( min-device-pixel-ratio: 2),
+ only screen and ( min-resolution: 192dpi),
+ only screen and ( min-resolution: 2dppx) {
+ background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-2x}"), "#{$file-2x}"));
+ background-size: $width-1x $height-1x;
+ }
+}
+
+
+// Responsive image
+//
+// Keep images from scaling beyond the width of their parents.
+
+@mixin img-responsive($display: block) {
+ display: $display;
+ max-width: 100%; // Part 1: Set a maximum relative to the parent
+ height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
+}
+
+
+// COMPONENT MIXINS
+// --------------------------------------------------
+
+// Horizontal dividers
+// -------------------------
+// Dividers (basically an hr) within dropdowns and nav lists
+@mixin nav-divider($color: #e5e5e5) {
+ height: 1px;
+ margin: (($line-height-computed / 2) - 1) 0;
+ overflow: hidden;
+ background-color: $color;
+}
+
+// Panels
+// -------------------------
+@mixin panel-variant($border, $heading-text-color, $heading-bg-color, $heading-border) {
+ border-color: $border;
+
+ & > .panel-heading {
+ color: $heading-text-color;
+ background-color: $heading-bg-color;
+ border-color: $heading-border;
+
+ + .panel-collapse .panel-body {
+ border-top-color: $border;
+ }
+ }
+ & > .panel-footer {
+ + .panel-collapse .panel-body {
+ border-bottom-color: $border;
+ }
+ }
+}
+
+// Alerts
+// -------------------------
+@mixin alert-variant($background, $border, $text-color) {
+ background-color: $background;
+ border-color: $border;
+ color: $text-color;
+
+ hr {
+ border-top-color: darken($border, 5%);
+ }
+ .alert-link {
+ color: darken($text-color, 10%);
+ }
+}
+
+// Tables
+// -------------------------
+@mixin table-row-variant($state, $background) {
+ // Exact selectors below required to override `.table-striped` and prevent
+ // inheritance to nested tables.
+ .table > thead > tr,
+ .table > tbody > tr,
+ .table > tfoot > tr {
+ > td.#{$state},
+ > th.#{$state},
+ &.#{$state} > td,
+ &.#{$state} > th {
+ background-color: $background;
+ }
+ }
+
+ // Hover states for `.table-hover`
+ // Note: this is not available for cells or rows within `thead` or `tfoot`.
+ .table-hover > tbody > tr {
+ > td.#{$state}:hover,
+ > th.#{$state}:hover,
+ &.#{$state}:hover > td,
+ &.#{$state}:hover > th {
+ background-color: darken($background, 5%);
+ }
+ }
+}
+
+// List Groups
+// -------------------------
+@mixin list-group-item-variant($state, $background, $color) {
+ .list-group-item-#{$state} {
+ color: $color;
+ background-color: $background;
+
+ // [converter] extracted a& to a.list-group-item-#{$state}
+ }
+
+ a.list-group-item-#{$state} {
+ color: $color;
+
+ .list-group-item-heading { color: inherit; }
+
+ &:hover,
+ &:focus {
+ color: $color;
+ background-color: darken($background, 5%);
+ }
+ &.active,
+ &.active:hover,
+ &.active:focus {
+ color: #fff;
+ background-color: $color;
+ border-color: $color;
+ }
+ }
+}
+
+// Button variants
+// -------------------------
+// Easily pump out default styles, as well as :hover, :focus, :active,
+// and disabled options for all buttons
+@mixin button-variant($color, $background, $border) {
+ color: $color;
+ background-color: $background;
+ border-color: $border;
+
+ &:hover,
+ &:focus,
+ &:active,
+ &.active {
+ color: $color;
+ background-color: darken($background, 8%);
+ border-color: darken($border, 12%);
+ }
+ .open & { &.dropdown-toggle {
+ color: $color;
+ background-color: darken($background, 8%);
+ border-color: darken($border, 12%);
+ } }
+ &:active,
+ &.active {
+ background-image: none;
+ }
+ .open & { &.dropdown-toggle {
+ background-image: none;
+ } }
+ &.disabled,
+ &[disabled],
+ fieldset[disabled] & {
+ &,
+ &:hover,
+ &:focus,
+ &:active,
+ &.active {
+ background-color: $background;
+ border-color: $border;
+ }
+ }
+
+ .badge {
+ color: $background;
+ background-color: $color;
+ }
+}
+
+// Button sizes
+// -------------------------
+@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
+ padding: $padding-vertical $padding-horizontal;
+ font-size: $font-size;
+ line-height: $line-height;
+ border-radius: $border-radius;
+}
+
+// Pagination
+// -------------------------
+@mixin pagination-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) {
+ > li {
+ > a,
+ > span {
+ padding: $padding-vertical $padding-horizontal;
+ font-size: $font-size;
+ }
+ &:first-child {
+ > a,
+ > span {
+ @include border-left-radius($border-radius);
+ }
+ }
+ &:last-child {
+ > a,
+ > span {
+ @include border-right-radius($border-radius);
+ }
+ }
+ }
+}
+
+// Labels
+// -------------------------
+@mixin label-variant($color) {
+ background-color: $color;
+ &[href] {
+ &:hover,
+ &:focus {
+ background-color: darken($color, 10%);
+ }
+ }
+}
+
+// Contextual backgrounds
+// -------------------------
+// [converter] $parent hack
+@mixin bg-variant($parent, $color) {
+ #{$parent} {
+ background-color: $color;
+ }
+ a#{$parent}:hover {
+ background-color: darken($color, 10%);
+ }
+}
+
+// Typography
+// -------------------------
+// [converter] $parent hack
+@mixin text-emphasis-variant($parent, $color) {
+ #{$parent} {
+ color: $color;
+ }
+ a#{$parent}:hover {
+ color: darken($color, 10%);
+ }
+}
+
+// Navbar vertical align
+// -------------------------
+// Vertically center elements in the navbar.
+// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.
+@mixin navbar-vertical-align($element-height) {
+ margin-top: (($navbar-height - $element-height) / 2);
+ margin-bottom: (($navbar-height - $element-height) / 2);
+}
+
+// Progress bars
+// -------------------------
+@mixin progress-bar-variant($color) {
+ background-color: $color;
+ .progress-striped & {
+ @include gradient-striped();
+ }
+}
+
+// Responsive utilities
+// -------------------------
+// More easily include all the states for responsive-utilities.less.
+// [converter] $parent hack
+@mixin responsive-visibility($parent) {
+ #{$parent} {
+ display: block !important;
+ }
+ table#{$parent} { display: table; }
+ tr#{$parent} { display: table-row !important; }
+ th#{$parent},
+ td#{$parent} { display: table-cell !important; }
+}
+
+// [converter] $parent hack
+@mixin responsive-invisibility($parent) {
+ #{$parent} {
+ display: none !important;
+ }
+}
+
+
+// Grid System
+// -----------
+
+// Centered container element
+@mixin container-fixed() {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: ($grid-gutter-width / 2);
+ padding-right: ($grid-gutter-width / 2);
+ @include clearfix();
+}
+
+// Creates a wrapper for a series of columns
+@mixin make-row($gutter: $grid-gutter-width) {
+ margin-left: ($gutter / -2);
+ margin-right: ($gutter / -2);
+ @include clearfix();
+}
+
+// Generate the extra small columns
+@mixin make-xs-column($columns, $gutter: $grid-gutter-width) {
+ position: relative;
+ float: left;
+ width: percentage(($columns / $grid-columns));
+ min-height: 1px;
+ padding-left: ($gutter / 2);
+ padding-right: ($gutter / 2);
+}
+@mixin make-xs-column-offset($columns) {
+ @media (min-width: $screen-xs-min) {
+ margin-left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-xs-column-push($columns) {
+ @media (min-width: $screen-xs-min) {
+ left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-xs-column-pull($columns) {
+ @media (min-width: $screen-xs-min) {
+ right: percentage(($columns / $grid-columns));
+ }
+}
+
+
+// Generate the small columns
+@mixin make-sm-column($columns, $gutter: $grid-gutter-width) {
+ position: relative;
+ min-height: 1px;
+ padding-left: ($gutter / 2);
+ padding-right: ($gutter / 2);
+
+ @media (min-width: $screen-sm-min) {
+ float: left;
+ width: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-sm-column-offset($columns) {
+ @media (min-width: $screen-sm-min) {
+ margin-left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-sm-column-push($columns) {
+ @media (min-width: $screen-sm-min) {
+ left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-sm-column-pull($columns) {
+ @media (min-width: $screen-sm-min) {
+ right: percentage(($columns / $grid-columns));
+ }
+}
+
+
+// Generate the medium columns
+@mixin make-md-column($columns, $gutter: $grid-gutter-width) {
+ position: relative;
+ min-height: 1px;
+ padding-left: ($gutter / 2);
+ padding-right: ($gutter / 2);
+
+ @media (min-width: $screen-md-min) {
+ float: left;
+ width: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-md-column-offset($columns) {
+ @media (min-width: $screen-md-min) {
+ margin-left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-md-column-push($columns) {
+ @media (min-width: $screen-md-min) {
+ left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-md-column-pull($columns) {
+ @media (min-width: $screen-md-min) {
+ right: percentage(($columns / $grid-columns));
+ }
+}
+
+
+// Generate the large columns
+@mixin make-lg-column($columns, $gutter: $grid-gutter-width) {
+ position: relative;
+ min-height: 1px;
+ padding-left: ($gutter / 2);
+ padding-right: ($gutter / 2);
+
+ @media (min-width: $screen-lg-min) {
+ float: left;
+ width: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-lg-column-offset($columns) {
+ @media (min-width: $screen-lg-min) {
+ margin-left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-lg-column-push($columns) {
+ @media (min-width: $screen-lg-min) {
+ left: percentage(($columns / $grid-columns));
+ }
+}
+@mixin make-lg-column-pull($columns) {
+ @media (min-width: $screen-lg-min) {
+ right: percentage(($columns / $grid-columns));
+ }
+}
+
+
+// Framework grid generation
+//
+// Used only by Bootstrap to generate the correct number of grid classes given
+// any value of `$grid-columns`.
+
+// [converter] This is defined recursively in LESS, but Sass supports real loops
+@mixin make-grid-columns() {
+ $list: '';
+ $i: 1;
+ $list: ".col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}";
+ @for $i from (1 + 1) through $grid-columns {
+ $list: "#{$list}, .col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}";
+ }
+ #{$list} {
+ position: relative;
+ // Prevent columns from collapsing when empty
+ min-height: 1px;
+ // Inner gutter via padding
+ padding-left: ($grid-gutter-width / 2);
+ padding-right: ($grid-gutter-width / 2);
+ }
+}
+
+
+// [converter] This is defined recursively in LESS, but Sass supports real loops
+@mixin float-grid-columns($class) {
+ $list: '';
+ $i: 1;
+ $list: ".col-#{$class}-#{$i}";
+ @for $i from (1 + 1) through $grid-columns {
+ $list: "#{$list}, .col-#{$class}-#{$i}";
+ }
+ #{$list} {
+ float: left;
+ }
+}
+
+
+@mixin calc-grid-column($index, $class, $type) {
+ @if ($type == width) and ($index > 0) {
+ .col-#{$class}-#{$index} {
+ width: percentage(($index / $grid-columns));
+ }
+ }
+ @if ($type == push) {
+ .col-#{$class}-push-#{$index} {
+ left: percentage(($index / $grid-columns));
+ }
+ }
+ @if ($type == pull) {
+ .col-#{$class}-pull-#{$index} {
+ right: percentage(($index / $grid-columns));
+ }
+ }
+ @if ($type == offset) {
+ .col-#{$class}-offset-#{$index} {
+ margin-left: percentage(($index / $grid-columns));
+ }
+ }
+}
+
+// [converter] This is defined recursively in LESS, but Sass supports real loops
+@mixin loop-grid-columns($columns, $class, $type) {
+ @for $i from 0 through $columns {
+ @include calc-grid-column($i, $class, $type);
+ }
+}
+
+
+// Create grid for specific class
+@mixin make-grid($class) {
+ @include float-grid-columns($class);
+ @include loop-grid-columns($grid-columns, $class, width);
+ @include loop-grid-columns($grid-columns, $class, pull);
+ @include loop-grid-columns($grid-columns, $class, push);
+ @include loop-grid-columns($grid-columns, $class, offset);
+}
+
+// Form validation states
+//
+// Used in forms.less to generate the form validation CSS for warnings, errors,
+// and successes.
+
+@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) {
+ // Color the label and help text
+ .help-block,
+ .control-label,
+ .radio,
+ .checkbox,
+ .radio-inline,
+ .checkbox-inline {
+ color: $text-color;
+ }
+ // Set the border and box shadow on specific inputs to match
+ .form-control {
+ border-color: $border-color;
+ @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
+ &:focus {
+ border-color: darken($border-color, 10%);
+ $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%);
+ @include box-shadow($shadow);
+ }
+ }
+ // Set validation states also for addons
+ .input-group-addon {
+ color: $text-color;
+ border-color: $border-color;
+ background-color: $background-color;
+ }
+ // Optional feedback icon
+ .form-control-feedback {
+ color: $text-color;
+ }
+}
+
+// Form control focus state
+//
+// Generate a customized focus state and for any input with the specified color,
+// which defaults to the `$input-focus-border` variable.
+//
+// We highly encourage you to not customize the default value, but instead use
+// this to tweak colors on an as-needed basis. This aesthetic change is based on
+// WebKit's default styles, but applicable to a wider range of browsers. Its
+// usability and accessibility should be taken into account with any change.
+//
+// Example usage: change the default blue border and shadow to white for better
+// contrast against a dark gray background.
+
+@mixin form-control-focus($color: $input-border-focus) {
+ $color-rgba: rgba(red($color), green($color), blue($color), .6);
+ &:focus {
+ border-color: $color;
+ outline: 0;
+ @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba);
+ }
+}
+
+// Form control sizing
+//
+// Relative text size, padding, and border-radii changes for form controls. For
+// horizontal sizing, wrap controls in the predefined grid classes. `
`
+// element gets special love because it's special, and that's a fact!
+
+// [converter] $parent hack
+@mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
+ #{$parent} {
+ height: $input-height;
+ padding: $padding-vertical $padding-horizontal;
+ font-size: $font-size;
+ line-height: $line-height;
+ border-radius: $border-radius;
+ }
+
+ select#{$parent} {
+ height: $input-height;
+ line-height: $input-height;
+ }
+
+ textarea#{$parent},
+ select[multiple]#{$parent} {
+ height: auto;
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_modals.scss b/app/assets/stylesheets/bootstrap/_modals.scss
new file mode 100644
index 0000000..931092c
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_modals.scss
@@ -0,0 +1,139 @@
+//
+// Modals
+// --------------------------------------------------
+
+// .modal-open - body class for killing the scroll
+// .modal - container to scroll within
+// .modal-dialog - positioning shell for the actual modal
+// .modal-content - actual modal w/ bg and corners and shit
+
+// Kill the scroll on the body
+.modal-open {
+ overflow: hidden;
+}
+
+// Container that the modal scrolls within
+.modal {
+ display: none;
+ overflow: auto;
+ overflow-y: scroll;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $zindex-modal;
+ -webkit-overflow-scrolling: touch;
+
+ // Prevent Chrome on Windows from adding a focus outline. For details, see
+ // https://github.com/twbs/bootstrap/pull/10951.
+ outline: 0;
+
+ // When fading in the modal, animate it to slide down
+ &.fade .modal-dialog {
+ @include translate(0, -25%);
+ @include transition-transform(0.3s ease-out);
+ }
+ &.in .modal-dialog { @include translate(0, 0)}
+}
+
+// Shell div to position the modal with bottom padding
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+
+// Actual modal
+.modal-content {
+ position: relative;
+ background-color: $modal-content-bg;
+ border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
+ border: 1px solid $modal-content-border-color;
+ border-radius: $border-radius-large;
+ @include box-shadow(0 3px 9px rgba(0,0,0,.5));
+ background-clip: padding-box;
+ // Remove focus outline from opened modal
+ outline: none;
+}
+
+// Modal background
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $zindex-modal-background;
+ background-color: $modal-backdrop-bg;
+ // Fade for backdrop
+ &.fade { @include opacity(0); }
+ &.in { @include opacity($modal-backdrop-opacity); }
+}
+
+// Modal header
+// Top section of the modal w/ title and dismiss
+.modal-header {
+ padding: $modal-title-padding;
+ border-bottom: 1px solid $modal-header-border-color;
+ min-height: ($modal-title-padding + $modal-title-line-height);
+}
+// Close icon
+.modal-header .close {
+ margin-top: -2px;
+}
+
+// Title text within header
+.modal-title {
+ margin: 0;
+ line-height: $modal-title-line-height;
+}
+
+// Modal body
+// Where all modal content resides (sibling of .modal-header and .modal-footer)
+.modal-body {
+ position: relative;
+ padding: $modal-inner-padding;
+}
+
+// Footer (for actions)
+.modal-footer {
+ margin-top: 15px;
+ padding: ($modal-inner-padding - 1) $modal-inner-padding $modal-inner-padding;
+ text-align: right; // right align buttons
+ border-top: 1px solid $modal-footer-border-color;
+ @include clearfix(); // clear it in case folks use .pull-* classes on buttons
+
+ // Properly space out buttons
+ .btn + .btn {
+ margin-left: 5px;
+ margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
+ }
+ // but override that for button groups
+ .btn-group .btn + .btn {
+ margin-left: -1px;
+ }
+ // and override it for block buttons as well
+ .btn-block + .btn-block {
+ margin-left: 0;
+ }
+}
+
+// Scale up the modal
+@media (min-width: $screen-sm-min) {
+ // Automatically set modal's width for larger viewports
+ .modal-dialog {
+ width: $modal-md;
+ margin: 30px auto;
+ }
+ .modal-content {
+ @include box-shadow(0 5px 15px rgba(0,0,0,.5));
+ }
+
+ // Modal sizes
+ .modal-sm { width: $modal-sm; }
+}
+
+@media (min-width: $screen-md-min) {
+ .modal-lg { width: $modal-lg; }
+}
diff --git a/app/assets/stylesheets/bootstrap/_navbar.scss b/app/assets/stylesheets/bootstrap/_navbar.scss
new file mode 100644
index 0000000..8ad9437
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_navbar.scss
@@ -0,0 +1,620 @@
+//
+// Navbars
+// --------------------------------------------------
+
+
+// Wrapper and base class
+//
+// Provide a static navbar from which we expand to create full-width, fixed, and
+// other navbar variations.
+
+.navbar {
+ position: relative;
+ min-height: $navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)
+ margin-bottom: $navbar-margin-bottom;
+ border: 1px solid transparent;
+
+ // Prevent floats from breaking the navbar
+ @include clearfix();
+
+ @media (min-width: $grid-float-breakpoint) {
+ border-radius: $navbar-border-radius;
+ }
+}
+
+
+// Navbar heading
+//
+// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy
+// styling of responsive aspects.
+
+.navbar-header {
+ @include clearfix();
+
+ @media (min-width: $grid-float-breakpoint) {
+ float: left;
+ }
+}
+
+
+// Navbar collapse (body)
+//
+// Group your navbar content into this for easy collapsing and expanding across
+// various device sizes. By default, this content is collapsed when <768px, but
+// will expand past that for a horizontal display.
+//
+// To start (on mobile devices) the navbar links, forms, and buttons are stacked
+// vertically and include a `max-height` to overflow in case you have too much
+// content for the user's viewport.
+
+.navbar-collapse {
+ max-height: $navbar-collapse-max-height;
+ overflow-x: visible;
+ padding-right: $navbar-padding-horizontal;
+ padding-left: $navbar-padding-horizontal;
+ border-top: 1px solid transparent;
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.1);
+ @include clearfix();
+ -webkit-overflow-scrolling: touch;
+
+ &.in {
+ overflow-y: auto;
+ }
+
+ @media (min-width: $grid-float-breakpoint) {
+ width: auto;
+ border-top: 0;
+ box-shadow: none;
+
+ &.collapse {
+ display: block !important;
+ height: auto !important;
+ padding-bottom: 0; // Override default setting
+ overflow: visible !important;
+ }
+
+ &.in {
+ overflow-y: visible;
+ }
+
+ // Undo the collapse side padding for navbars with containers to ensure
+ // alignment of right-aligned contents.
+ .navbar-fixed-top &,
+ .navbar-static-top &,
+ .navbar-fixed-bottom & {
+ padding-left: 0;
+ padding-right: 0;
+ }
+ }
+}
+
+
+// Both navbar header and collapse
+//
+// When a container is present, change the behavior of the header and collapse.
+
+.container,
+.container-fluid {
+ > .navbar-header,
+ > .navbar-collapse {
+ margin-right: -$navbar-padding-horizontal;
+ margin-left: -$navbar-padding-horizontal;
+
+ @media (min-width: $grid-float-breakpoint) {
+ margin-right: 0;
+ margin-left: 0;
+ }
+ }
+}
+
+
+//
+// Navbar alignment options
+//
+// Display the navbar across the entirety of the page or fixed it to the top or
+// bottom of the page.
+
+// Static top (unfixed, but 100% wide) navbar
+.navbar-static-top {
+ z-index: $zindex-navbar;
+ border-width: 0 0 1px;
+
+ @media (min-width: $grid-float-breakpoint) {
+ border-radius: 0;
+ }
+}
+
+// Fix the top/bottom navbars when screen real estate supports it
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: $zindex-navbar-fixed;
+
+ // Undo the rounded corners
+ @media (min-width: $grid-float-breakpoint) {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top {
+ top: 0;
+ border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+ bottom: 0;
+ margin-bottom: 0; // override .navbar defaults
+ border-width: 1px 0 0;
+}
+
+
+// Brand/project name
+
+.navbar-brand {
+ float: left;
+ padding: $navbar-padding-vertical $navbar-padding-horizontal;
+ font-size: $font-size-large;
+ line-height: $line-height-computed;
+ height: $navbar-height;
+
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ }
+
+ @media (min-width: $grid-float-breakpoint) {
+ .navbar > .container &,
+ .navbar > .container-fluid & {
+ margin-left: -$navbar-padding-horizontal;
+ }
+ }
+}
+
+
+// Navbar toggle
+//
+// Custom button for toggling the `.navbar-collapse`, powered by the collapse
+// JavaScript plugin.
+
+.navbar-toggle {
+ position: relative;
+ float: right;
+ margin-right: $navbar-padding-horizontal;
+ padding: 9px 10px;
+ @include navbar-vertical-align(34px);
+ background-color: transparent;
+ background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
+ border: 1px solid transparent;
+ border-radius: $border-radius-base;
+
+ // We remove the `outline` here, but later compensate by attaching `:hover`
+ // styles to `:focus`.
+ &:focus {
+ outline: none;
+ }
+
+ // Bars
+ .icon-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ border-radius: 1px;
+ }
+ .icon-bar + .icon-bar {
+ margin-top: 4px;
+ }
+
+ @media (min-width: $grid-float-breakpoint) {
+ display: none;
+ }
+}
+
+
+// Navbar nav links
+//
+// Builds on top of the `.nav` components with its own modifier class to make
+// the nav the full height of the horizontal nav (above 768px).
+
+.navbar-nav {
+ margin: ($navbar-padding-vertical / 2) (-$navbar-padding-horizontal);
+
+ > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: $line-height-computed;
+ }
+
+ @media (max-width: $grid-float-breakpoint-max) {
+ // Dropdowns get custom display when collapsed
+ .open .dropdown-menu {
+ position: static;
+ float: none;
+ width: auto;
+ margin-top: 0;
+ background-color: transparent;
+ border: 0;
+ box-shadow: none;
+ > li > a,
+ .dropdown-header {
+ padding: 5px 15px 5px 25px;
+ }
+ > li > a {
+ line-height: $line-height-computed;
+ &:hover,
+ &:focus {
+ background-image: none;
+ }
+ }
+ }
+ }
+
+ // Uncollapse the nav
+ @media (min-width: $grid-float-breakpoint) {
+ float: left;
+ margin: 0;
+
+ > li {
+ float: left;
+ > a {
+ padding-top: $navbar-padding-vertical;
+ padding-bottom: $navbar-padding-vertical;
+ }
+ }
+
+ &.navbar-right:last-child {
+ margin-right: -$navbar-padding-horizontal;
+ }
+ }
+}
+
+
+// Component alignment
+//
+// Repurpose the pull utilities as their own navbar utilities to avoid specificity
+// issues with parents and chaining. Only do this when the navbar is uncollapsed
+// though so that navbar contents properly stack and align in mobile.
+
+@media (min-width: $grid-float-breakpoint) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ }
+}
+
+
+// Navbar form
+//
+// Extension of the `.form-inline` with some extra flavor for optimum display in
+// our navbars.
+
+.navbar-form {
+ margin-left: -$navbar-padding-horizontal;
+ margin-right: -$navbar-padding-horizontal;
+ padding: 10px $navbar-padding-horizontal;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ $shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
+ @include box-shadow($shadow);
+
+ // Mixin behavior for optimum display
+ @extend .form-inline;
+
+ .form-group {
+ @media (max-width: $grid-float-breakpoint-max) {
+ margin-bottom: 5px;
+ }
+ }
+
+ // Vertically center in expanded, horizontal navbar
+ @include navbar-vertical-align($input-height-base);
+
+ // Undo 100% width for pull classes
+ @media (min-width: $grid-float-breakpoint) {
+ width: auto;
+ border: 0;
+ margin-left: 0;
+ margin-right: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ @include box-shadow(none);
+
+ // Outdent the form if last child to line up with content down the page
+ &.navbar-right:last-child {
+ margin-right: -$navbar-padding-horizontal;
+ }
+ }
+}
+
+
+// Dropdown menus
+
+// Menu position and menu carets
+.navbar-nav > li > .dropdown-menu {
+ margin-top: 0;
+ @include border-top-radius(0);
+}
+// Menu position and menu caret support for dropups via extra dropup class
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+ @include border-bottom-radius(0);
+}
+
+
+// Buttons in navbars
+//
+// Vertically center a button within a navbar (when *not* in a form).
+
+.navbar-btn {
+ @include navbar-vertical-align($input-height-base);
+
+ &.btn-sm {
+ @include navbar-vertical-align($input-height-small);
+ }
+ &.btn-xs {
+ @include navbar-vertical-align(22);
+ }
+}
+
+
+// Text in navbars
+//
+// Add a class to make any element properly align itself vertically within the navbars.
+
+.navbar-text {
+ @include navbar-vertical-align($line-height-computed);
+
+ @media (min-width: $grid-float-breakpoint) {
+ float: left;
+ margin-left: $navbar-padding-horizontal;
+ margin-right: $navbar-padding-horizontal;
+
+ // Outdent the form if last child to line up with content down the page
+ &.navbar-right:last-child {
+ margin-right: 0;
+ }
+ }
+}
+
+// Alternate navbars
+// --------------------------------------------------
+
+// Default navbar
+.navbar-default {
+ background-color: $navbar-default-bg;
+ border-color: $navbar-default-border;
+
+ .navbar-brand {
+ color: $navbar-default-brand-color;
+ &:hover,
+ &:focus {
+ color: $navbar-default-brand-hover-color;
+ background-color: $navbar-default-brand-hover-bg;
+ }
+ }
+
+ .navbar-text {
+ color: $navbar-default-color;
+ }
+
+ .navbar-nav {
+ > li > a {
+ color: $navbar-default-link-color;
+
+ &:hover,
+ &:focus {
+ color: $navbar-default-link-hover-color;
+ background-color: $navbar-default-link-hover-bg;
+ }
+ }
+ > .active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-default-link-active-color;
+ background-color: $navbar-default-link-active-bg;
+ }
+ }
+ > .disabled > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-default-link-disabled-color;
+ background-color: $navbar-default-link-disabled-bg;
+ }
+ }
+ }
+
+ .navbar-toggle {
+ border-color: $navbar-default-toggle-border-color;
+ &:hover,
+ &:focus {
+ background-color: $navbar-default-toggle-hover-bg;
+ }
+ .icon-bar {
+ background-color: $navbar-default-toggle-icon-bar-bg;
+ }
+ }
+
+ .navbar-collapse,
+ .navbar-form {
+ border-color: $navbar-default-border;
+ }
+
+ // Dropdown menu items
+ .navbar-nav {
+ // Remove background color from open dropdown
+ > .open > a {
+ &,
+ &:hover,
+ &:focus {
+ background-color: $navbar-default-link-active-bg;
+ color: $navbar-default-link-active-color;
+ }
+ }
+
+ @media (max-width: $grid-float-breakpoint-max) {
+ // Dropdowns get custom display when collapsed
+ .open .dropdown-menu {
+ > li > a {
+ color: $navbar-default-link-color;
+ &:hover,
+ &:focus {
+ color: $navbar-default-link-hover-color;
+ background-color: $navbar-default-link-hover-bg;
+ }
+ }
+ > .active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-default-link-active-color;
+ background-color: $navbar-default-link-active-bg;
+ }
+ }
+ > .disabled > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-default-link-disabled-color;
+ background-color: $navbar-default-link-disabled-bg;
+ }
+ }
+ }
+ }
+ }
+
+
+ // Links in navbars
+ //
+ // Add a class to ensure links outside the navbar nav are colored correctly.
+
+ .navbar-link {
+ color: $navbar-default-link-color;
+ &:hover {
+ color: $navbar-default-link-hover-color;
+ }
+ }
+
+}
+
+// Inverse navbar
+
+.navbar-inverse {
+ background-color: $navbar-inverse-bg;
+ border-color: $navbar-inverse-border;
+
+ .navbar-brand {
+ color: $navbar-inverse-brand-color;
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-brand-hover-color;
+ background-color: $navbar-inverse-brand-hover-bg;
+ }
+ }
+
+ .navbar-text {
+ color: $navbar-inverse-color;
+ }
+
+ .navbar-nav {
+ > li > a {
+ color: $navbar-inverse-link-color;
+
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-link-hover-color;
+ background-color: $navbar-inverse-link-hover-bg;
+ }
+ }
+ > .active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-link-active-color;
+ background-color: $navbar-inverse-link-active-bg;
+ }
+ }
+ > .disabled > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-link-disabled-color;
+ background-color: $navbar-inverse-link-disabled-bg;
+ }
+ }
+ }
+
+ // Darken the responsive nav toggle
+ .navbar-toggle {
+ border-color: $navbar-inverse-toggle-border-color;
+ &:hover,
+ &:focus {
+ background-color: $navbar-inverse-toggle-hover-bg;
+ }
+ .icon-bar {
+ background-color: $navbar-inverse-toggle-icon-bar-bg;
+ }
+ }
+
+ .navbar-collapse,
+ .navbar-form {
+ border-color: darken($navbar-inverse-bg, 7%);
+ }
+
+ // Dropdowns
+ .navbar-nav {
+ > .open > a {
+ &,
+ &:hover,
+ &:focus {
+ background-color: $navbar-inverse-link-active-bg;
+ color: $navbar-inverse-link-active-color;
+ }
+ }
+
+ @media (max-width: $grid-float-breakpoint-max) {
+ // Dropdowns get custom display
+ .open .dropdown-menu {
+ > .dropdown-header {
+ border-color: $navbar-inverse-border;
+ }
+ .divider {
+ background-color: $navbar-inverse-border;
+ }
+ > li > a {
+ color: $navbar-inverse-link-color;
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-link-hover-color;
+ background-color: $navbar-inverse-link-hover-bg;
+ }
+ }
+ > .active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-link-active-color;
+ background-color: $navbar-inverse-link-active-bg;
+ }
+ }
+ > .disabled > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $navbar-inverse-link-disabled-color;
+ background-color: $navbar-inverse-link-disabled-bg;
+ }
+ }
+ }
+ }
+ }
+
+ .navbar-link {
+ color: $navbar-inverse-link-color;
+ &:hover {
+ color: $navbar-inverse-link-hover-color;
+ }
+ }
+
+}
diff --git a/app/assets/stylesheets/bootstrap/_navs.scss b/app/assets/stylesheets/bootstrap/_navs.scss
new file mode 100644
index 0000000..c690072
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_navs.scss
@@ -0,0 +1,242 @@
+//
+// Navs
+// --------------------------------------------------
+
+
+// Base class
+// --------------------------------------------------
+
+.nav {
+ margin-bottom: 0;
+ padding-left: 0; // Override default ul/ol
+ list-style: none;
+ @include clearfix();
+
+ > li {
+ position: relative;
+ display: block;
+
+ > a {
+ position: relative;
+ display: block;
+ padding: $nav-link-padding;
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ background-color: $nav-link-hover-bg;
+ }
+ }
+
+ // Disabled state sets text to gray and nukes hover/tab effects
+ &.disabled > a {
+ color: $nav-disabled-link-color;
+
+ &:hover,
+ &:focus {
+ color: $nav-disabled-link-hover-color;
+ text-decoration: none;
+ background-color: transparent;
+ cursor: not-allowed;
+ }
+ }
+ }
+
+ // Open dropdowns
+ .open > a {
+ &,
+ &:hover,
+ &:focus {
+ background-color: $nav-link-hover-bg;
+ border-color: $link-color;
+ }
+ }
+
+ // Nav dividers (deprecated with v3.0.1)
+ //
+ // This should have been removed in v3 with the dropping of `.nav-list`, but
+ // we missed it. We don't currently support this anywhere, but in the interest
+ // of maintaining backward compatibility in case you use it, it's deprecated.
+ .nav-divider {
+ @include nav-divider();
+ }
+
+ // Prevent IE8 from misplacing imgs
+ //
+ // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989
+ > li > a > img {
+ max-width: none;
+ }
+}
+
+
+// Tabs
+// -------------------------
+
+// Give the tabs something to sit on
+.nav-tabs {
+ border-bottom: 1px solid $nav-tabs-border-color;
+ > li {
+ float: left;
+ // Make the list-items overlay the bottom border
+ margin-bottom: -1px;
+
+ // Actual tabs (as links)
+ > a {
+ margin-right: 2px;
+ line-height: $line-height-base;
+ border: 1px solid transparent;
+ border-radius: $border-radius-base $border-radius-base 0 0;
+ &:hover {
+ border-color: $nav-tabs-link-hover-border-color $nav-tabs-link-hover-border-color $nav-tabs-border-color;
+ }
+ }
+
+ // Active state, and its :hover to override normal :hover
+ &.active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $nav-tabs-active-link-hover-color;
+ background-color: $nav-tabs-active-link-hover-bg;
+ border: 1px solid $nav-tabs-active-link-hover-border-color;
+ border-bottom-color: transparent;
+ cursor: default;
+ }
+ }
+ }
+ // pulling this in mainly for less shorthand
+ &.nav-justified {
+ @extend .nav-justified;
+ @extend .nav-tabs-justified;
+ }
+}
+
+
+// Pills
+// -------------------------
+.nav-pills {
+ > li {
+ float: left;
+
+ // Links rendered as pills
+ > a {
+ border-radius: $nav-pills-border-radius;
+ }
+ + li {
+ margin-left: 2px;
+ }
+
+ // Active state
+ &.active > a {
+ &,
+ &:hover,
+ &:focus {
+ color: $nav-pills-active-link-hover-color;
+ background-color: $nav-pills-active-link-hover-bg;
+ }
+ }
+ }
+}
+
+
+// Stacked pills
+.nav-stacked {
+ > li {
+ float: none;
+ + li {
+ margin-top: 2px;
+ margin-left: 0; // no need for this gap between nav items
+ }
+ }
+}
+
+
+// Nav variations
+// --------------------------------------------------
+
+// Justified nav links
+// -------------------------
+
+.nav-justified {
+ width: 100%;
+
+ > li {
+ float: none;
+ > a {
+ text-align: center;
+ margin-bottom: 5px;
+ }
+ }
+
+ > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+ }
+
+ @media (min-width: $screen-sm-min) {
+ > li {
+ display: table-cell;
+ width: 1%;
+ > a {
+ margin-bottom: 0;
+ }
+ }
+ }
+}
+
+// Move borders to anchors instead of bottom of list
+//
+// Mixin for adding on top the shared `.nav-justified` styles for our tabs
+.nav-tabs-justified {
+ border-bottom: 0;
+
+ > li > a {
+ // Override margin from .nav-tabs
+ margin-right: 0;
+ border-radius: $border-radius-base;
+ }
+
+ > .active > a,
+ > .active > a:hover,
+ > .active > a:focus {
+ border: 1px solid $nav-tabs-justified-link-border-color;
+ }
+
+ @media (min-width: $screen-sm-min) {
+ > li > a {
+ border-bottom: 1px solid $nav-tabs-justified-link-border-color;
+ border-radius: $border-radius-base $border-radius-base 0 0;
+ }
+ > .active > a,
+ > .active > a:hover,
+ > .active > a:focus {
+ border-bottom-color: $nav-tabs-justified-active-link-border-color;
+ }
+ }
+}
+
+
+// Tabbable tabs
+// -------------------------
+
+// Hide tabbable panes to start, show them when `.active`
+.tab-content {
+ > .tab-pane {
+ display: none;
+ }
+ > .active {
+ display: block;
+ }
+}
+
+
+// Dropdowns
+// -------------------------
+
+// Specific dropdowns
+.nav-tabs .dropdown-menu {
+ // make dropdown border overlap tab border
+ margin-top: -1px;
+ // Remove the top rounded corners here since there is a hard edge above the menu
+ @include border-top-radius(0);
+}
diff --git a/app/assets/stylesheets/bootstrap/_normalize.scss b/app/assets/stylesheets/bootstrap/_normalize.scss
new file mode 100644
index 0000000..024e257
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_normalize.scss
@@ -0,0 +1,423 @@
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */
+
+//
+// 1. Set default font family to sans-serif.
+// 2. Prevent iOS text size adjust after orientation change, without disabling
+// user zoom.
+//
+
+html {
+ font-family: sans-serif; // 1
+ -ms-text-size-adjust: 100%; // 2
+ -webkit-text-size-adjust: 100%; // 2
+}
+
+//
+// Remove default margin.
+//
+
+body {
+ margin: 0;
+}
+
+// HTML5 display definitions
+// ==========================================================================
+
+//
+// Correct `block` display not defined in IE 8/9.
+//
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+ display: block;
+}
+
+//
+// 1. Correct `inline-block` display not defined in IE 8/9.
+// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+//
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; // 1
+ vertical-align: baseline; // 2
+}
+
+//
+// Prevent modern browsers from displaying `audio` without controls.
+// Remove excess height in iOS 5 devices.
+//
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+//
+// Address `[hidden]` styling not present in IE 8/9.
+// Hide the `template` element in IE, Safari, and Firefox < 22.
+//
+
+[hidden],
+template {
+ display: none;
+}
+
+// Links
+// ==========================================================================
+
+//
+// Remove the gray background color from active links in IE 10.
+//
+
+a {
+ background: transparent;
+}
+
+//
+// Improve readability when focused and also mouse hovered in all browsers.
+//
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+// Text-level semantics
+// ==========================================================================
+
+//
+// Address styling not present in IE 8/9, Safari 5, and Chrome.
+//
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+//
+// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
+//
+
+b,
+strong {
+ font-weight: bold;
+}
+
+//
+// Address styling not present in Safari 5 and Chrome.
+//
+
+dfn {
+ font-style: italic;
+}
+
+//
+// Address variable `h1` font-size and margin within `section` and `article`
+// contexts in Firefox 4+, Safari 5, and Chrome.
+//
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+//
+// Address styling not present in IE 8/9.
+//
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+//
+// Address inconsistent and variable font size in all browsers.
+//
+
+small {
+ font-size: 80%;
+}
+
+//
+// Prevent `sub` and `sup` affecting `line-height` in all browsers.
+//
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+// Embedded content
+// ==========================================================================
+
+//
+// Remove border when inside `a` element in IE 8/9.
+//
+
+img {
+ border: 0;
+}
+
+//
+// Correct overflow displayed oddly in IE 9.
+//
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+// Grouping content
+// ==========================================================================
+
+//
+// Address margin not present in IE 8/9 and Safari 5.
+//
+
+figure {
+ margin: 1em 40px;
+}
+
+//
+// Address differences between Firefox and other browsers.
+//
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+//
+// Contain overflow in all browsers.
+//
+
+pre {
+ overflow: auto;
+}
+
+//
+// Address odd `em`-unit font size rendering in all browsers.
+//
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+// Forms
+// ==========================================================================
+
+//
+// Known limitation: by default, Chrome and Safari on OS X allow very limited
+// styling of `select`, unless a `border` property is set.
+//
+
+//
+// 1. Correct color not being inherited.
+// Known issue: affects color of disabled elements.
+// 2. Correct font properties not being inherited.
+// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
+//
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; // 1
+ font: inherit; // 2
+ margin: 0; // 3
+}
+
+//
+// Address `overflow` set to `hidden` in IE 8/9/10.
+//
+
+button {
+ overflow: visible;
+}
+
+//
+// Address inconsistent `text-transform` inheritance for `button` and `select`.
+// All other form control elements do not inherit `text-transform` values.
+// Correct `button` style inheritance in Firefox, IE 8+, and Opera
+// Correct `select` style inheritance in Firefox.
+//
+
+button,
+select {
+ text-transform: none;
+}
+
+//
+// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+// and `video` controls.
+// 2. Correct inability to style clickable `input` types in iOS.
+// 3. Improve usability and consistency of cursor style between image-type
+// `input` and others.
+//
+
+button,
+html input[type="button"], // 1
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; // 2
+ cursor: pointer; // 3
+}
+
+//
+// Re-set default cursor for disabled elements.
+//
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+//
+// Remove inner padding and border in Firefox 4+.
+//
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+//
+// Address Firefox 4+ setting `line-height` on `input` using `!important` in
+// the UA stylesheet.
+//
+
+input {
+ line-height: normal;
+}
+
+//
+// It's recommended that you don't attempt to style these elements.
+// Firefox's implementation doesn't respect box-sizing, padding, or width.
+//
+// 1. Address box sizing set to `content-box` in IE 8/9/10.
+// 2. Remove excess padding in IE 8/9/10.
+//
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; // 1
+ padding: 0; // 2
+}
+
+//
+// Fix the cursor style for Chrome's increment/decrement buttons. For certain
+// `font-size` values of the `input`, it causes the cursor style of the
+// decrement button to change from `default` to `text`.
+//
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+//
+// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
+// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
+// (include `-moz` to future-proof).
+//
+
+input[type="search"] {
+ -webkit-appearance: textfield; // 1
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; // 2
+ box-sizing: content-box;
+}
+
+//
+// Remove inner padding and search cancel button in Safari and Chrome on OS X.
+// Safari (but not Chrome) clips the cancel button when the search input has
+// padding (and `textfield` appearance).
+//
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+//
+// Define consistent border, margin, and padding.
+//
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+//
+// 1. Correct `color` not being inherited in IE 8/9.
+// 2. Remove padding so people aren't caught out if they zero out fieldsets.
+//
+
+legend {
+ border: 0; // 1
+ padding: 0; // 2
+}
+
+//
+// Remove default vertical scrollbar in IE 8/9.
+//
+
+textarea {
+ overflow: auto;
+}
+
+//
+// Don't inherit the `font-weight` (applied by a rule above).
+// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+//
+
+optgroup {
+ font-weight: bold;
+}
+
+// Tables
+// ==========================================================================
+
+//
+// Remove most spacing between table cells.
+//
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/bootstrap/_pager.scss b/app/assets/stylesheets/bootstrap/_pager.scss
new file mode 100644
index 0000000..6531fe6
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_pager.scss
@@ -0,0 +1,55 @@
+//
+// Pager pagination
+// --------------------------------------------------
+
+
+.pager {
+ padding-left: 0;
+ margin: $line-height-computed 0;
+ list-style: none;
+ text-align: center;
+ @include clearfix();
+ li {
+ display: inline;
+ > a,
+ > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: $pager-bg;
+ border: 1px solid $pager-border;
+ border-radius: $pager-border-radius;
+ }
+
+ > a:hover,
+ > a:focus {
+ text-decoration: none;
+ background-color: $pager-hover-bg;
+ }
+ }
+
+ .next {
+ > a,
+ > span {
+ float: right;
+ }
+ }
+
+ .previous {
+ > a,
+ > span {
+ float: left;
+ }
+ }
+
+ .disabled {
+ > a,
+ > a:hover,
+ > a:focus,
+ > span {
+ color: $pager-disabled-color;
+ background-color: $pager-bg;
+ cursor: not-allowed;
+ }
+ }
+
+}
diff --git a/app/assets/stylesheets/bootstrap/_pagination.scss b/app/assets/stylesheets/bootstrap/_pagination.scss
new file mode 100644
index 0000000..44c1222
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_pagination.scss
@@ -0,0 +1,88 @@
+//
+// Pagination (multiple pages)
+// --------------------------------------------------
+.pagination {
+ display: inline-block;
+ padding-left: 0;
+ margin: $line-height-computed 0;
+ border-radius: $border-radius-base;
+
+ > li {
+ display: inline; // Remove list-style and block-level defaults
+ > a,
+ > span {
+ position: relative;
+ float: left; // Collapse white-space
+ padding: $padding-base-vertical $padding-base-horizontal;
+ line-height: $line-height-base;
+ text-decoration: none;
+ color: $pagination-color;
+ background-color: $pagination-bg;
+ border: 1px solid $pagination-border;
+ margin-left: -1px;
+ }
+ &:first-child {
+ > a,
+ > span {
+ margin-left: 0;
+ @include border-left-radius($border-radius-base);
+ }
+ }
+ &:last-child {
+ > a,
+ > span {
+ @include border-right-radius($border-radius-base);
+ }
+ }
+ }
+
+ > li > a,
+ > li > span {
+ &:hover,
+ &:focus {
+ color: $pagination-hover-color;
+ background-color: $pagination-hover-bg;
+ border-color: $pagination-hover-border;
+ }
+ }
+
+ > .active > a,
+ > .active > span {
+ &,
+ &:hover,
+ &:focus {
+ z-index: 2;
+ color: $pagination-active-color;
+ background-color: $pagination-active-bg;
+ border-color: $pagination-active-border;
+ cursor: default;
+ }
+ }
+
+ > .disabled {
+ > span,
+ > span:hover,
+ > span:focus,
+ > a,
+ > a:hover,
+ > a:focus {
+ color: $pagination-disabled-color;
+ background-color: $pagination-disabled-bg;
+ border-color: $pagination-disabled-border;
+ cursor: not-allowed;
+ }
+ }
+}
+
+// Sizing
+// --------------------------------------------------
+
+// Large
+.pagination-lg {
+ @include pagination-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large);
+}
+
+// Small
+.pagination-sm {
+ @include pagination-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $border-radius-small);
+}
diff --git a/app/assets/stylesheets/bootstrap/_panels.scss b/app/assets/stylesheets/bootstrap/_panels.scss
new file mode 100644
index 0000000..0ab9925
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_panels.scss
@@ -0,0 +1,241 @@
+//
+// Panels
+// --------------------------------------------------
+
+
+// Base class
+.panel {
+ margin-bottom: $line-height-computed;
+ background-color: $panel-bg;
+ border: 1px solid transparent;
+ border-radius: $panel-border-radius;
+ @include box-shadow(0 1px 1px rgba(0,0,0,.05));
+}
+
+// Panel contents
+.panel-body {
+ padding: $panel-body-padding;
+ @include clearfix();
+}
+
+// Optional heading
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ @include border-top-radius(($panel-border-radius - 1));
+
+ > .dropdown .dropdown-toggle {
+ color: inherit;
+ }
+}
+
+// Within heading, strip any `h*` tag of its default margins for spacing.
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: ceil(($font-size-base * 1.125));
+ color: inherit;
+
+ > a {
+ color: inherit;
+ }
+}
+
+// Optional footer (stays gray in every modifier class)
+.panel-footer {
+ padding: 10px 15px;
+ background-color: $panel-footer-bg;
+ border-top: 1px solid $panel-inner-border;
+ @include border-bottom-radius(($panel-border-radius - 1));
+}
+
+
+// List groups in panels
+//
+// By default, space out list group content from panel headings to account for
+// any kind of custom content between the two.
+
+.panel {
+ > .list-group {
+ margin-bottom: 0;
+
+ .list-group-item {
+ border-width: 1px 0;
+ border-radius: 0;
+ }
+
+ // Add border top radius for first one
+ &:first-child {
+ .list-group-item:first-child {
+ border-top: 0;
+ @include border-top-radius(($panel-border-radius - 1));
+ }
+ }
+ // Add border bottom radius for last one
+ &:last-child {
+ .list-group-item:last-child {
+ border-bottom: 0;
+ @include border-bottom-radius(($panel-border-radius - 1));
+ }
+ }
+ }
+}
+// Collapse space between when there's no additional content.
+.panel-heading + .list-group {
+ .list-group-item:first-child {
+ border-top-width: 0;
+ }
+}
+
+
+// Tables in panels
+//
+// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and
+// watch it go full width.
+
+.panel {
+ > .table,
+ > .table-responsive > .table {
+ margin-bottom: 0;
+ }
+ // Add border top radius for first one
+ > .table:first-child,
+ > .table-responsive:first-child > .table:first-child {
+ @include border-top-radius(($panel-border-radius - 1));
+
+ > thead:first-child,
+ > tbody:first-child {
+ > tr:first-child {
+ td:first-child,
+ th:first-child {
+ border-top-left-radius: ($panel-border-radius - 1);
+ }
+ td:last-child,
+ th:last-child {
+ border-top-right-radius: ($panel-border-radius - 1);
+ }
+ }
+ }
+ }
+ // Add border bottom radius for last one
+ > .table:last-child,
+ > .table-responsive:last-child > .table:last-child {
+ @include border-bottom-radius(($panel-border-radius - 1));
+
+ > tbody:last-child,
+ > tfoot:last-child {
+ > tr:last-child {
+ td:first-child,
+ th:first-child {
+ border-bottom-left-radius: ($panel-border-radius - 1);
+ }
+ td:last-child,
+ th:last-child {
+ border-bottom-right-radius: ($panel-border-radius - 1);
+ }
+ }
+ }
+ }
+ > .panel-body + .table,
+ > .panel-body + .table-responsive {
+ border-top: 1px solid $table-border-color;
+ }
+ > .table > tbody:first-child > tr:first-child th,
+ > .table > tbody:first-child > tr:first-child td {
+ border-top: 0;
+ }
+ > .table-bordered,
+ > .table-responsive > .table-bordered {
+ border: 0;
+ > thead,
+ > tbody,
+ > tfoot {
+ > tr {
+ > th:first-child,
+ > td:first-child {
+ border-left: 0;
+ }
+ > th:last-child,
+ > td:last-child {
+ border-right: 0;
+ }
+ }
+ }
+ > thead,
+ > tbody {
+ > tr:first-child {
+ > td,
+ > th {
+ border-bottom: 0;
+ }
+ }
+ }
+ > tbody,
+ > tfoot {
+ > tr:last-child {
+ > td,
+ > th {
+ border-bottom: 0;
+ }
+ }
+ }
+ }
+ > .table-responsive {
+ border: 0;
+ margin-bottom: 0;
+ }
+}
+
+
+// Collapsable panels (aka, accordion)
+//
+// Wrap a series of panels in `.panel-group` to turn them into an accordion with
+// the help of our collapse JavaScript plugin.
+
+.panel-group {
+ margin-bottom: $line-height-computed;
+
+ // Tighten up margin so it's only between panels
+ .panel {
+ margin-bottom: 0;
+ border-radius: $panel-border-radius;
+ overflow: hidden; // crop contents when collapsed
+ + .panel {
+ margin-top: 5px;
+ }
+ }
+
+ .panel-heading {
+ border-bottom: 0;
+ + .panel-collapse .panel-body {
+ border-top: 1px solid $panel-inner-border;
+ }
+ }
+ .panel-footer {
+ border-top: 0;
+ + .panel-collapse .panel-body {
+ border-bottom: 1px solid $panel-inner-border;
+ }
+ }
+}
+
+
+// Contextual variations
+.panel-default {
+ @include panel-variant($panel-default-border, $panel-default-text, $panel-default-heading-bg, $panel-default-border);
+}
+.panel-primary {
+ @include panel-variant($panel-primary-border, $panel-primary-text, $panel-primary-heading-bg, $panel-primary-border);
+}
+.panel-success {
+ @include panel-variant($panel-success-border, $panel-success-text, $panel-success-heading-bg, $panel-success-border);
+}
+.panel-info {
+ @include panel-variant($panel-info-border, $panel-info-text, $panel-info-heading-bg, $panel-info-border);
+}
+.panel-warning {
+ @include panel-variant($panel-warning-border, $panel-warning-text, $panel-warning-heading-bg, $panel-warning-border);
+}
+.panel-danger {
+ @include panel-variant($panel-danger-border, $panel-danger-text, $panel-danger-heading-bg, $panel-danger-border);
+}
diff --git a/app/assets/stylesheets/bootstrap/_popovers.scss b/app/assets/stylesheets/bootstrap/_popovers.scss
new file mode 100644
index 0000000..6d6bed5
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_popovers.scss
@@ -0,0 +1,133 @@
+//
+// Popovers
+// --------------------------------------------------
+
+
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: $zindex-popover;
+ display: none;
+ max-width: $popover-max-width;
+ padding: 1px;
+ text-align: left; // Reset given new insertion method
+ background-color: $popover-bg;
+ background-clip: padding-box;
+ border: 1px solid $popover-fallback-border-color;
+ border: 1px solid $popover-border-color;
+ border-radius: $border-radius-large;
+ @include box-shadow(0 5px 10px rgba(0,0,0,.2));
+
+ // Overrides for proper insertion
+ white-space: normal;
+
+ // Offset the popover to account for the popover arrow
+ &.top { margin-top: -$popover-arrow-width; }
+ &.right { margin-left: $popover-arrow-width; }
+ &.bottom { margin-top: $popover-arrow-width; }
+ &.left { margin-left: -$popover-arrow-width; }
+}
+
+.popover-title {
+ margin: 0; // reset heading margin
+ padding: 8px 14px;
+ font-size: $font-size-base;
+ font-weight: normal;
+ line-height: 18px;
+ background-color: $popover-title-bg;
+ border-bottom: 1px solid darken($popover-title-bg, 5%);
+ border-radius: 5px 5px 0 0;
+}
+
+.popover-content {
+ padding: 9px 14px;
+}
+
+// Arrows
+//
+// .arrow is outer, .arrow:after is inner
+
+.popover > .arrow {
+ &,
+ &:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ }
+}
+.popover > .arrow {
+ border-width: $popover-arrow-outer-width;
+}
+.popover > .arrow:after {
+ border-width: $popover-arrow-width;
+ content: "";
+}
+
+.popover {
+ &.top > .arrow {
+ left: 50%;
+ margin-left: -$popover-arrow-outer-width;
+ border-bottom-width: 0;
+ border-top-color: $popover-arrow-outer-fallback-color; // IE8 fallback
+ border-top-color: $popover-arrow-outer-color;
+ bottom: -$popover-arrow-outer-width;
+ &:after {
+ content: " ";
+ bottom: 1px;
+ margin-left: -$popover-arrow-width;
+ border-bottom-width: 0;
+ border-top-color: $popover-arrow-color;
+ }
+ }
+ &.right > .arrow {
+ top: 50%;
+ left: -$popover-arrow-outer-width;
+ margin-top: -$popover-arrow-outer-width;
+ border-left-width: 0;
+ border-right-color: $popover-arrow-outer-fallback-color; // IE8 fallback
+ border-right-color: $popover-arrow-outer-color;
+ &:after {
+ content: " ";
+ left: 1px;
+ bottom: -$popover-arrow-width;
+ border-left-width: 0;
+ border-right-color: $popover-arrow-color;
+ }
+ }
+ &.bottom > .arrow {
+ left: 50%;
+ margin-left: -$popover-arrow-outer-width;
+ border-top-width: 0;
+ border-bottom-color: $popover-arrow-outer-fallback-color; // IE8 fallback
+ border-bottom-color: $popover-arrow-outer-color;
+ top: -$popover-arrow-outer-width;
+ &:after {
+ content: " ";
+ top: 1px;
+ margin-left: -$popover-arrow-width;
+ border-top-width: 0;
+ border-bottom-color: $popover-arrow-color;
+ }
+ }
+
+ &.left > .arrow {
+ top: 50%;
+ right: -$popover-arrow-outer-width;
+ margin-top: -$popover-arrow-outer-width;
+ border-right-width: 0;
+ border-left-color: $popover-arrow-outer-fallback-color; // IE8 fallback
+ border-left-color: $popover-arrow-outer-color;
+ &:after {
+ content: " ";
+ right: 1px;
+ border-right-width: 0;
+ border-left-color: $popover-arrow-color;
+ bottom: -$popover-arrow-width;
+ }
+ }
+
+}
diff --git a/app/assets/stylesheets/bootstrap/_print.scss b/app/assets/stylesheets/bootstrap/_print.scss
new file mode 100644
index 0000000..3655d03
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_print.scss
@@ -0,0 +1,101 @@
+//
+// Basic print styles
+// --------------------------------------------------
+// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css
+
+@media print {
+
+ * {
+ text-shadow: none !important;
+ color: #000 !important; // Black prints faster: h5bp.com/s
+ background: transparent !important;
+ box-shadow: none !important;
+ }
+
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+
+ // Don't show links for images, or javascript/internal links
+ a[href^="javascript:"]:after,
+ a[href^="#"]:after {
+ content: "";
+ }
+
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+
+ thead {
+ display: table-header-group; // h5bp.com/t
+ }
+
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+
+ img {
+ max-width: 100% !important;
+ }
+
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+
+ // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245
+ // Once fixed, we can just straight up remove this.
+ select {
+ background: #fff !important;
+ }
+
+ // Bootstrap components
+ .navbar {
+ display: none;
+ }
+ .table {
+ td,
+ th {
+ background-color: #fff !important;
+ }
+ }
+ .btn,
+ .dropup > .btn {
+ > .caret {
+ border-top-color: #000 !important;
+ }
+ }
+ .label {
+ border: 1px solid #000;
+ }
+
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table-bordered {
+ th,
+ td {
+ border: 1px solid #ddd !important;
+ }
+ }
+
+}
diff --git a/app/assets/stylesheets/bootstrap/_progress-bars.scss b/app/assets/stylesheets/bootstrap/_progress-bars.scss
new file mode 100644
index 0000000..7302b72
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_progress-bars.scss
@@ -0,0 +1,80 @@
+//
+// Progress bars
+// --------------------------------------------------
+
+
+// Bar animations
+// -------------------------
+
+// WebKit
+@-webkit-keyframes progress-bar-stripes {
+ from { background-position: 40px 0; }
+ to { background-position: 0 0; }
+}
+
+// Spec and IE10+
+@keyframes progress-bar-stripes {
+ from { background-position: 40px 0; }
+ to { background-position: 0 0; }
+}
+
+
+
+// Bar itself
+// -------------------------
+
+// Outer container
+.progress {
+ overflow: hidden;
+ height: $line-height-computed;
+ margin-bottom: $line-height-computed;
+ background-color: $progress-bg;
+ border-radius: $border-radius-base;
+ @include box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
+}
+
+// Bar of progress
+.progress-bar {
+ float: left;
+ width: 0%;
+ height: 100%;
+ font-size: $font-size-small;
+ line-height: $line-height-computed;
+ color: $progress-bar-color;
+ text-align: center;
+ background-color: $progress-bar-bg;
+ @include box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));
+ @include transition(width .6s ease);
+}
+
+// Striped bars
+.progress-striped .progress-bar {
+ @include gradient-striped();
+ background-size: 40px 40px;
+}
+
+// Call animation for the active one
+.progress.active .progress-bar {
+ @include animation(progress-bar-stripes 2s linear infinite);
+}
+
+
+
+// Variations
+// -------------------------
+
+.progress-bar-success {
+ @include progress-bar-variant($progress-bar-success-bg);
+}
+
+.progress-bar-info {
+ @include progress-bar-variant($progress-bar-info-bg);
+}
+
+.progress-bar-warning {
+ @include progress-bar-variant($progress-bar-warning-bg);
+}
+
+.progress-bar-danger {
+ @include progress-bar-variant($progress-bar-danger-bg);
+}
diff --git a/app/assets/stylesheets/bootstrap/_responsive-utilities.scss b/app/assets/stylesheets/bootstrap/_responsive-utilities.scss
new file mode 100644
index 0000000..cd9348c
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_responsive-utilities.scss
@@ -0,0 +1,74 @@
+//
+// Responsive: Utility classes
+// --------------------------------------------------
+
+
+// IE10 in Windows (Phone) 8
+//
+// Support for responsive views via media queries is kind of borked in IE10, for
+// Surface/desktop in split view and for Windows Phone 8. This particular fix
+// must be accompanied by a snippet of JavaScript to sniff the user agent and
+// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at
+// our Getting Started page for more information on this bug.
+//
+// For more information, see the following:
+//
+// Issue: https://github.com/twbs/bootstrap/issues/10497
+// Docs: http://getbootstrap.com/getting-started/#browsers
+// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/
+
+@-ms-viewport {
+ width: device-width;
+}
+
+
+// Visibility utilities
+
+@include responsive-invisibility('.visible-xs, .visible-sm, .visible-md, .visible-lg');
+
+@media (max-width: $screen-xs-max) {
+ @include responsive-visibility('.visible-xs');
+}
+
+@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
+ @include responsive-visibility('.visible-sm');
+}
+
+@media (min-width: $screen-md-min) and (max-width: $screen-md-max) {
+ @include responsive-visibility('.visible-md');
+}
+
+@media (min-width: $screen-lg-min) {
+ @include responsive-visibility('.visible-lg');
+}
+
+@media (max-width: $screen-xs-max) {
+ @include responsive-invisibility('.hidden-xs');
+}
+
+@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
+ @include responsive-invisibility('.hidden-sm');
+}
+
+@media (min-width: $screen-md-min) and (max-width: $screen-md-max) {
+ @include responsive-invisibility('.hidden-md');
+}
+
+@media (min-width: $screen-lg-min) {
+ @include responsive-invisibility('.hidden-lg');
+}
+
+
+// Print utilities
+//
+// Media queries are placed on the inside to be mixin-friendly.
+
+@include responsive-invisibility('.visible-print');
+
+@media print {
+ @include responsive-visibility('.visible-print');
+}
+
+@media print {
+ @include responsive-invisibility('.hidden-print');
+}
diff --git a/app/assets/stylesheets/bootstrap/_scaffolding.scss b/app/assets/stylesheets/bootstrap/_scaffolding.scss
new file mode 100644
index 0000000..cf02029
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_scaffolding.scss
@@ -0,0 +1,134 @@
+//
+// Scaffolding
+// --------------------------------------------------
+
+
+// Reset the box-sizing
+//
+// Heads up! This reset may cause conflicts with some third-party widgets.
+// For recommendations on resolving such conflicts, see
+// http://getbootstrap.com/getting-started/#third-box-sizing
+* {
+ @include box-sizing(border-box);
+}
+*:before,
+*:after {
+ @include box-sizing(border-box);
+}
+
+
+// Body reset
+
+html {
+ font-size: 62.5%;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+}
+
+body {
+ font-family: $font-family-base;
+ font-size: $font-size-base;
+ line-height: $line-height-base;
+ color: $text-color;
+ background-color: $body-bg;
+}
+
+// Reset fonts for relevant elements
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+
+
+// Links
+
+a {
+ color: $link-color;
+ text-decoration: none;
+
+ &:hover,
+ &:focus {
+ color: $link-hover-color;
+ text-decoration: underline;
+ }
+
+ &:focus {
+ @include tab-focus();
+ }
+}
+
+
+// Figures
+//
+// We reset this here because previously Normalize had no `figure` margins. This
+// ensures we don't break anyone's use of the element.
+
+figure {
+ margin: 0;
+}
+
+
+// Images
+
+img {
+ vertical-align: middle;
+}
+
+// Responsive images (ensure images don't scale beyond their parents)
+.img-responsive {
+ @include img-responsive();
+}
+
+// Rounded corners
+.img-rounded {
+ border-radius: $border-radius-large;
+}
+
+// Image thumbnails
+//
+// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.
+.img-thumbnail {
+ padding: $thumbnail-padding;
+ line-height: $line-height-base;
+ background-color: $thumbnail-bg;
+ border: 1px solid $thumbnail-border;
+ border-radius: $thumbnail-border-radius;
+ @include transition(all .2s ease-in-out);
+
+ // Keep them at most 100% wide
+ @include img-responsive(inline-block);
+}
+
+// Perfect circle
+.img-circle {
+ border-radius: 50%; // set radius in percents
+}
+
+
+// Horizontal rules
+
+hr {
+ margin-top: $line-height-computed;
+ margin-bottom: $line-height-computed;
+ border: 0;
+ border-top: 1px solid $hr-border;
+}
+
+
+// Only display content to screen readers
+//
+// See: http://a11yproject.com/posts/how-to-hide-content/
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ border: 0;
+}
diff --git a/app/assets/stylesheets/bootstrap/_tables.scss b/app/assets/stylesheets/bootstrap/_tables.scss
new file mode 100644
index 0000000..1ddfb7a
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_tables.scss
@@ -0,0 +1,233 @@
+//
+// Tables
+// --------------------------------------------------
+
+
+table {
+ max-width: 100%;
+ background-color: $table-bg;
+}
+th {
+ text-align: left;
+}
+
+
+// Baseline styles
+
+.table {
+ width: 100%;
+ margin-bottom: $line-height-computed;
+ // Cells
+ > thead,
+ > tbody,
+ > tfoot {
+ > tr {
+ > th,
+ > td {
+ padding: $table-cell-padding;
+ line-height: $line-height-base;
+ vertical-align: top;
+ border-top: 1px solid $table-border-color;
+ }
+ }
+ }
+ // Bottom align for column headings
+ > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid $table-border-color;
+ }
+ // Remove top border from thead by default
+ > caption + thead,
+ > colgroup + thead,
+ > thead:first-child {
+ > tr:first-child {
+ > th,
+ > td {
+ border-top: 0;
+ }
+ }
+ }
+ // Account for multiple tbody instances
+ > tbody + tbody {
+ border-top: 2px solid $table-border-color;
+ }
+
+ // Nesting
+ .table {
+ background-color: $body-bg;
+ }
+}
+
+
+// Condensed table w/ half padding
+
+.table-condensed {
+ > thead,
+ > tbody,
+ > tfoot {
+ > tr {
+ > th,
+ > td {
+ padding: $table-condensed-cell-padding;
+ }
+ }
+ }
+}
+
+
+// Bordered version
+//
+// Add borders all around the table and between all the columns.
+
+.table-bordered {
+ border: 1px solid $table-border-color;
+ > thead,
+ > tbody,
+ > tfoot {
+ > tr {
+ > th,
+ > td {
+ border: 1px solid $table-border-color;
+ }
+ }
+ }
+ > thead > tr {
+ > th,
+ > td {
+ border-bottom-width: 2px;
+ }
+ }
+}
+
+
+// Zebra-striping
+//
+// Default zebra-stripe styles (alternating gray and transparent backgrounds)
+
+.table-striped {
+ > tbody > tr:nth-child(odd) {
+ > td,
+ > th {
+ background-color: $table-bg-accent;
+ }
+ }
+}
+
+
+// Hover effect
+//
+// Placed here since it has to come after the potential zebra striping
+
+.table-hover {
+ > tbody > tr:hover {
+ > td,
+ > th {
+ background-color: $table-bg-hover;
+ }
+ }
+}
+
+
+// Table cell sizing
+//
+// Reset default table behavior
+
+table col[class*="col-"] {
+ position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)
+ float: none;
+ display: table-column;
+}
+table {
+ td,
+ th {
+ &[class*="col-"] {
+ position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)
+ float: none;
+ display: table-cell;
+ }
+ }
+}
+
+
+// Table backgrounds
+//
+// Exact selectors below required to override `.table-striped` and prevent
+// inheritance to nested tables.
+
+// Generate the contextual variants
+@include table-row-variant('active', $table-bg-active);
+@include table-row-variant('success', $state-success-bg);
+@include table-row-variant('info', $state-info-bg);
+@include table-row-variant('warning', $state-warning-bg);
+@include table-row-variant('danger', $state-danger-bg);
+
+
+// Responsive tables
+//
+// Wrap your tables in `.table-responsive` and we'll make them mobile friendly
+// by enabling horizontal scrolling. Only applies <768px. Everything above that
+// will display normally.
+
+@media (max-width: $screen-xs-max) {
+ .table-responsive {
+ width: 100%;
+ margin-bottom: ($line-height-computed * 0.75);
+ overflow-y: hidden;
+ overflow-x: scroll;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ border: 1px solid $table-border-color;
+ -webkit-overflow-scrolling: touch;
+
+ // Tighten up spacing
+ > .table {
+ margin-bottom: 0;
+
+ // Ensure the content doesn't wrap
+ > thead,
+ > tbody,
+ > tfoot {
+ > tr {
+ > th,
+ > td {
+ white-space: nowrap;
+ }
+ }
+ }
+ }
+
+ // Special overrides for the bordered tables
+ > .table-bordered {
+ border: 0;
+
+ // Nuke the appropriate borders so that the parent can handle them
+ > thead,
+ > tbody,
+ > tfoot {
+ > tr {
+ > th:first-child,
+ > td:first-child {
+ border-left: 0;
+ }
+ > th:last-child,
+ > td:last-child {
+ border-right: 0;
+ }
+ }
+ }
+
+ // Only nuke the last row's bottom-border in `tbody` and `tfoot` since
+ // chances are there will be only one `tr` in a `thead` and that would
+ // remove the border altogether.
+ > tbody,
+ > tfoot {
+ > tr:last-child {
+ > th,
+ > td {
+ border-bottom: 0;
+ }
+ }
+ }
+
+ }
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_theme.scss b/app/assets/stylesheets/bootstrap/_theme.scss
new file mode 100644
index 0000000..d8f7bc2
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_theme.scss
@@ -0,0 +1,247 @@
+
+//
+// Load core variables and mixins
+// --------------------------------------------------
+
+@import "variables";
+@import "mixins";
+
+
+
+//
+// Buttons
+// --------------------------------------------------
+
+// Common styles
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+ text-shadow: 0 -1px 0 rgba(0,0,0,.2);
+ $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);
+ @include box-shadow($shadow);
+
+ // Reset the shadow
+ &:active,
+ &.active {
+ @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
+ }
+}
+
+// Mixin for generating new styles
+@mixin btn-styles($btn-color: #555) {
+ @include gradient-vertical($start-color: $btn-color, $end-color: darken($btn-color, 12%));
+ @include reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners
+ background-repeat: repeat-x;
+ border-color: darken($btn-color, 14%);
+
+ &:hover,
+ &:focus {
+ background-color: darken($btn-color, 12%);
+ background-position: 0 -15px;
+ }
+
+ &:active,
+ &.active {
+ background-color: darken($btn-color, 12%);
+ border-color: darken($btn-color, 14%);
+ }
+}
+
+// Common styles
+.btn {
+ // Remove the gradient for the pressed/active state
+ &:active,
+ &.active {
+ background-image: none;
+ }
+}
+
+// Apply the mixin to the buttons
+.btn-default { @include btn-styles($btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }
+.btn-primary { @include btn-styles($btn-primary-bg); }
+.btn-success { @include btn-styles($btn-success-bg); }
+.btn-info { @include btn-styles($btn-info-bg); }
+.btn-warning { @include btn-styles($btn-warning-bg); }
+.btn-danger { @include btn-styles($btn-danger-bg); }
+
+
+
+//
+// Images
+// --------------------------------------------------
+
+.thumbnail,
+.img-thumbnail {
+ @include box-shadow(0 1px 2px rgba(0,0,0,.075));
+}
+
+
+
+//
+// Dropdowns
+// --------------------------------------------------
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ @include gradient-vertical($start-color: $dropdown-link-hover-bg, $end-color: darken($dropdown-link-hover-bg, 5%));
+ background-color: darken($dropdown-link-hover-bg, 5%);
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ @include gradient-vertical($start-color: $dropdown-link-active-bg, $end-color: darken($dropdown-link-active-bg, 5%));
+ background-color: darken($dropdown-link-active-bg, 5%);
+}
+
+
+
+//
+// Navbar
+// --------------------------------------------------
+
+// Default navbar
+.navbar-default {
+ @include gradient-vertical($start-color: lighten($navbar-default-bg, 10%), $end-color: $navbar-default-bg);
+ @include reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
+ border-radius: $navbar-border-radius;
+ $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);
+ @include box-shadow($shadow);
+
+ .navbar-nav > .active > a {
+ @include gradient-vertical($start-color: darken($navbar-default-bg, 5%), $end-color: darken($navbar-default-bg, 2%));
+ @include box-shadow(inset 0 3px 9px rgba(0,0,0,.075));
+ }
+}
+.navbar-brand,
+.navbar-nav > li > a {
+ text-shadow: 0 1px 0 rgba(255,255,255,.25);
+}
+
+// Inverted navbar
+.navbar-inverse {
+ @include gradient-vertical($start-color: lighten($navbar-inverse-bg, 10%), $end-color: $navbar-inverse-bg);
+ @include reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
+
+ .navbar-nav > .active > a {
+ @include gradient-vertical($start-color: $navbar-inverse-bg, $end-color: lighten($navbar-inverse-bg, 2.5%));
+ @include box-shadow(inset 0 3px 9px rgba(0,0,0,.25));
+ }
+
+ .navbar-brand,
+ .navbar-nav > li > a {
+ text-shadow: 0 -1px 0 rgba(0,0,0,.25);
+ }
+}
+
+// Undo rounded corners in static and fixed navbars
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ border-radius: 0;
+}
+
+
+
+//
+// Alerts
+// --------------------------------------------------
+
+// Common styles
+.alert {
+ text-shadow: 0 1px 0 rgba(255,255,255,.2);
+ $shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);
+ @include box-shadow($shadow);
+}
+
+// Mixin for generating new styles
+@mixin alert-styles($color) {
+ @include gradient-vertical($start-color: $color, $end-color: darken($color, 7.5%));
+ border-color: darken($color, 15%);
+}
+
+// Apply the mixin to the alerts
+.alert-success { @include alert-styles($alert-success-bg); }
+.alert-info { @include alert-styles($alert-info-bg); }
+.alert-warning { @include alert-styles($alert-warning-bg); }
+.alert-danger { @include alert-styles($alert-danger-bg); }
+
+
+
+//
+// Progress bars
+// --------------------------------------------------
+
+// Give the progress background some depth
+.progress {
+ @include gradient-vertical($start-color: darken($progress-bg, 4%), $end-color: $progress-bg)
+}
+
+// Mixin for generating new styles
+@mixin progress-bar-styles($color) {
+ @include gradient-vertical($start-color: $color, $end-color: darken($color, 10%));
+}
+
+// Apply the mixin to the progress bars
+.progress-bar { @include progress-bar-styles($progress-bar-bg); }
+.progress-bar-success { @include progress-bar-styles($progress-bar-success-bg); }
+.progress-bar-info { @include progress-bar-styles($progress-bar-info-bg); }
+.progress-bar-warning { @include progress-bar-styles($progress-bar-warning-bg); }
+.progress-bar-danger { @include progress-bar-styles($progress-bar-danger-bg); }
+
+
+
+//
+// List groups
+// --------------------------------------------------
+
+.list-group {
+ border-radius: $border-radius-base;
+ @include box-shadow(0 1px 2px rgba(0,0,0,.075));
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ text-shadow: 0 -1px 0 darken($list-group-active-bg, 10%);
+ @include gradient-vertical($start-color: $list-group-active-bg, $end-color: darken($list-group-active-bg, 7.5%));
+ border-color: darken($list-group-active-border, 7.5%);
+}
+
+
+
+//
+// Panels
+// --------------------------------------------------
+
+// Common styles
+.panel {
+ @include box-shadow(0 1px 2px rgba(0,0,0,.05));
+}
+
+// Mixin for generating new styles
+@mixin panel-heading-styles($color) {
+ @include gradient-vertical($start-color: $color, $end-color: darken($color, 5%));
+}
+
+// Apply the mixin to the panel headings only
+.panel-default > .panel-heading { @include panel-heading-styles($panel-default-heading-bg); }
+.panel-primary > .panel-heading { @include panel-heading-styles($panel-primary-heading-bg); }
+.panel-success > .panel-heading { @include panel-heading-styles($panel-success-heading-bg); }
+.panel-info > .panel-heading { @include panel-heading-styles($panel-info-heading-bg); }
+.panel-warning > .panel-heading { @include panel-heading-styles($panel-warning-heading-bg); }
+.panel-danger > .panel-heading { @include panel-heading-styles($panel-danger-heading-bg); }
+
+
+
+//
+// Wells
+// --------------------------------------------------
+
+.well {
+ @include gradient-vertical($start-color: darken($well-bg, 5%), $end-color: $well-bg);
+ border-color: darken($well-bg, 10%);
+ $shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);
+ @include box-shadow($shadow);
+}
diff --git a/app/assets/stylesheets/bootstrap/_thumbnails.scss b/app/assets/stylesheets/bootstrap/_thumbnails.scss
new file mode 100644
index 0000000..3d5ed86
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_thumbnails.scss
@@ -0,0 +1,38 @@
+//
+// Thumbnails
+// --------------------------------------------------
+
+
+// Mixin and adjust the regular image class
+.thumbnail {
+ display: block;
+ padding: $thumbnail-padding;
+ margin-bottom: $line-height-computed;
+ line-height: $line-height-base;
+ background-color: $thumbnail-bg;
+ border: 1px solid $thumbnail-border;
+ border-radius: $thumbnail-border-radius;
+ @include transition(all .2s ease-in-out);
+
+ > img,
+ a > img {
+ @include img-responsive();
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ // [converter] extracted a&:hover, a&:focus, a&.active to a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active
+
+ // Image captions
+ .caption {
+ padding: $thumbnail-caption-padding;
+ color: $thumbnail-caption-color;
+ }
+}
+
+// Add a hover state for linked versions only
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+ border-color: $link-color;
+}
diff --git a/app/assets/stylesheets/bootstrap/_tooltip.scss b/app/assets/stylesheets/bootstrap/_tooltip.scss
new file mode 100644
index 0000000..dec674c
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_tooltip.scss
@@ -0,0 +1,95 @@
+//
+// Tooltips
+// --------------------------------------------------
+
+
+// Base class
+.tooltip {
+ position: absolute;
+ z-index: $zindex-tooltip;
+ display: block;
+ visibility: visible;
+ font-size: $font-size-small;
+ line-height: 1.4;
+ @include opacity(0);
+
+ &.in { @include opacity($tooltip-opacity); }
+ &.top { margin-top: -3px; padding: $tooltip-arrow-width 0; }
+ &.right { margin-left: 3px; padding: 0 $tooltip-arrow-width; }
+ &.bottom { margin-top: 3px; padding: $tooltip-arrow-width 0; }
+ &.left { margin-left: -3px; padding: 0 $tooltip-arrow-width; }
+}
+
+// Wrapper for the tooltip content
+.tooltip-inner {
+ max-width: $tooltip-max-width;
+ padding: 3px 8px;
+ color: $tooltip-color;
+ text-align: center;
+ text-decoration: none;
+ background-color: $tooltip-bg;
+ border-radius: $border-radius-base;
+}
+
+// Arrows
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.tooltip {
+ &.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -$tooltip-arrow-width;
+ border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
+ border-top-color: $tooltip-arrow-color;
+ }
+ &.top-left .tooltip-arrow {
+ bottom: 0;
+ left: $tooltip-arrow-width;
+ border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
+ border-top-color: $tooltip-arrow-color;
+ }
+ &.top-right .tooltip-arrow {
+ bottom: 0;
+ right: $tooltip-arrow-width;
+ border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
+ border-top-color: $tooltip-arrow-color;
+ }
+ &.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -$tooltip-arrow-width;
+ border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0;
+ border-right-color: $tooltip-arrow-color;
+ }
+ &.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -$tooltip-arrow-width;
+ border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width;
+ border-left-color: $tooltip-arrow-color;
+ }
+ &.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -$tooltip-arrow-width;
+ border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
+ border-bottom-color: $tooltip-arrow-color;
+ }
+ &.bottom-left .tooltip-arrow {
+ top: 0;
+ left: $tooltip-arrow-width;
+ border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
+ border-bottom-color: $tooltip-arrow-color;
+ }
+ &.bottom-right .tooltip-arrow {
+ top: 0;
+ right: $tooltip-arrow-width;
+ border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
+ border-bottom-color: $tooltip-arrow-color;
+ }
+}
diff --git a/app/assets/stylesheets/bootstrap/_type.scss b/app/assets/stylesheets/bootstrap/_type.scss
new file mode 100644
index 0000000..7fee043
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_type.scss
@@ -0,0 +1,284 @@
+//
+// Typography
+// --------------------------------------------------
+
+
+// Headings
+// -------------------------
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+ font-family: $headings-font-family;
+ font-weight: $headings-font-weight;
+ line-height: $headings-line-height;
+ color: $headings-color;
+
+ small,
+ .small {
+ font-weight: normal;
+ line-height: 1;
+ color: $headings-small-color;
+ }
+}
+
+h1, .h1,
+h2, .h2,
+h3, .h3 {
+ margin-top: $line-height-computed;
+ margin-bottom: ($line-height-computed / 2);
+
+ small,
+ .small {
+ font-size: 65%;
+ }
+}
+h4, .h4,
+h5, .h5,
+h6, .h6 {
+ margin-top: ($line-height-computed / 2);
+ margin-bottom: ($line-height-computed / 2);
+
+ small,
+ .small {
+ font-size: 75%;
+ }
+}
+
+h1, .h1 { font-size: $font-size-h1; }
+h2, .h2 { font-size: $font-size-h2; }
+h3, .h3 { font-size: $font-size-h3; }
+h4, .h4 { font-size: $font-size-h4; }
+h5, .h5 { font-size: $font-size-h5; }
+h6, .h6 { font-size: $font-size-h6; }
+
+
+// Body text
+// -------------------------
+
+p {
+ margin: 0 0 ($line-height-computed / 2);
+}
+
+.lead {
+ margin-bottom: $line-height-computed;
+ font-size: floor(($font-size-base * 1.15));
+ font-weight: 200;
+ line-height: 1.4;
+
+ @media (min-width: $screen-sm-min) {
+ font-size: ($font-size-base * 1.5);
+ }
+}
+
+
+// Emphasis & misc
+// -------------------------
+
+// Ex: 14px base font * 85% = about 12px
+small,
+.small { font-size: 85%; }
+
+// Undo browser default styling
+cite { font-style: normal; }
+
+// Alignment
+.text-left { text-align: left; }
+.text-right { text-align: right; }
+.text-center { text-align: center; }
+.text-justify { text-align: justify; }
+
+// Contextual colors
+.text-muted {
+ color: $text-muted;
+}
+
+@include text-emphasis-variant('.text-primary', $brand-primary);
+
+@include text-emphasis-variant('.text-success', $state-success-text);
+
+@include text-emphasis-variant('.text-info', $state-info-text);
+
+@include text-emphasis-variant('.text-warning', $state-warning-text);
+
+@include text-emphasis-variant('.text-danger', $state-danger-text);
+
+// Contextual backgrounds
+// For now we'll leave these alongside the text classes until v4 when we can
+// safely shift things around (per SemVer rules).
+.bg-primary {
+ // Given the contrast here, this is the only class to have its color inverted
+ // automatically.
+ color: #fff;
+}
+@include bg-variant('.bg-primary', $brand-primary);
+
+@include bg-variant('.bg-success', $state-success-bg);
+
+@include bg-variant('.bg-info', $state-info-bg);
+
+@include bg-variant('.bg-warning', $state-warning-bg);
+
+@include bg-variant('.bg-danger', $state-danger-bg);
+
+
+// Page header
+// -------------------------
+
+.page-header {
+ padding-bottom: (($line-height-computed / 2) - 1);
+ margin: ($line-height-computed * 2) 0 $line-height-computed;
+ border-bottom: 1px solid $page-header-border-color;
+}
+
+
+// Lists
+// --------------------------------------------------
+
+// Unordered and Ordered lists
+ul,
+ol {
+ margin-top: 0;
+ margin-bottom: ($line-height-computed / 2);
+ ul,
+ ol {
+ margin-bottom: 0;
+ }
+}
+
+// List options
+
+// Unstyled keeps list items block level, just removes default browser padding and list-style
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+
+// Inline turns list items into inline-block
+.list-inline {
+ @extend .list-unstyled;
+ margin-left: -5px;
+
+ > li {
+ display: inline-block;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+}
+
+// Description Lists
+dl {
+ margin-top: 0; // Remove browser default
+ margin-bottom: $line-height-computed;
+}
+dt,
+dd {
+ line-height: $line-height-base;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: 0; // Undo browser default
+}
+
+// Horizontal description lists
+//
+// Defaults to being stacked without any of the below styles applied, until the
+// grid breakpoint is reached (default of ~768px).
+
+@media (min-width: $grid-float-breakpoint) {
+ .dl-horizontal {
+ dt {
+ float: left;
+ width: ($component-offset-horizontal - 20);
+ clear: left;
+ text-align: right;
+ @include text-overflow();
+ }
+ dd {
+ margin-left: $component-offset-horizontal;
+ @include clearfix(); // Clear the floated `dt` if an empty `dd` is present
+ }
+ }
+}
+
+// MISC
+// ----
+
+// Abbreviations and acronyms
+abbr[title],
+// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted $abbr-border-color;
+}
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+
+// Blockquotes
+blockquote {
+ padding: ($line-height-computed / 2) $line-height-computed;
+ margin: 0 0 $line-height-computed;
+ font-size: $blockquote-font-size;
+ border-left: 5px solid $blockquote-border-color;
+
+ p,
+ ul,
+ ol {
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ // Note: Deprecated small and .small as of v3.1.0
+ // Context: https://github.com/twbs/bootstrap/issues/11660
+ footer,
+ small,
+ .small {
+ display: block;
+ font-size: 80%; // back to default font-size
+ line-height: $line-height-base;
+ color: $blockquote-small-color;
+
+ &:before {
+ content: '\2014 \00A0'; // em dash, nbsp
+ }
+ }
+}
+
+// Opposite alignment of blockquote
+//
+// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.
+.blockquote-reverse,
+blockquote.pull-right {
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid $blockquote-border-color;
+ border-left: 0;
+ text-align: right;
+
+ // Account for citation
+ footer,
+ small,
+ .small {
+ &:before { content: ''; }
+ &:after {
+ content: '\00A0 \2014'; // nbsp, em dash
+ }
+ }
+}
+
+// Quotes
+blockquote:before,
+blockquote:after {
+ content: "";
+}
+
+// Addresses
+address {
+ margin-bottom: $line-height-computed;
+ font-style: normal;
+ line-height: $line-height-base;
+}
diff --git a/app/assets/stylesheets/bootstrap/_utilities.scss b/app/assets/stylesheets/bootstrap/_utilities.scss
new file mode 100644
index 0000000..85cb62e
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_utilities.scss
@@ -0,0 +1,56 @@
+//
+// Utility classes
+// --------------------------------------------------
+
+
+// Floats
+// -------------------------
+
+.clearfix {
+ @include clearfix();
+}
+.center-block {
+ @include center-block();
+}
+.pull-right {
+ float: right !important;
+}
+.pull-left {
+ float: left !important;
+}
+
+
+// Toggling content
+// -------------------------
+
+// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1
+.hide {
+ display: none !important;
+}
+.show {
+ display: block !important;
+}
+.invisible {
+ visibility: hidden;
+}
+.text-hide {
+ @include text-hide();
+}
+
+
+// Hide from screenreaders and browsers
+//
+// Credit: HTML5 Boilerplate
+
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+
+
+// For Affix plugin
+// -------------------------
+
+.affix {
+ position: fixed;
+}
diff --git a/app/assets/stylesheets/bootstrap/_variables.scss b/app/assets/stylesheets/bootstrap/_variables.scss
new file mode 100644
index 0000000..6e8f9ff
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_variables.scss
@@ -0,0 +1,833 @@
+// a flag to toggle asset pipeline / compass integration
+// defaults to true if twbs-font-path function is present (no function => twbs-font-path('') parsed as string == right side)
+// in Sass 3.3 this can be improved with: function-exists(twbs-font-path)
+$bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")')) !default;
+//
+// Variables
+// --------------------------------------------------
+
+
+//== Colors
+//
+//## Gray and brand colors for use across Bootstrap.
+
+$gray-darker: lighten(#000, 13.5%) !default; // #222
+$gray-dark: lighten(#000, 20%) !default; // #333
+$gray: lighten(#000, 33.5%) !default; // #555
+$gray-light: lighten(#000, 60%) !default; // #999
+$gray-lighter: lighten(#000, 93.5%) !default; // #eee
+
+$brand-primary: #428bca !default;
+$brand-success: #5cb85c !default;
+$brand-info: #5bc0de !default;
+$brand-warning: #f0ad4e !default;
+$brand-danger: #d9534f !default;
+
+
+//== Scaffolding
+//
+// ## Settings for some of the most global styles.
+
+//** Background color for ``.
+$body-bg: #fff !default;
+//** Global text color on ``.
+$text-color: $gray-dark !default;
+
+//** Global textual link color.
+$link-color: $brand-primary !default;
+//** Link hover color set via `darken()` function.
+$link-hover-color: darken($link-color, 15%) !default;
+
+
+//== Typography
+//
+//## Font, line-height, and color for body text, headings, and more.
+
+$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif !default;
+$font-family-serif: Georgia, "Times New Roman", Times, serif !default;
+//** Default monospace fonts for ``, ``, and ``.
+$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace !default;
+$font-family-base: $font-family-sans-serif !default;
+
+$font-size-base: 14px !default;
+$font-size-large: ceil(($font-size-base * 1.25)) !default; // ~18px
+$font-size-small: ceil(($font-size-base * 0.85)) !default; // ~12px
+
+$font-size-h1: floor(($font-size-base * 2.6)) !default; // ~36px
+$font-size-h2: floor(($font-size-base * 2.15)) !default; // ~30px
+$font-size-h3: ceil(($font-size-base * 1.7)) !default; // ~24px
+$font-size-h4: ceil(($font-size-base * 1.25)) !default; // ~18px
+$font-size-h5: $font-size-base !default;
+$font-size-h6: ceil(($font-size-base * 0.85)) !default; // ~12px
+
+//** Unit-less `line-height` for use in components like buttons.
+$line-height-base: 1.428571429 !default; // 20/14
+//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
+$line-height-computed: floor(($font-size-base * $line-height-base)) !default; // ~20px
+
+//** By default, this inherits from the ``.
+$headings-font-family: inherit !default;
+$headings-font-weight: 300 !default;
+$headings-line-height: 1.1 !default;
+$headings-color: inherit !default;
+
+
+//-- Iconography
+//
+//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.
+
+$icon-font-path: "bootstrap/" !default;
+$icon-font-name: "glyphicons-halflings-regular" !default;
+$icon-font-svg-id: "glyphicons_halflingsregular" !default;
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+$padding-base-vertical: 6px !default;
+$padding-base-horizontal: 12px !default;
+
+$padding-large-vertical: 10px !default;
+$padding-large-horizontal: 16px !default;
+
+$padding-small-vertical: 5px !default;
+$padding-small-horizontal: 10px !default;
+
+$padding-xs-vertical: 1px !default;
+$padding-xs-horizontal: 5px !default;
+
+$line-height-large: 1.33 !default;
+$line-height-small: 1.5 !default;
+
+$border-radius-base: 4px !default;
+$border-radius-large: 6px !default;
+$border-radius-small: 3px !default;
+
+//** Global color for active items (e.g., navs or dropdowns).
+$component-active-color: #fff !default;
+//** Global background color for active items (e.g., navs or dropdowns).
+$component-active-bg: $brand-primary !default;
+
+//** Width of the `border` for generating carets that indicator dropdowns.
+$caret-width-base: 4px !default;
+//** Carets increase slightly in size for larger components.
+$caret-width-large: 5px !default;
+
+
+//== Tables
+//
+//## Customizes the `.table` component with basic values, each used across all table variations.
+
+//** Padding for ``s and ` `s.
+$table-cell-padding: 8px !default;
+//** Padding for cells in `.table-condensed`.
+$table-condensed-cell-padding: 5px !default;
+
+//** Default background color used for all tables.
+$table-bg: transparent !default;
+//** Background color used for `.table-striped`.
+$table-bg-accent: #f9f9f9 !default;
+//** Background color used for `.table-hover`.
+$table-bg-hover: #f5f5f5 !default;
+$table-bg-active: $table-bg-hover !default;
+
+//** Border color for table and cell borders.
+$table-border-color: #ddd !default;
+
+
+//== Buttons
+//
+//## For each of Bootstrap's buttons, define text, background and border color.
+
+$btn-font-weight: normal !default;
+
+$btn-default-color: #333 !default;
+$btn-default-bg: #fff !default;
+$btn-default-border: #ccc !default;
+
+$btn-primary-color: #fff !default;
+$btn-primary-bg: $brand-primary !default;
+$btn-primary-border: darken($btn-primary-bg, 5%) !default;
+
+$btn-success-color: #fff !default;
+$btn-success-bg: $brand-success !default;
+$btn-success-border: darken($btn-success-bg, 5%) !default;
+
+$btn-info-color: #fff !default;
+$btn-info-bg: $brand-info !default;
+$btn-info-border: darken($btn-info-bg, 5%) !default;
+
+$btn-warning-color: #fff !default;
+$btn-warning-bg: $brand-warning !default;
+$btn-warning-border: darken($btn-warning-bg, 5%) !default;
+
+$btn-danger-color: #fff !default;
+$btn-danger-bg: $brand-danger !default;
+$btn-danger-border: darken($btn-danger-bg, 5%) !default;
+
+$btn-link-disabled-color: $gray-light !default;
+
+
+//== Forms
+//
+//##
+
+//** ` ` background color
+$input-bg: #fff !default;
+//** ` ` background color
+$input-bg-disabled: $gray-lighter !default;
+
+//** Text color for ` `s
+$input-color: $gray !default;
+//** ` ` border color
+$input-border: #ccc !default;
+//** ` ` border radius
+$input-border-radius: $border-radius-base !default;
+//** Border color for inputs on focus
+$input-border-focus: #66afe9 !default;
+
+//** Placeholder text color
+$input-color-placeholder: $gray-light !default;
+
+//** Default `.form-control` height
+$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
+//** Large `.form-control` height
+$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
+//** Small `.form-control` height
+$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
+
+$legend-color: $gray-dark !default;
+$legend-border-color: #e5e5e5 !default;
+
+//** Background color for textual input addons
+$input-group-addon-bg: $gray-lighter !default;
+//** Border color for textual input addons
+$input-group-addon-border-color: $input-border !default;
+
+
+//== Dropdowns
+//
+//## Dropdown menu container and contents.
+
+//** Background for the dropdown menu.
+$dropdown-bg: #fff !default;
+//** Dropdown menu `border-color`.
+$dropdown-border: rgba(0,0,0,.15) !default;
+//** Dropdown menu `border-color` **for IE8**.
+$dropdown-fallback-border: #ccc !default;
+//** Divider color for between dropdown items.
+$dropdown-divider-bg: #e5e5e5 !default;
+
+//** Dropdown link text color.
+$dropdown-link-color: $gray-dark !default;
+//** Hover color for dropdown links.
+$dropdown-link-hover-color: darken($gray-dark, 5%) !default;
+//** Hover background for dropdown links.
+$dropdown-link-hover-bg: #f5f5f5 !default;
+
+//** Active dropdown menu item text color.
+$dropdown-link-active-color: $component-active-color !default;
+//** Active dropdown menu item background color.
+$dropdown-link-active-bg: $component-active-bg !default;
+
+//** Disabled dropdown menu item background color.
+$dropdown-link-disabled-color: $gray-light !default;
+
+//** Text color for headers within dropdown menus.
+$dropdown-header-color: $gray-light !default;
+
+// Note: Deprecated $dropdown-caret-color as of v3.1.0
+$dropdown-caret-color: #000 !default;
+
+
+//-- Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+//
+// Note: These variables are not generated into the Customizer.
+
+$zindex-navbar: 1000 !default;
+$zindex-dropdown: 1000 !default;
+$zindex-popover: 1010 !default;
+$zindex-tooltip: 1030 !default;
+$zindex-navbar-fixed: 1030 !default;
+$zindex-modal-background: 1040 !default;
+$zindex-modal: 1050 !default;
+
+
+//== Media queries breakpoints
+//
+//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
+
+// Extra small screen / phone
+// Note: Deprecated $screen-xs and $screen-phone as of v3.0.1
+$screen-xs: 480px !default;
+$screen-xs-min: $screen-xs !default;
+$screen-phone: $screen-xs-min !default;
+
+// Small screen / tablet
+// Note: Deprecated $screen-sm and $screen-tablet as of v3.0.1
+$screen-sm: 768px !default;
+$screen-sm-min: $screen-sm !default;
+$screen-tablet: $screen-sm-min !default;
+
+// Medium screen / desktop
+// Note: Deprecated $screen-md and $screen-desktop as of v3.0.1
+$screen-md: 992px !default;
+$screen-md-min: $screen-md !default;
+$screen-desktop: $screen-md-min !default;
+
+// Large screen / wide desktop
+// Note: Deprecated $screen-lg and $screen-lg-desktop as of v3.0.1
+$screen-lg: 1200px !default;
+$screen-lg-min: $screen-lg !default;
+$screen-lg-desktop: $screen-lg-min !default;
+
+// So media queries don't overlap when required, provide a maximum
+$screen-xs-max: ($screen-sm-min - 1) !default;
+$screen-sm-max: ($screen-md-min - 1) !default;
+$screen-md-max: ($screen-lg-min - 1) !default;
+
+
+//== Grid system
+//
+//## Define your custom responsive grid.
+
+//** Number of columns in the grid.
+$grid-columns: 12 !default;
+//** Padding between columns. Gets divided in half for the left and right.
+$grid-gutter-width: 30px !default;
+// Navbar collapse
+//** Point at which the navbar becomes uncollapsed.
+$grid-float-breakpoint: $screen-sm-min !default;
+//** Point at which the navbar begins collapsing.
+$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
+
+
+//== Container sizes
+//
+//## Define the maximum width of `.container` for different screen sizes.
+
+// Small screen / tablet
+$container-tablet: ((720px + $grid-gutter-width)) !default;
+//** For `$screen-sm-min` and up.
+$container-sm: $container-tablet !default;
+
+// Medium screen / desktop
+$container-desktop: ((940px + $grid-gutter-width)) !default;
+//** For `$screen-md-min` and up.
+$container-md: $container-desktop !default;
+
+// Large screen / wide desktop
+$container-large-desktop: ((1140px + $grid-gutter-width)) !default;
+//** For `$screen-lg-min` and up.
+$container-lg: $container-large-desktop !default;
+
+
+//== Navbar
+//
+//##
+
+// Basics of a navbar
+$navbar-height: 50px !default;
+$navbar-margin-bottom: $line-height-computed !default;
+$navbar-border-radius: $border-radius-base !default;
+$navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default;
+$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) !default;
+$navbar-collapse-max-height: 340px !default;
+
+$navbar-default-color: #777 !default;
+$navbar-default-bg: #f8f8f8 !default;
+$navbar-default-border: darken($navbar-default-bg, 6.5%) !default;
+
+// Navbar links
+$navbar-default-link-color: #777 !default;
+$navbar-default-link-hover-color: #333 !default;
+$navbar-default-link-hover-bg: transparent !default;
+$navbar-default-link-active-color: #555 !default;
+$navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%) !default;
+$navbar-default-link-disabled-color: #ccc !default;
+$navbar-default-link-disabled-bg: transparent !default;
+
+// Navbar brand label
+$navbar-default-brand-color: $navbar-default-link-color !default;
+$navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%) !default;
+$navbar-default-brand-hover-bg: transparent !default;
+
+// Navbar toggle
+$navbar-default-toggle-hover-bg: #ddd !default;
+$navbar-default-toggle-icon-bar-bg: #888 !default;
+$navbar-default-toggle-border-color: #ddd !default;
+
+
+// Inverted navbar
+// Reset inverted navbar basics
+$navbar-inverse-color: $gray-light !default;
+$navbar-inverse-bg: #222 !default;
+$navbar-inverse-border: darken($navbar-inverse-bg, 10%) !default;
+
+// Inverted navbar links
+$navbar-inverse-link-color: $gray-light !default;
+$navbar-inverse-link-hover-color: #fff !default;
+$navbar-inverse-link-hover-bg: transparent !default;
+$navbar-inverse-link-active-color: $navbar-inverse-link-hover-color !default;
+$navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%) !default;
+$navbar-inverse-link-disabled-color: #444 !default;
+$navbar-inverse-link-disabled-bg: transparent !default;
+
+// Inverted navbar brand label
+$navbar-inverse-brand-color: $navbar-inverse-link-color !default;
+$navbar-inverse-brand-hover-color: #fff !default;
+$navbar-inverse-brand-hover-bg: transparent !default;
+
+// Inverted navbar toggle
+$navbar-inverse-toggle-hover-bg: #333 !default;
+$navbar-inverse-toggle-icon-bar-bg: #fff !default;
+$navbar-inverse-toggle-border-color: #333 !default;
+
+
+//== Navs
+//
+//##
+
+//=== Shared nav styles
+$nav-link-padding: 10px 15px !default;
+$nav-link-hover-bg: $gray-lighter !default;
+
+$nav-disabled-link-color: $gray-light !default;
+$nav-disabled-link-hover-color: $gray-light !default;
+
+$nav-open-link-hover-color: #fff !default;
+
+//== Tabs
+$nav-tabs-border-color: #ddd !default;
+
+$nav-tabs-link-hover-border-color: $gray-lighter !default;
+
+$nav-tabs-active-link-hover-bg: $body-bg !default;
+$nav-tabs-active-link-hover-color: $gray !default;
+$nav-tabs-active-link-hover-border-color: #ddd !default;
+
+$nav-tabs-justified-link-border-color: #ddd !default;
+$nav-tabs-justified-active-link-border-color: $body-bg !default;
+
+//== Pills
+$nav-pills-border-radius: $border-radius-base !default;
+$nav-pills-active-link-hover-bg: $component-active-bg !default;
+$nav-pills-active-link-hover-color: $component-active-color !default;
+
+
+//== Pagination
+//
+//##
+
+$pagination-color: $link-color !default;
+$pagination-bg: #fff !default;
+$pagination-border: #ddd !default;
+
+$pagination-hover-color: $link-hover-color !default;
+$pagination-hover-bg: $gray-lighter !default;
+$pagination-hover-border: #ddd !default;
+
+$pagination-active-color: #fff !default;
+$pagination-active-bg: $brand-primary !default;
+$pagination-active-border: $brand-primary !default;
+
+$pagination-disabled-color: $gray-light !default;
+$pagination-disabled-bg: #fff !default;
+$pagination-disabled-border: #ddd !default;
+
+
+//== Pager
+//
+//##
+
+$pager-bg: $pagination-bg !default;
+$pager-border: $pagination-border !default;
+$pager-border-radius: 15px !default;
+
+$pager-hover-bg: $pagination-hover-bg !default;
+
+$pager-active-bg: $pagination-active-bg !default;
+$pager-active-color: $pagination-active-color !default;
+
+$pager-disabled-color: $pagination-disabled-color !default;
+
+
+//== Jumbotron
+//
+//##
+
+$jumbotron-padding: 30px !default;
+$jumbotron-color: inherit !default;
+$jumbotron-bg: $gray-lighter !default;
+$jumbotron-heading-color: inherit !default;
+$jumbotron-font-size: ceil(($font-size-base * 1.5)) !default;
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+$state-success-text: #3c763d !default;
+$state-success-bg: #dff0d8 !default;
+$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%) !default;
+
+$state-info-text: #31708f !default;
+$state-info-bg: #d9edf7 !default;
+$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%) !default;
+
+$state-warning-text: #8a6d3b !default;
+$state-warning-bg: #fcf8e3 !default;
+$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%) !default;
+
+$state-danger-text: #a94442 !default;
+$state-danger-bg: #f2dede !default;
+$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%) !default;
+
+
+//== Tooltips
+//
+//##
+
+//** Tooltip max width
+$tooltip-max-width: 200px !default;
+//** Tooltip text color
+$tooltip-color: #fff !default;
+//** Tooltip background color
+$tooltip-bg: #000 !default;
+$tooltip-opacity: .9 !default;
+
+//** Tooltip arrow width
+$tooltip-arrow-width: 5px !default;
+//** Tooltip arrow color
+$tooltip-arrow-color: $tooltip-bg !default;
+
+
+//== Popovers
+//
+//##
+
+//** Popover body background color
+$popover-bg: #fff !default;
+//** Popover maximum width
+$popover-max-width: 276px !default;
+//** Popover border color
+$popover-border-color: rgba(0,0,0,.2) !default;
+//** Popover fallback border color
+$popover-fallback-border-color: #ccc !default;
+
+//** Popover title background color
+$popover-title-bg: darken($popover-bg, 3%) !default;
+
+//** Popover arrow width
+$popover-arrow-width: 10px !default;
+//** Popover arrow color
+$popover-arrow-color: #fff !default;
+
+//** Popover outer arrow width
+$popover-arrow-outer-width: ($popover-arrow-width + 1) !default;
+//** Popover outer arrow color
+$popover-arrow-outer-color: fadein($popover-border-color, 5%) !default;
+//** Popover outer arrow fallback color
+$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) !default;
+
+
+//== Labels
+//
+//##
+
+//** Default label background color
+$label-default-bg: $gray-light !default;
+//** Primary label background color
+$label-primary-bg: $brand-primary !default;
+//** Success label background color
+$label-success-bg: $brand-success !default;
+//** Info label background color
+$label-info-bg: $brand-info !default;
+//** Warning label background color
+$label-warning-bg: $brand-warning !default;
+//** Danger label background color
+$label-danger-bg: $brand-danger !default;
+
+//** Default label text color
+$label-color: #fff !default;
+//** Default text color of a linked label
+$label-link-hover-color: #fff !default;
+
+
+//== Modals
+//
+//##
+
+//** Padding applied to the modal body
+$modal-inner-padding: 20px !default;
+
+//** Padding applied to the modal title
+$modal-title-padding: 15px !default;
+//** Modal title line-height
+$modal-title-line-height: $line-height-base !default;
+
+//** Background color of modal content area
+$modal-content-bg: #fff !default;
+//** Modal content border color
+$modal-content-border-color: rgba(0,0,0,.2) !default;
+//** Modal content border color **for IE8**
+$modal-content-fallback-border-color: #999 !default;
+
+//** Modal backdrop background color
+$modal-backdrop-bg: #000 !default;
+//** Modal backdrop opacity
+$modal-backdrop-opacity: .5 !default;
+//** Modal header border color
+$modal-header-border-color: #e5e5e5 !default;
+//** Modal footer border color
+$modal-footer-border-color: $modal-header-border-color !default;
+
+$modal-lg: 900px !default;
+$modal-md: 600px !default;
+$modal-sm: 300px !default;
+
+
+//== Alerts
+//
+//## Define alert colors, border radius, and padding.
+
+$alert-padding: 15px !default;
+$alert-border-radius: $border-radius-base !default;
+$alert-link-font-weight: bold !default;
+
+$alert-success-bg: $state-success-bg !default;
+$alert-success-text: $state-success-text !default;
+$alert-success-border: $state-success-border !default;
+
+$alert-info-bg: $state-info-bg !default;
+$alert-info-text: $state-info-text !default;
+$alert-info-border: $state-info-border !default;
+
+$alert-warning-bg: $state-warning-bg !default;
+$alert-warning-text: $state-warning-text !default;
+$alert-warning-border: $state-warning-border !default;
+
+$alert-danger-bg: $state-danger-bg !default;
+$alert-danger-text: $state-danger-text !default;
+$alert-danger-border: $state-danger-border !default;
+
+
+//== Progress bars
+//
+//##
+
+//** Background color of the whole progress component
+$progress-bg: #f5f5f5 !default;
+//** Progress bar text color
+$progress-bar-color: #fff !default;
+
+//** Default progress bar color
+$progress-bar-bg: $brand-primary !default;
+//** Success progress bar color
+$progress-bar-success-bg: $brand-success !default;
+//** Warning progress bar color
+$progress-bar-warning-bg: $brand-warning !default;
+//** Danger progress bar color
+$progress-bar-danger-bg: $brand-danger !default;
+//** Info progress bar color
+$progress-bar-info-bg: $brand-info !default;
+
+
+//== List group
+//
+//##
+
+//** Background color on `.list-group-item`
+$list-group-bg: #fff !default;
+//** `.list-group-item` border color
+$list-group-border: #ddd !default;
+//** List group border radius
+$list-group-border-radius: $border-radius-base !default;
+
+//** Background color of single list elements on hover
+$list-group-hover-bg: #f5f5f5 !default;
+//** Text color of active list elements
+$list-group-active-color: $component-active-color !default;
+//** Background color of active list elements
+$list-group-active-bg: $component-active-bg !default;
+//** Border color of active list elements
+$list-group-active-border: $list-group-active-bg !default;
+$list-group-active-text-color: lighten($list-group-active-bg, 40%) !default;
+
+$list-group-link-color: #555 !default;
+$list-group-link-heading-color: #333 !default;
+
+
+//== Panels
+//
+//##
+
+$panel-bg: #fff !default;
+$panel-body-padding: 15px !default;
+$panel-border-radius: $border-radius-base !default;
+
+//** Border color for elements within panels
+$panel-inner-border: #ddd !default;
+$panel-footer-bg: #f5f5f5 !default;
+
+$panel-default-text: $gray-dark !default;
+$panel-default-border: #ddd !default;
+$panel-default-heading-bg: #f5f5f5 !default;
+
+$panel-primary-text: #fff !default;
+$panel-primary-border: $brand-primary !default;
+$panel-primary-heading-bg: $brand-primary !default;
+
+$panel-success-text: $state-success-text !default;
+$panel-success-border: $state-success-border !default;
+$panel-success-heading-bg: $state-success-bg !default;
+
+$panel-info-text: $state-info-text !default;
+$panel-info-border: $state-info-border !default;
+$panel-info-heading-bg: $state-info-bg !default;
+
+$panel-warning-text: $state-warning-text !default;
+$panel-warning-border: $state-warning-border !default;
+$panel-warning-heading-bg: $state-warning-bg !default;
+
+$panel-danger-text: $state-danger-text !default;
+$panel-danger-border: $state-danger-border !default;
+$panel-danger-heading-bg: $state-danger-bg !default;
+
+
+//== Thumbnails
+//
+//##
+
+//** Padding around the thumbnail image
+$thumbnail-padding: 4px !default;
+//** Thumbnail background color
+$thumbnail-bg: $body-bg !default;
+//** Thumbnail border color
+$thumbnail-border: #ddd !default;
+//** Thumbnail border radius
+$thumbnail-border-radius: $border-radius-base !default;
+
+//** Custom text color for thumbnail captions
+$thumbnail-caption-color: $text-color !default;
+//** Padding around the thumbnail caption
+$thumbnail-caption-padding: 9px !default;
+
+
+//== Wells
+//
+//##
+
+$well-bg: #f5f5f5 !default;
+$well-border: darken($well-bg, 7%) !default;
+
+
+//== Badges
+//
+//##
+
+$badge-color: #fff !default;
+//** Linked badge text color on hover
+$badge-link-hover-color: #fff !default;
+$badge-bg: $gray-light !default;
+
+//** Badge text color in active nav link
+$badge-active-color: $link-color !default;
+//** Badge background color in active nav link
+$badge-active-bg: #fff !default;
+
+$badge-font-weight: bold !default;
+$badge-line-height: 1 !default;
+$badge-border-radius: 10px !default;
+
+
+//== Breadcrumbs
+//
+//##
+
+$breadcrumb-padding-vertical: 8px !default;
+$breadcrumb-padding-horizontal: 15px !default;
+//** Breadcrumb background color
+$breadcrumb-bg: #f5f5f5 !default;
+//** Breadcrumb text color
+$breadcrumb-color: #ccc !default;
+//** Text color of current page in the breadcrumb
+$breadcrumb-active-color: $gray-light !default;
+//** Textual separator for between breadcrumb elements
+$breadcrumb-separator: "/" !default;
+
+
+//== Carousel
+//
+//##
+
+$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default;
+
+$carousel-control-color: #fff !default;
+$carousel-control-width: 15% !default;
+$carousel-control-opacity: .5 !default;
+$carousel-control-font-size: 20px !default;
+
+$carousel-indicator-active-bg: #fff !default;
+$carousel-indicator-border-color: #fff !default;
+
+$carousel-caption-color: #fff !default;
+
+
+//== Close
+//
+//##
+
+$close-font-weight: bold !default;
+$close-color: #000 !default;
+$close-text-shadow: 0 1px 0 #fff !default;
+
+
+//== Code
+//
+//##
+
+$code-color: #c7254e !default;
+$code-bg: #f9f2f4 !default;
+
+$kbd-color: #fff !default;
+$kbd-bg: #333 !default;
+
+$pre-bg: #f5f5f5 !default;
+$pre-color: $gray-dark !default;
+$pre-border-color: #ccc !default;
+$pre-scrollable-max-height: 340px !default;
+
+
+//== Type
+//
+//##
+
+//** Text muted color
+$text-muted: $gray-light !default;
+//** Abbreviations and acronyms border color
+$abbr-border-color: $gray-light !default;
+//** Headings small color
+$headings-small-color: $gray-light !default;
+//** Blockquote small color
+$blockquote-small-color: $gray-light !default;
+//** Blockquote font size
+$blockquote-font-size: ($font-size-base * 1.25) !default;
+//** Blockquote border color
+$blockquote-border-color: $gray-lighter !default;
+//** Page header border color
+$page-header-border-color: $gray-lighter !default;
+
+
+//== Miscellaneous
+//
+//##
+
+//** Horizontal line color.
+$hr-border: $gray-lighter !default;
+
+//** Horizontal offset for forms and lists.
+$component-offset-horizontal: 180px !default;
diff --git a/app/assets/stylesheets/bootstrap/_wells.scss b/app/assets/stylesheets/bootstrap/_wells.scss
new file mode 100644
index 0000000..b865711
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/_wells.scss
@@ -0,0 +1,29 @@
+//
+// Wells
+// --------------------------------------------------
+
+
+// Base class
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: $well-bg;
+ border: 1px solid $well-border;
+ border-radius: $border-radius-base;
+ @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
+ blockquote {
+ border-color: #ddd;
+ border-color: rgba(0,0,0,.15);
+ }
+}
+
+// Sizes
+.well-lg {
+ padding: 24px;
+ border-radius: $border-radius-large;
+}
+.well-sm {
+ padding: 9px;
+ border-radius: $border-radius-small;
+}
diff --git a/app/assets/stylesheets/bootstrap/bootstrap.scss b/app/assets/stylesheets/bootstrap/bootstrap.scss
new file mode 100644
index 0000000..cb5147d
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/bootstrap.scss
@@ -0,0 +1,49 @@
+// Core variables and mixins
+@import "variables";
+@import "mixins";
+
+// Reset
+@import "normalize";
+@import "print";
+
+// Core CSS
+@import "scaffolding";
+@import "type";
+@import "code";
+@import "grid";
+@import "tables";
+@import "forms";
+@import "buttons";
+
+// Components
+@import "component-animations";
+@import "glyphicons";
+@import "dropdowns";
+@import "button-groups";
+@import "input-groups";
+@import "navs";
+@import "navbar";
+@import "breadcrumbs";
+@import "pagination";
+@import "pager";
+@import "labels";
+@import "badges";
+@import "jumbotron";
+@import "thumbnails";
+@import "alerts";
+@import "progress-bars";
+@import "media";
+@import "list-group";
+@import "panels";
+@import "wells";
+@import "close";
+
+// Components w/ JavaScript
+@import "modals";
+@import "tooltip";
+@import "popovers";
+@import "carousel";
+
+// Utility classes
+@import "utilities";
+@import "responsive-utilities";
diff --git a/app/assets/stylesheets/bootstrap/slider.scss b/app/assets/stylesheets/bootstrap/slider.scss
new file mode 100755
index 0000000..8cbc16c
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/slider.scss
@@ -0,0 +1,138 @@
+/*!
+ * Slider for Bootstrap
+ *
+ * Copyright 2012 Stefan Petre
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+.slider {
+ display: inline-block;
+ vertical-align: middle;
+ position: relative;
+}
+.slider.slider-horizontal {
+ width: 210px;
+ height: 20px;
+}
+.slider.slider-horizontal .slider-track {
+ height: 10px;
+ width: 100%;
+ margin-top: -5px;
+ top: 50%;
+ left: 0;
+}
+.slider.slider-horizontal .slider-selection {
+ height: 100%;
+ top: 0;
+ bottom: 0;
+}
+.slider.slider-horizontal .slider-handle {
+ margin-left: -10px;
+ margin-top: -5px;
+}
+.slider.slider-horizontal .slider-handle.triangle {
+ border-width: 0 10px 10px 10px;
+ width: 0;
+ height: 0;
+ border-bottom-color: #0480be;
+ margin-top: 0;
+}
+.slider.slider-vertical {
+ height: 210px;
+ width: 20px;
+}
+.slider.slider-vertical .slider-track {
+ width: 10px;
+ height: 100%;
+ margin-left: -5px;
+ left: 50%;
+ top: 0;
+}
+.slider.slider-vertical .slider-selection {
+ width: 100%;
+ left: 0;
+ top: 0;
+ bottom: 0;
+}
+.slider.slider-vertical .slider-handle {
+ margin-left: -5px;
+ margin-top: -10px;
+}
+.slider.slider-vertical .slider-handle.triangle {
+ border-width: 10px 0 10px 10px;
+ width: 1px;
+ height: 1px;
+ border-left-color: #0480be;
+ margin-left: 0;
+}
+.slider input {
+ display: none;
+}
+.slider .tooltip-inner {
+ white-space: nowrap;
+}
+.slider-track {
+ position: absolute;
+ cursor: pointer;
+ background-color: #f7f7f7;
+ background-image: -moz-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(to bottom, #f5f5f5, #f9f9f9);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', 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);
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+.slider-selection {
+ position: absolute;
+ background-color: #f7f7f7;
+ background-image: -moz-linear-gradient(top, #f9f9f9, #f5f5f5);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f5f5f5));
+ background-image: -webkit-linear-gradient(top, #f9f9f9, #f5f5f5);
+ background-image: -o-linear-gradient(top, #f9f9f9, #f5f5f5);
+ background-image: linear-gradient(to bottom, #f9f9f9, #f5f5f5);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', 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;
+ box-sizing: border-box;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+.slider-handle {
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ 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(to bottom, #149bdf, #0480be);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+ -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+ opacity: 0.8;
+ border: 0px solid transparent;
+}
+.slider-handle.round {
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+}
+.slider-handle.triangle {
+ background: transparent none;
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/fontawesome/_bordered-pulled.scss b/app/assets/stylesheets/fontawesome/_bordered-pulled.scss
new file mode 100644
index 0000000..9d3fdf3
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_bordered-pulled.scss
@@ -0,0 +1,16 @@
+// Bordered & Pulled
+// -------------------------
+
+.#{$fa-css-prefix}-border {
+ padding: .2em .25em .15em;
+ border: solid .08em $fa-border-color;
+ border-radius: .1em;
+}
+
+.pull-right { float: right; }
+.pull-left { float: left; }
+
+.#{$fa-css-prefix} {
+ &.pull-left { margin-right: .3em; }
+ &.pull-right { margin-left: .3em; }
+}
diff --git a/app/assets/stylesheets/fontawesome/_core.scss b/app/assets/stylesheets/fontawesome/_core.scss
new file mode 100644
index 0000000..861ccd9
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_core.scss
@@ -0,0 +1,12 @@
+// Base Class Definition
+// -------------------------
+
+.#{$fa-css-prefix} {
+ display: inline-block;
+ font-family: FontAwesome;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
diff --git a/app/assets/stylesheets/fontawesome/_fixed-width.scss b/app/assets/stylesheets/fontawesome/_fixed-width.scss
new file mode 100644
index 0000000..b221c98
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_fixed-width.scss
@@ -0,0 +1,6 @@
+// Fixed Width Icons
+// -------------------------
+.#{$fa-css-prefix}-fw {
+ width: (18em / 14);
+ text-align: center;
+}
diff --git a/app/assets/stylesheets/fontawesome/_icons.scss b/app/assets/stylesheets/fontawesome/_icons.scss
new file mode 100644
index 0000000..7490cf3
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_icons.scss
@@ -0,0 +1,412 @@
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+ readers do not read off random characters that represent icons */
+
+.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
+.#{$fa-css-prefix}-music:before { content: $fa-var-music; }
+.#{$fa-css-prefix}-search:before { content: $fa-var-search; }
+.#{$fa-css-prefix}-envelope-o:before { content: $fa-var-envelope-o; }
+.#{$fa-css-prefix}-heart:before { content: $fa-var-heart; }
+.#{$fa-css-prefix}-star:before { content: $fa-var-star; }
+.#{$fa-css-prefix}-star-o:before { content: $fa-var-star-o; }
+.#{$fa-css-prefix}-user:before { content: $fa-var-user; }
+.#{$fa-css-prefix}-film:before { content: $fa-var-film; }
+.#{$fa-css-prefix}-th-large:before { content: $fa-var-th-large; }
+.#{$fa-css-prefix}-th:before { content: $fa-var-th; }
+.#{$fa-css-prefix}-th-list:before { content: $fa-var-th-list; }
+.#{$fa-css-prefix}-check:before { content: $fa-var-check; }
+.#{$fa-css-prefix}-times:before { content: $fa-var-times; }
+.#{$fa-css-prefix}-search-plus:before { content: $fa-var-search-plus; }
+.#{$fa-css-prefix}-search-minus:before { content: $fa-var-search-minus; }
+.#{$fa-css-prefix}-power-off:before { content: $fa-var-power-off; }
+.#{$fa-css-prefix}-signal:before { content: $fa-var-signal; }
+.#{$fa-css-prefix}-gear:before,
+.#{$fa-css-prefix}-cog:before { content: $fa-var-cog; }
+.#{$fa-css-prefix}-trash-o:before { content: $fa-var-trash-o; }
+.#{$fa-css-prefix}-home:before { content: $fa-var-home; }
+.#{$fa-css-prefix}-file-o:before { content: $fa-var-file-o; }
+.#{$fa-css-prefix}-clock-o:before { content: $fa-var-clock-o; }
+.#{$fa-css-prefix}-road:before { content: $fa-var-road; }
+.#{$fa-css-prefix}-download:before { content: $fa-var-download; }
+.#{$fa-css-prefix}-arrow-circle-o-down:before { content: $fa-var-arrow-circle-o-down; }
+.#{$fa-css-prefix}-arrow-circle-o-up:before { content: $fa-var-arrow-circle-o-up; }
+.#{$fa-css-prefix}-inbox:before { content: $fa-var-inbox; }
+.#{$fa-css-prefix}-play-circle-o:before { content: $fa-var-play-circle-o; }
+.#{$fa-css-prefix}-rotate-right:before,
+.#{$fa-css-prefix}-repeat:before { content: $fa-var-repeat; }
+.#{$fa-css-prefix}-refresh:before { content: $fa-var-refresh; }
+.#{$fa-css-prefix}-list-alt:before { content: $fa-var-list-alt; }
+.#{$fa-css-prefix}-lock:before { content: $fa-var-lock; }
+.#{$fa-css-prefix}-flag:before { content: $fa-var-flag; }
+.#{$fa-css-prefix}-headphones:before { content: $fa-var-headphones; }
+.#{$fa-css-prefix}-volume-off:before { content: $fa-var-volume-off; }
+.#{$fa-css-prefix}-volume-down:before { content: $fa-var-volume-down; }
+.#{$fa-css-prefix}-volume-up:before { content: $fa-var-volume-up; }
+.#{$fa-css-prefix}-qrcode:before { content: $fa-var-qrcode; }
+.#{$fa-css-prefix}-barcode:before { content: $fa-var-barcode; }
+.#{$fa-css-prefix}-tag:before { content: $fa-var-tag; }
+.#{$fa-css-prefix}-tags:before { content: $fa-var-tags; }
+.#{$fa-css-prefix}-book:before { content: $fa-var-book; }
+.#{$fa-css-prefix}-bookmark:before { content: $fa-var-bookmark; }
+.#{$fa-css-prefix}-print:before { content: $fa-var-print; }
+.#{$fa-css-prefix}-camera:before { content: $fa-var-camera; }
+.#{$fa-css-prefix}-font:before { content: $fa-var-font; }
+.#{$fa-css-prefix}-bold:before { content: $fa-var-bold; }
+.#{$fa-css-prefix}-italic:before { content: $fa-var-italic; }
+.#{$fa-css-prefix}-text-height:before { content: $fa-var-text-height; }
+.#{$fa-css-prefix}-text-width:before { content: $fa-var-text-width; }
+.#{$fa-css-prefix}-align-left:before { content: $fa-var-align-left; }
+.#{$fa-css-prefix}-align-center:before { content: $fa-var-align-center; }
+.#{$fa-css-prefix}-align-right:before { content: $fa-var-align-right; }
+.#{$fa-css-prefix}-align-justify:before { content: $fa-var-align-justify; }
+.#{$fa-css-prefix}-list:before { content: $fa-var-list; }
+.#{$fa-css-prefix}-dedent:before,
+.#{$fa-css-prefix}-outdent:before { content: $fa-var-outdent; }
+.#{$fa-css-prefix}-indent:before { content: $fa-var-indent; }
+.#{$fa-css-prefix}-video-camera:before { content: $fa-var-video-camera; }
+.#{$fa-css-prefix}-picture-o:before { content: $fa-var-picture-o; }
+.#{$fa-css-prefix}-pencil:before { content: $fa-var-pencil; }
+.#{$fa-css-prefix}-map-marker:before { content: $fa-var-map-marker; }
+.#{$fa-css-prefix}-adjust:before { content: $fa-var-adjust; }
+.#{$fa-css-prefix}-tint:before { content: $fa-var-tint; }
+.#{$fa-css-prefix}-edit:before,
+.#{$fa-css-prefix}-pencil-square-o:before { content: $fa-var-pencil-square-o; }
+.#{$fa-css-prefix}-share-square-o:before { content: $fa-var-share-square-o; }
+.#{$fa-css-prefix}-check-square-o:before { content: $fa-var-check-square-o; }
+.#{$fa-css-prefix}-arrows:before { content: $fa-var-arrows; }
+.#{$fa-css-prefix}-step-backward:before { content: $fa-var-step-backward; }
+.#{$fa-css-prefix}-fast-backward:before { content: $fa-var-fast-backward; }
+.#{$fa-css-prefix}-backward:before { content: $fa-var-backward; }
+.#{$fa-css-prefix}-play:before { content: $fa-var-play; }
+.#{$fa-css-prefix}-pause:before { content: $fa-var-pause; }
+.#{$fa-css-prefix}-stop:before { content: $fa-var-stop; }
+.#{$fa-css-prefix}-forward:before { content: $fa-var-forward; }
+.#{$fa-css-prefix}-fast-forward:before { content: $fa-var-fast-forward; }
+.#{$fa-css-prefix}-step-forward:before { content: $fa-var-step-forward; }
+.#{$fa-css-prefix}-eject:before { content: $fa-var-eject; }
+.#{$fa-css-prefix}-chevron-left:before { content: $fa-var-chevron-left; }
+.#{$fa-css-prefix}-chevron-right:before { content: $fa-var-chevron-right; }
+.#{$fa-css-prefix}-plus-circle:before { content: $fa-var-plus-circle; }
+.#{$fa-css-prefix}-minus-circle:before { content: $fa-var-minus-circle; }
+.#{$fa-css-prefix}-times-circle:before { content: $fa-var-times-circle; }
+.#{$fa-css-prefix}-check-circle:before { content: $fa-var-check-circle; }
+.#{$fa-css-prefix}-question-circle:before { content: $fa-var-question-circle; }
+.#{$fa-css-prefix}-info-circle:before { content: $fa-var-info-circle; }
+.#{$fa-css-prefix}-crosshairs:before { content: $fa-var-crosshairs; }
+.#{$fa-css-prefix}-times-circle-o:before { content: $fa-var-times-circle-o; }
+.#{$fa-css-prefix}-check-circle-o:before { content: $fa-var-check-circle-o; }
+.#{$fa-css-prefix}-ban:before { content: $fa-var-ban; }
+.#{$fa-css-prefix}-arrow-left:before { content: $fa-var-arrow-left; }
+.#{$fa-css-prefix}-arrow-right:before { content: $fa-var-arrow-right; }
+.#{$fa-css-prefix}-arrow-up:before { content: $fa-var-arrow-up; }
+.#{$fa-css-prefix}-arrow-down:before { content: $fa-var-arrow-down; }
+.#{$fa-css-prefix}-mail-forward:before,
+.#{$fa-css-prefix}-share:before { content: $fa-var-share; }
+.#{$fa-css-prefix}-expand:before { content: $fa-var-expand; }
+.#{$fa-css-prefix}-compress:before { content: $fa-var-compress; }
+.#{$fa-css-prefix}-plus:before { content: $fa-var-plus; }
+.#{$fa-css-prefix}-minus:before { content: $fa-var-minus; }
+.#{$fa-css-prefix}-asterisk:before { content: $fa-var-asterisk; }
+.#{$fa-css-prefix}-exclamation-circle:before { content: $fa-var-exclamation-circle; }
+.#{$fa-css-prefix}-gift:before { content: $fa-var-gift; }
+.#{$fa-css-prefix}-leaf:before { content: $fa-var-leaf; }
+.#{$fa-css-prefix}-fire:before { content: $fa-var-fire; }
+.#{$fa-css-prefix}-eye:before { content: $fa-var-eye; }
+.#{$fa-css-prefix}-eye-slash:before { content: $fa-var-eye-slash; }
+.#{$fa-css-prefix}-warning:before,
+.#{$fa-css-prefix}-exclamation-triangle:before { content: $fa-var-exclamation-triangle; }
+.#{$fa-css-prefix}-plane:before { content: $fa-var-plane; }
+.#{$fa-css-prefix}-calendar:before { content: $fa-var-calendar; }
+.#{$fa-css-prefix}-random:before { content: $fa-var-random; }
+.#{$fa-css-prefix}-comment:before { content: $fa-var-comment; }
+.#{$fa-css-prefix}-magnet:before { content: $fa-var-magnet; }
+.#{$fa-css-prefix}-chevron-up:before { content: $fa-var-chevron-up; }
+.#{$fa-css-prefix}-chevron-down:before { content: $fa-var-chevron-down; }
+.#{$fa-css-prefix}-retweet:before { content: $fa-var-retweet; }
+.#{$fa-css-prefix}-shopping-cart:before { content: $fa-var-shopping-cart; }
+.#{$fa-css-prefix}-folder:before { content: $fa-var-folder; }
+.#{$fa-css-prefix}-folder-open:before { content: $fa-var-folder-open; }
+.#{$fa-css-prefix}-arrows-v:before { content: $fa-var-arrows-v; }
+.#{$fa-css-prefix}-arrows-h:before { content: $fa-var-arrows-h; }
+.#{$fa-css-prefix}-bar-chart-o:before { content: $fa-var-bar-chart-o; }
+.#{$fa-css-prefix}-twitter-square:before { content: $fa-var-twitter-square; }
+.#{$fa-css-prefix}-facebook-square:before { content: $fa-var-facebook-square; }
+.#{$fa-css-prefix}-camera-retro:before { content: $fa-var-camera-retro; }
+.#{$fa-css-prefix}-key:before { content: $fa-var-key; }
+.#{$fa-css-prefix}-gears:before,
+.#{$fa-css-prefix}-cogs:before { content: $fa-var-cogs; }
+.#{$fa-css-prefix}-comments:before { content: $fa-var-comments; }
+.#{$fa-css-prefix}-thumbs-o-up:before { content: $fa-var-thumbs-o-up; }
+.#{$fa-css-prefix}-thumbs-o-down:before { content: $fa-var-thumbs-o-down; }
+.#{$fa-css-prefix}-star-half:before { content: $fa-var-star-half; }
+.#{$fa-css-prefix}-heart-o:before { content: $fa-var-heart-o; }
+.#{$fa-css-prefix}-sign-out:before { content: $fa-var-sign-out; }
+.#{$fa-css-prefix}-linkedin-square:before { content: $fa-var-linkedin-square; }
+.#{$fa-css-prefix}-thumb-tack:before { content: $fa-var-thumb-tack; }
+.#{$fa-css-prefix}-external-link:before { content: $fa-var-external-link; }
+.#{$fa-css-prefix}-sign-in:before { content: $fa-var-sign-in; }
+.#{$fa-css-prefix}-trophy:before { content: $fa-var-trophy; }
+.#{$fa-css-prefix}-github-square:before { content: $fa-var-github-square; }
+.#{$fa-css-prefix}-upload:before { content: $fa-var-upload; }
+.#{$fa-css-prefix}-lemon-o:before { content: $fa-var-lemon-o; }
+.#{$fa-css-prefix}-phone:before { content: $fa-var-phone; }
+.#{$fa-css-prefix}-square-o:before { content: $fa-var-square-o; }
+.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; }
+.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; }
+.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; }
+.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; }
+.#{$fa-css-prefix}-github:before { content: $fa-var-github; }
+.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; }
+.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; }
+.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; }
+.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; }
+.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; }
+.#{$fa-css-prefix}-bell:before { content: $fa-var-bell; }
+.#{$fa-css-prefix}-certificate:before { content: $fa-var-certificate; }
+.#{$fa-css-prefix}-hand-o-right:before { content: $fa-var-hand-o-right; }
+.#{$fa-css-prefix}-hand-o-left:before { content: $fa-var-hand-o-left; }
+.#{$fa-css-prefix}-hand-o-up:before { content: $fa-var-hand-o-up; }
+.#{$fa-css-prefix}-hand-o-down:before { content: $fa-var-hand-o-down; }
+.#{$fa-css-prefix}-arrow-circle-left:before { content: $fa-var-arrow-circle-left; }
+.#{$fa-css-prefix}-arrow-circle-right:before { content: $fa-var-arrow-circle-right; }
+.#{$fa-css-prefix}-arrow-circle-up:before { content: $fa-var-arrow-circle-up; }
+.#{$fa-css-prefix}-arrow-circle-down:before { content: $fa-var-arrow-circle-down; }
+.#{$fa-css-prefix}-globe:before { content: $fa-var-globe; }
+.#{$fa-css-prefix}-wrench:before { content: $fa-var-wrench; }
+.#{$fa-css-prefix}-tasks:before { content: $fa-var-tasks; }
+.#{$fa-css-prefix}-filter:before { content: $fa-var-filter; }
+.#{$fa-css-prefix}-briefcase:before { content: $fa-var-briefcase; }
+.#{$fa-css-prefix}-arrows-alt:before { content: $fa-var-arrows-alt; }
+.#{$fa-css-prefix}-group:before,
+.#{$fa-css-prefix}-users:before { content: $fa-var-users; }
+.#{$fa-css-prefix}-chain:before,
+.#{$fa-css-prefix}-link:before { content: $fa-var-link; }
+.#{$fa-css-prefix}-cloud:before { content: $fa-var-cloud; }
+.#{$fa-css-prefix}-flask:before { content: $fa-var-flask; }
+.#{$fa-css-prefix}-cut:before,
+.#{$fa-css-prefix}-scissors:before { content: $fa-var-scissors; }
+.#{$fa-css-prefix}-copy:before,
+.#{$fa-css-prefix}-files-o:before { content: $fa-var-files-o; }
+.#{$fa-css-prefix}-paperclip:before { content: $fa-var-paperclip; }
+.#{$fa-css-prefix}-save:before,
+.#{$fa-css-prefix}-floppy-o:before { content: $fa-var-floppy-o; }
+.#{$fa-css-prefix}-square:before { content: $fa-var-square; }
+.#{$fa-css-prefix}-bars:before { content: $fa-var-bars; }
+.#{$fa-css-prefix}-list-ul:before { content: $fa-var-list-ul; }
+.#{$fa-css-prefix}-list-ol:before { content: $fa-var-list-ol; }
+.#{$fa-css-prefix}-strikethrough:before { content: $fa-var-strikethrough; }
+.#{$fa-css-prefix}-underline:before { content: $fa-var-underline; }
+.#{$fa-css-prefix}-table:before { content: $fa-var-table; }
+.#{$fa-css-prefix}-magic:before { content: $fa-var-magic; }
+.#{$fa-css-prefix}-truck:before { content: $fa-var-truck; }
+.#{$fa-css-prefix}-pinterest:before { content: $fa-var-pinterest; }
+.#{$fa-css-prefix}-pinterest-square:before { content: $fa-var-pinterest-square; }
+.#{$fa-css-prefix}-google-plus-square:before { content: $fa-var-google-plus-square; }
+.#{$fa-css-prefix}-google-plus:before { content: $fa-var-google-plus; }
+.#{$fa-css-prefix}-money:before { content: $fa-var-money; }
+.#{$fa-css-prefix}-caret-down:before { content: $fa-var-caret-down; }
+.#{$fa-css-prefix}-caret-up:before { content: $fa-var-caret-up; }
+.#{$fa-css-prefix}-caret-left:before { content: $fa-var-caret-left; }
+.#{$fa-css-prefix}-caret-right:before { content: $fa-var-caret-right; }
+.#{$fa-css-prefix}-columns:before { content: $fa-var-columns; }
+.#{$fa-css-prefix}-unsorted:before,
+.#{$fa-css-prefix}-sort:before { content: $fa-var-sort; }
+.#{$fa-css-prefix}-sort-down:before,
+.#{$fa-css-prefix}-sort-asc:before { content: $fa-var-sort-asc; }
+.#{$fa-css-prefix}-sort-up:before,
+.#{$fa-css-prefix}-sort-desc:before { content: $fa-var-sort-desc; }
+.#{$fa-css-prefix}-envelope:before { content: $fa-var-envelope; }
+.#{$fa-css-prefix}-linkedin:before { content: $fa-var-linkedin; }
+.#{$fa-css-prefix}-rotate-left:before,
+.#{$fa-css-prefix}-undo:before { content: $fa-var-undo; }
+.#{$fa-css-prefix}-legal:before,
+.#{$fa-css-prefix}-gavel:before { content: $fa-var-gavel; }
+.#{$fa-css-prefix}-dashboard:before,
+.#{$fa-css-prefix}-tachometer:before { content: $fa-var-tachometer; }
+.#{$fa-css-prefix}-comment-o:before { content: $fa-var-comment-o; }
+.#{$fa-css-prefix}-comments-o:before { content: $fa-var-comments-o; }
+.#{$fa-css-prefix}-flash:before,
+.#{$fa-css-prefix}-bolt:before { content: $fa-var-bolt; }
+.#{$fa-css-prefix}-sitemap:before { content: $fa-var-sitemap; }
+.#{$fa-css-prefix}-umbrella:before { content: $fa-var-umbrella; }
+.#{$fa-css-prefix}-paste:before,
+.#{$fa-css-prefix}-clipboard:before { content: $fa-var-clipboard; }
+.#{$fa-css-prefix}-lightbulb-o:before { content: $fa-var-lightbulb-o; }
+.#{$fa-css-prefix}-exchange:before { content: $fa-var-exchange; }
+.#{$fa-css-prefix}-cloud-download:before { content: $fa-var-cloud-download; }
+.#{$fa-css-prefix}-cloud-upload:before { content: $fa-var-cloud-upload; }
+.#{$fa-css-prefix}-user-md:before { content: $fa-var-user-md; }
+.#{$fa-css-prefix}-stethoscope:before { content: $fa-var-stethoscope; }
+.#{$fa-css-prefix}-suitcase:before { content: $fa-var-suitcase; }
+.#{$fa-css-prefix}-bell-o:before { content: $fa-var-bell-o; }
+.#{$fa-css-prefix}-coffee:before { content: $fa-var-coffee; }
+.#{$fa-css-prefix}-cutlery:before { content: $fa-var-cutlery; }
+.#{$fa-css-prefix}-file-text-o:before { content: $fa-var-file-text-o; }
+.#{$fa-css-prefix}-building-o:before { content: $fa-var-building-o; }
+.#{$fa-css-prefix}-hospital-o:before { content: $fa-var-hospital-o; }
+.#{$fa-css-prefix}-ambulance:before { content: $fa-var-ambulance; }
+.#{$fa-css-prefix}-medkit:before { content: $fa-var-medkit; }
+.#{$fa-css-prefix}-fighter-jet:before { content: $fa-var-fighter-jet; }
+.#{$fa-css-prefix}-beer:before { content: $fa-var-beer; }
+.#{$fa-css-prefix}-h-square:before { content: $fa-var-h-square; }
+.#{$fa-css-prefix}-plus-square:before { content: $fa-var-plus-square; }
+.#{$fa-css-prefix}-angle-double-left:before { content: $fa-var-angle-double-left; }
+.#{$fa-css-prefix}-angle-double-right:before { content: $fa-var-angle-double-right; }
+.#{$fa-css-prefix}-angle-double-up:before { content: $fa-var-angle-double-up; }
+.#{$fa-css-prefix}-angle-double-down:before { content: $fa-var-angle-double-down; }
+.#{$fa-css-prefix}-angle-left:before { content: $fa-var-angle-left; }
+.#{$fa-css-prefix}-angle-right:before { content: $fa-var-angle-right; }
+.#{$fa-css-prefix}-angle-up:before { content: $fa-var-angle-up; }
+.#{$fa-css-prefix}-angle-down:before { content: $fa-var-angle-down; }
+.#{$fa-css-prefix}-desktop:before { content: $fa-var-desktop; }
+.#{$fa-css-prefix}-laptop:before { content: $fa-var-laptop; }
+.#{$fa-css-prefix}-tablet:before { content: $fa-var-tablet; }
+.#{$fa-css-prefix}-mobile-phone:before,
+.#{$fa-css-prefix}-mobile:before { content: $fa-var-mobile; }
+.#{$fa-css-prefix}-circle-o:before { content: $fa-var-circle-o; }
+.#{$fa-css-prefix}-quote-left:before { content: $fa-var-quote-left; }
+.#{$fa-css-prefix}-quote-right:before { content: $fa-var-quote-right; }
+.#{$fa-css-prefix}-spinner:before { content: $fa-var-spinner; }
+.#{$fa-css-prefix}-circle:before { content: $fa-var-circle; }
+.#{$fa-css-prefix}-mail-reply:before,
+.#{$fa-css-prefix}-reply:before { content: $fa-var-reply; }
+.#{$fa-css-prefix}-github-alt:before { content: $fa-var-github-alt; }
+.#{$fa-css-prefix}-folder-o:before { content: $fa-var-folder-o; }
+.#{$fa-css-prefix}-folder-open-o:before { content: $fa-var-folder-open-o; }
+.#{$fa-css-prefix}-smile-o:before { content: $fa-var-smile-o; }
+.#{$fa-css-prefix}-frown-o:before { content: $fa-var-frown-o; }
+.#{$fa-css-prefix}-meh-o:before { content: $fa-var-meh-o; }
+.#{$fa-css-prefix}-gamepad:before { content: $fa-var-gamepad; }
+.#{$fa-css-prefix}-keyboard-o:before { content: $fa-var-keyboard-o; }
+.#{$fa-css-prefix}-flag-o:before { content: $fa-var-flag-o; }
+.#{$fa-css-prefix}-flag-checkered:before { content: $fa-var-flag-checkered; }
+.#{$fa-css-prefix}-terminal:before { content: $fa-var-terminal; }
+.#{$fa-css-prefix}-code:before { content: $fa-var-code; }
+.#{$fa-css-prefix}-reply-all:before { content: $fa-var-reply-all; }
+.#{$fa-css-prefix}-mail-reply-all:before { content: $fa-var-mail-reply-all; }
+.#{$fa-css-prefix}-star-half-empty:before,
+.#{$fa-css-prefix}-star-half-full:before,
+.#{$fa-css-prefix}-star-half-o:before { content: $fa-var-star-half-o; }
+.#{$fa-css-prefix}-location-arrow:before { content: $fa-var-location-arrow; }
+.#{$fa-css-prefix}-crop:before { content: $fa-var-crop; }
+.#{$fa-css-prefix}-code-fork:before { content: $fa-var-code-fork; }
+.#{$fa-css-prefix}-unlink:before,
+.#{$fa-css-prefix}-chain-broken:before { content: $fa-var-chain-broken; }
+.#{$fa-css-prefix}-question:before { content: $fa-var-question; }
+.#{$fa-css-prefix}-info:before { content: $fa-var-info; }
+.#{$fa-css-prefix}-exclamation:before { content: $fa-var-exclamation; }
+.#{$fa-css-prefix}-superscript:before { content: $fa-var-superscript; }
+.#{$fa-css-prefix}-subscript:before { content: $fa-var-subscript; }
+.#{$fa-css-prefix}-eraser:before { content: $fa-var-eraser; }
+.#{$fa-css-prefix}-puzzle-piece:before { content: $fa-var-puzzle-piece; }
+.#{$fa-css-prefix}-microphone:before { content: $fa-var-microphone; }
+.#{$fa-css-prefix}-microphone-slash:before { content: $fa-var-microphone-slash; }
+.#{$fa-css-prefix}-shield:before { content: $fa-var-shield; }
+.#{$fa-css-prefix}-calendar-o:before { content: $fa-var-calendar-o; }
+.#{$fa-css-prefix}-fire-extinguisher:before { content: $fa-var-fire-extinguisher; }
+.#{$fa-css-prefix}-rocket:before { content: $fa-var-rocket; }
+.#{$fa-css-prefix}-maxcdn:before { content: $fa-var-maxcdn; }
+.#{$fa-css-prefix}-chevron-circle-left:before { content: $fa-var-chevron-circle-left; }
+.#{$fa-css-prefix}-chevron-circle-right:before { content: $fa-var-chevron-circle-right; }
+.#{$fa-css-prefix}-chevron-circle-up:before { content: $fa-var-chevron-circle-up; }
+.#{$fa-css-prefix}-chevron-circle-down:before { content: $fa-var-chevron-circle-down; }
+.#{$fa-css-prefix}-html5:before { content: $fa-var-html5; }
+.#{$fa-css-prefix}-css3:before { content: $fa-var-css3; }
+.#{$fa-css-prefix}-anchor:before { content: $fa-var-anchor; }
+.#{$fa-css-prefix}-unlock-alt:before { content: $fa-var-unlock-alt; }
+.#{$fa-css-prefix}-bullseye:before { content: $fa-var-bullseye; }
+.#{$fa-css-prefix}-ellipsis-h:before { content: $fa-var-ellipsis-h; }
+.#{$fa-css-prefix}-ellipsis-v:before { content: $fa-var-ellipsis-v; }
+.#{$fa-css-prefix}-rss-square:before { content: $fa-var-rss-square; }
+.#{$fa-css-prefix}-play-circle:before { content: $fa-var-play-circle; }
+.#{$fa-css-prefix}-ticket:before { content: $fa-var-ticket; }
+.#{$fa-css-prefix}-minus-square:before { content: $fa-var-minus-square; }
+.#{$fa-css-prefix}-minus-square-o:before { content: $fa-var-minus-square-o; }
+.#{$fa-css-prefix}-level-up:before { content: $fa-var-level-up; }
+.#{$fa-css-prefix}-level-down:before { content: $fa-var-level-down; }
+.#{$fa-css-prefix}-check-square:before { content: $fa-var-check-square; }
+.#{$fa-css-prefix}-pencil-square:before { content: $fa-var-pencil-square; }
+.#{$fa-css-prefix}-external-link-square:before { content: $fa-var-external-link-square; }
+.#{$fa-css-prefix}-share-square:before { content: $fa-var-share-square; }
+.#{$fa-css-prefix}-compass:before { content: $fa-var-compass; }
+.#{$fa-css-prefix}-toggle-down:before,
+.#{$fa-css-prefix}-caret-square-o-down:before { content: $fa-var-caret-square-o-down; }
+.#{$fa-css-prefix}-toggle-up:before,
+.#{$fa-css-prefix}-caret-square-o-up:before { content: $fa-var-caret-square-o-up; }
+.#{$fa-css-prefix}-toggle-right:before,
+.#{$fa-css-prefix}-caret-square-o-right:before { content: $fa-var-caret-square-o-right; }
+.#{$fa-css-prefix}-euro:before,
+.#{$fa-css-prefix}-eur:before { content: $fa-var-eur; }
+.#{$fa-css-prefix}-gbp:before { content: $fa-var-gbp; }
+.#{$fa-css-prefix}-dollar:before,
+.#{$fa-css-prefix}-usd:before { content: $fa-var-usd; }
+.#{$fa-css-prefix}-rupee:before,
+.#{$fa-css-prefix}-inr:before { content: $fa-var-inr; }
+.#{$fa-css-prefix}-cny:before,
+.#{$fa-css-prefix}-rmb:before,
+.#{$fa-css-prefix}-yen:before,
+.#{$fa-css-prefix}-jpy:before { content: $fa-var-jpy; }
+.#{$fa-css-prefix}-ruble:before,
+.#{$fa-css-prefix}-rouble:before,
+.#{$fa-css-prefix}-rub:before { content: $fa-var-rub; }
+.#{$fa-css-prefix}-won:before,
+.#{$fa-css-prefix}-krw:before { content: $fa-var-krw; }
+.#{$fa-css-prefix}-bitcoin:before,
+.#{$fa-css-prefix}-btc:before { content: $fa-var-btc; }
+.#{$fa-css-prefix}-file:before { content: $fa-var-file; }
+.#{$fa-css-prefix}-file-text:before { content: $fa-var-file-text; }
+.#{$fa-css-prefix}-sort-alpha-asc:before { content: $fa-var-sort-alpha-asc; }
+.#{$fa-css-prefix}-sort-alpha-desc:before { content: $fa-var-sort-alpha-desc; }
+.#{$fa-css-prefix}-sort-amount-asc:before { content: $fa-var-sort-amount-asc; }
+.#{$fa-css-prefix}-sort-amount-desc:before { content: $fa-var-sort-amount-desc; }
+.#{$fa-css-prefix}-sort-numeric-asc:before { content: $fa-var-sort-numeric-asc; }
+.#{$fa-css-prefix}-sort-numeric-desc:before { content: $fa-var-sort-numeric-desc; }
+.#{$fa-css-prefix}-thumbs-up:before { content: $fa-var-thumbs-up; }
+.#{$fa-css-prefix}-thumbs-down:before { content: $fa-var-thumbs-down; }
+.#{$fa-css-prefix}-youtube-square:before { content: $fa-var-youtube-square; }
+.#{$fa-css-prefix}-youtube:before { content: $fa-var-youtube; }
+.#{$fa-css-prefix}-xing:before { content: $fa-var-xing; }
+.#{$fa-css-prefix}-xing-square:before { content: $fa-var-xing-square; }
+.#{$fa-css-prefix}-youtube-play:before { content: $fa-var-youtube-play; }
+.#{$fa-css-prefix}-dropbox:before { content: $fa-var-dropbox; }
+.#{$fa-css-prefix}-stack-overflow:before { content: $fa-var-stack-overflow; }
+.#{$fa-css-prefix}-instagram:before { content: $fa-var-instagram; }
+.#{$fa-css-prefix}-flickr:before { content: $fa-var-flickr; }
+.#{$fa-css-prefix}-adn:before { content: $fa-var-adn; }
+.#{$fa-css-prefix}-bitbucket:before { content: $fa-var-bitbucket; }
+.#{$fa-css-prefix}-bitbucket-square:before { content: $fa-var-bitbucket-square; }
+.#{$fa-css-prefix}-tumblr:before { content: $fa-var-tumblr; }
+.#{$fa-css-prefix}-tumblr-square:before { content: $fa-var-tumblr-square; }
+.#{$fa-css-prefix}-long-arrow-down:before { content: $fa-var-long-arrow-down; }
+.#{$fa-css-prefix}-long-arrow-up:before { content: $fa-var-long-arrow-up; }
+.#{$fa-css-prefix}-long-arrow-left:before { content: $fa-var-long-arrow-left; }
+.#{$fa-css-prefix}-long-arrow-right:before { content: $fa-var-long-arrow-right; }
+.#{$fa-css-prefix}-apple:before { content: $fa-var-apple; }
+.#{$fa-css-prefix}-windows:before { content: $fa-var-windows; }
+.#{$fa-css-prefix}-android:before { content: $fa-var-android; }
+.#{$fa-css-prefix}-linux:before { content: $fa-var-linux; }
+.#{$fa-css-prefix}-dribbble:before { content: $fa-var-dribbble; }
+.#{$fa-css-prefix}-skype:before { content: $fa-var-skype; }
+.#{$fa-css-prefix}-foursquare:before { content: $fa-var-foursquare; }
+.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; }
+.#{$fa-css-prefix}-female:before { content: $fa-var-female; }
+.#{$fa-css-prefix}-male:before { content: $fa-var-male; }
+.#{$fa-css-prefix}-gittip:before { content: $fa-var-gittip; }
+.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; }
+.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; }
+.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; }
+.#{$fa-css-prefix}-bug:before { content: $fa-var-bug; }
+.#{$fa-css-prefix}-vk:before { content: $fa-var-vk; }
+.#{$fa-css-prefix}-weibo:before { content: $fa-var-weibo; }
+.#{$fa-css-prefix}-renren:before { content: $fa-var-renren; }
+.#{$fa-css-prefix}-pagelines:before { content: $fa-var-pagelines; }
+.#{$fa-css-prefix}-stack-exchange:before { content: $fa-var-stack-exchange; }
+.#{$fa-css-prefix}-arrow-circle-o-right:before { content: $fa-var-arrow-circle-o-right; }
+.#{$fa-css-prefix}-arrow-circle-o-left:before { content: $fa-var-arrow-circle-o-left; }
+.#{$fa-css-prefix}-toggle-left:before,
+.#{$fa-css-prefix}-caret-square-o-left:before { content: $fa-var-caret-square-o-left; }
+.#{$fa-css-prefix}-dot-circle-o:before { content: $fa-var-dot-circle-o; }
+.#{$fa-css-prefix}-wheelchair:before { content: $fa-var-wheelchair; }
+.#{$fa-css-prefix}-vimeo-square:before { content: $fa-var-vimeo-square; }
+.#{$fa-css-prefix}-turkish-lira:before,
+.#{$fa-css-prefix}-try:before { content: $fa-var-try; }
+.#{$fa-css-prefix}-plus-square-o:before { content: $fa-var-plus-square-o; }
diff --git a/app/assets/stylesheets/fontawesome/_larger.scss b/app/assets/stylesheets/fontawesome/_larger.scss
new file mode 100644
index 0000000..41e9a81
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_larger.scss
@@ -0,0 +1,13 @@
+// Icon Sizes
+// -------------------------
+
+/* makes the font 33% larger relative to the icon container */
+.#{$fa-css-prefix}-lg {
+ font-size: (4em / 3);
+ line-height: (3em / 4);
+ vertical-align: -15%;
+}
+.#{$fa-css-prefix}-2x { font-size: 2em; }
+.#{$fa-css-prefix}-3x { font-size: 3em; }
+.#{$fa-css-prefix}-4x { font-size: 4em; }
+.#{$fa-css-prefix}-5x { font-size: 5em; }
diff --git a/app/assets/stylesheets/fontawesome/_list.scss b/app/assets/stylesheets/fontawesome/_list.scss
new file mode 100644
index 0000000..7d1e4d5
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_list.scss
@@ -0,0 +1,19 @@
+// List Icons
+// -------------------------
+
+.#{$fa-css-prefix}-ul {
+ padding-left: 0;
+ margin-left: $fa-li-width;
+ list-style-type: none;
+ > li { position: relative; }
+}
+.#{$fa-css-prefix}-li {
+ position: absolute;
+ left: -$fa-li-width;
+ width: $fa-li-width;
+ top: (2em / 14);
+ text-align: center;
+ &.#{$fa-css-prefix}-lg {
+ left: -$fa-li-width + (4em / 14);
+ }
+}
diff --git a/app/assets/stylesheets/fontawesome/_mixins.scss b/app/assets/stylesheets/fontawesome/_mixins.scss
new file mode 100644
index 0000000..9f55596
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_mixins.scss
@@ -0,0 +1,20 @@
+// Mixins
+// --------------------------
+
+@mixin fa-icon-rotate($degrees, $rotation) {
+ filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);
+ -webkit-transform: rotate($degrees);
+ -moz-transform: rotate($degrees);
+ -ms-transform: rotate($degrees);
+ -o-transform: rotate($degrees);
+ transform: rotate($degrees);
+}
+
+@mixin fa-icon-flip($horiz, $vert, $rotation) {
+ filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);
+ -webkit-transform: scale($horiz, $vert);
+ -moz-transform: scale($horiz, $vert);
+ -ms-transform: scale($horiz, $vert);
+ -o-transform: scale($horiz, $vert);
+ transform: scale($horiz, $vert);
+}
diff --git a/app/assets/stylesheets/fontawesome/_path.scss b/app/assets/stylesheets/fontawesome/_path.scss
new file mode 100644
index 0000000..fd21c35
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_path.scss
@@ -0,0 +1,14 @@
+/* FONT PATH
+ * -------------------------- */
+
+@font-face {
+ font-family: 'FontAwesome';
+ src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
+ src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
+ url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
+ url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
+ url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
+ //src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
+ font-weight: normal;
+ font-style: normal;
+}
diff --git a/app/assets/stylesheets/fontawesome/_rotated-flipped.scss b/app/assets/stylesheets/fontawesome/_rotated-flipped.scss
new file mode 100644
index 0000000..343fa55
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_rotated-flipped.scss
@@ -0,0 +1,9 @@
+// Rotated & Flipped Icons
+// -------------------------
+
+.#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
+.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
+.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
+
+.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
+.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
diff --git a/app/assets/stylesheets/fontawesome/_spinning.scss b/app/assets/stylesheets/fontawesome/_spinning.scss
new file mode 100644
index 0000000..ba1e4f1
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_spinning.scss
@@ -0,0 +1,30 @@
+// Spinning Icons
+// --------------------------
+
+.#{$fa-css-prefix}-spin {
+ -webkit-animation: spin 2s infinite linear;
+ -moz-animation: spin 2s infinite linear;
+ -o-animation: spin 2s infinite linear;
+ animation: spin 2s infinite linear;
+}
+
+@-moz-keyframes spin {
+ 0% { -moz-transform: rotate(0deg); }
+ 100% { -moz-transform: rotate(359deg); }
+}
+@-webkit-keyframes spin {
+ 0% { -webkit-transform: rotate(0deg); }
+ 100% { -webkit-transform: rotate(359deg); }
+}
+@-o-keyframes spin {
+ 0% { -o-transform: rotate(0deg); }
+ 100% { -o-transform: rotate(359deg); }
+}
+@-ms-keyframes spin {
+ 0% { -ms-transform: rotate(0deg); }
+ 100% { -ms-transform: rotate(359deg); }
+}
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(359deg); }
+}
diff --git a/app/assets/stylesheets/fontawesome/_stacked.scss b/app/assets/stylesheets/fontawesome/_stacked.scss
new file mode 100644
index 0000000..aef7403
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_stacked.scss
@@ -0,0 +1,20 @@
+// Stacked Icons
+// -------------------------
+
+.#{$fa-css-prefix}-stack {
+ position: relative;
+ display: inline-block;
+ width: 2em;
+ height: 2em;
+ line-height: 2em;
+ vertical-align: middle;
+}
+.#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x {
+ position: absolute;
+ left: 0;
+ width: 100%;
+ text-align: center;
+}
+.#{$fa-css-prefix}-stack-1x { line-height: inherit; }
+.#{$fa-css-prefix}-stack-2x { font-size: 2em; }
+.#{$fa-css-prefix}-inverse { color: $fa-inverse; }
diff --git a/app/assets/stylesheets/fontawesome/_variables.scss b/app/assets/stylesheets/fontawesome/_variables.scss
new file mode 100644
index 0000000..efa24b9
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/_variables.scss
@@ -0,0 +1,381 @@
+// Variables
+// --------------------------
+
+$fa-font-path: "/fonts" !default;
+//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts" !default; // for referencing Bootstrap CDN font files directly
+$fa-css-prefix: fa !default;
+$fa-version: "4.0.3" !default;
+$fa-border-color: #eee !default;
+$fa-inverse: #fff !default;
+$fa-li-width: (30em / 14) !default;
+
+$fa-var-glass: "\f000";
+$fa-var-music: "\f001";
+$fa-var-search: "\f002";
+$fa-var-envelope-o: "\f003";
+$fa-var-heart: "\f004";
+$fa-var-star: "\f005";
+$fa-var-star-o: "\f006";
+$fa-var-user: "\f007";
+$fa-var-film: "\f008";
+$fa-var-th-large: "\f009";
+$fa-var-th: "\f00a";
+$fa-var-th-list: "\f00b";
+$fa-var-check: "\f00c";
+$fa-var-times: "\f00d";
+$fa-var-search-plus: "\f00e";
+$fa-var-search-minus: "\f010";
+$fa-var-power-off: "\f011";
+$fa-var-signal: "\f012";
+$fa-var-cog: "\f013";
+$fa-var-trash-o: "\f014";
+$fa-var-home: "\f015";
+$fa-var-file-o: "\f016";
+$fa-var-clock-o: "\f017";
+$fa-var-road: "\f018";
+$fa-var-download: "\f019";
+$fa-var-arrow-circle-o-down: "\f01a";
+$fa-var-arrow-circle-o-up: "\f01b";
+$fa-var-inbox: "\f01c";
+$fa-var-play-circle-o: "\f01d";
+$fa-var-repeat: "\f01e";
+$fa-var-refresh: "\f021";
+$fa-var-list-alt: "\f022";
+$fa-var-lock: "\f023";
+$fa-var-flag: "\f024";
+$fa-var-headphones: "\f025";
+$fa-var-volume-off: "\f026";
+$fa-var-volume-down: "\f027";
+$fa-var-volume-up: "\f028";
+$fa-var-qrcode: "\f029";
+$fa-var-barcode: "\f02a";
+$fa-var-tag: "\f02b";
+$fa-var-tags: "\f02c";
+$fa-var-book: "\f02d";
+$fa-var-bookmark: "\f02e";
+$fa-var-print: "\f02f";
+$fa-var-camera: "\f030";
+$fa-var-font: "\f031";
+$fa-var-bold: "\f032";
+$fa-var-italic: "\f033";
+$fa-var-text-height: "\f034";
+$fa-var-text-width: "\f035";
+$fa-var-align-left: "\f036";
+$fa-var-align-center: "\f037";
+$fa-var-align-right: "\f038";
+$fa-var-align-justify: "\f039";
+$fa-var-list: "\f03a";
+$fa-var-outdent: "\f03b";
+$fa-var-indent: "\f03c";
+$fa-var-video-camera: "\f03d";
+$fa-var-picture-o: "\f03e";
+$fa-var-pencil: "\f040";
+$fa-var-map-marker: "\f041";
+$fa-var-adjust: "\f042";
+$fa-var-tint: "\f043";
+$fa-var-pencil-square-o: "\f044";
+$fa-var-share-square-o: "\f045";
+$fa-var-check-square-o: "\f046";
+$fa-var-arrows: "\f047";
+$fa-var-step-backward: "\f048";
+$fa-var-fast-backward: "\f049";
+$fa-var-backward: "\f04a";
+$fa-var-play: "\f04b";
+$fa-var-pause: "\f04c";
+$fa-var-stop: "\f04d";
+$fa-var-forward: "\f04e";
+$fa-var-fast-forward: "\f050";
+$fa-var-step-forward: "\f051";
+$fa-var-eject: "\f052";
+$fa-var-chevron-left: "\f053";
+$fa-var-chevron-right: "\f054";
+$fa-var-plus-circle: "\f055";
+$fa-var-minus-circle: "\f056";
+$fa-var-times-circle: "\f057";
+$fa-var-check-circle: "\f058";
+$fa-var-question-circle: "\f059";
+$fa-var-info-circle: "\f05a";
+$fa-var-crosshairs: "\f05b";
+$fa-var-times-circle-o: "\f05c";
+$fa-var-check-circle-o: "\f05d";
+$fa-var-ban: "\f05e";
+$fa-var-arrow-left: "\f060";
+$fa-var-arrow-right: "\f061";
+$fa-var-arrow-up: "\f062";
+$fa-var-arrow-down: "\f063";
+$fa-var-share: "\f064";
+$fa-var-expand: "\f065";
+$fa-var-compress: "\f066";
+$fa-var-plus: "\f067";
+$fa-var-minus: "\f068";
+$fa-var-asterisk: "\f069";
+$fa-var-exclamation-circle: "\f06a";
+$fa-var-gift: "\f06b";
+$fa-var-leaf: "\f06c";
+$fa-var-fire: "\f06d";
+$fa-var-eye: "\f06e";
+$fa-var-eye-slash: "\f070";
+$fa-var-exclamation-triangle: "\f071";
+$fa-var-plane: "\f072";
+$fa-var-calendar: "\f073";
+$fa-var-random: "\f074";
+$fa-var-comment: "\f075";
+$fa-var-magnet: "\f076";
+$fa-var-chevron-up: "\f077";
+$fa-var-chevron-down: "\f078";
+$fa-var-retweet: "\f079";
+$fa-var-shopping-cart: "\f07a";
+$fa-var-folder: "\f07b";
+$fa-var-folder-open: "\f07c";
+$fa-var-arrows-v: "\f07d";
+$fa-var-arrows-h: "\f07e";
+$fa-var-bar-chart-o: "\f080";
+$fa-var-twitter-square: "\f081";
+$fa-var-facebook-square: "\f082";
+$fa-var-camera-retro: "\f083";
+$fa-var-key: "\f084";
+$fa-var-cogs: "\f085";
+$fa-var-comments: "\f086";
+$fa-var-thumbs-o-up: "\f087";
+$fa-var-thumbs-o-down: "\f088";
+$fa-var-star-half: "\f089";
+$fa-var-heart-o: "\f08a";
+$fa-var-sign-out: "\f08b";
+$fa-var-linkedin-square: "\f08c";
+$fa-var-thumb-tack: "\f08d";
+$fa-var-external-link: "\f08e";
+$fa-var-sign-in: "\f090";
+$fa-var-trophy: "\f091";
+$fa-var-github-square: "\f092";
+$fa-var-upload: "\f093";
+$fa-var-lemon-o: "\f094";
+$fa-var-phone: "\f095";
+$fa-var-square-o: "\f096";
+$fa-var-bookmark-o: "\f097";
+$fa-var-phone-square: "\f098";
+$fa-var-twitter: "\f099";
+$fa-var-facebook: "\f09a";
+$fa-var-github: "\f09b";
+$fa-var-unlock: "\f09c";
+$fa-var-credit-card: "\f09d";
+$fa-var-rss: "\f09e";
+$fa-var-hdd-o: "\f0a0";
+$fa-var-bullhorn: "\f0a1";
+$fa-var-bell: "\f0f3";
+$fa-var-certificate: "\f0a3";
+$fa-var-hand-o-right: "\f0a4";
+$fa-var-hand-o-left: "\f0a5";
+$fa-var-hand-o-up: "\f0a6";
+$fa-var-hand-o-down: "\f0a7";
+$fa-var-arrow-circle-left: "\f0a8";
+$fa-var-arrow-circle-right: "\f0a9";
+$fa-var-arrow-circle-up: "\f0aa";
+$fa-var-arrow-circle-down: "\f0ab";
+$fa-var-globe: "\f0ac";
+$fa-var-wrench: "\f0ad";
+$fa-var-tasks: "\f0ae";
+$fa-var-filter: "\f0b0";
+$fa-var-briefcase: "\f0b1";
+$fa-var-arrows-alt: "\f0b2";
+$fa-var-users: "\f0c0";
+$fa-var-link: "\f0c1";
+$fa-var-cloud: "\f0c2";
+$fa-var-flask: "\f0c3";
+$fa-var-scissors: "\f0c4";
+$fa-var-files-o: "\f0c5";
+$fa-var-paperclip: "\f0c6";
+$fa-var-floppy-o: "\f0c7";
+$fa-var-square: "\f0c8";
+$fa-var-bars: "\f0c9";
+$fa-var-list-ul: "\f0ca";
+$fa-var-list-ol: "\f0cb";
+$fa-var-strikethrough: "\f0cc";
+$fa-var-underline: "\f0cd";
+$fa-var-table: "\f0ce";
+$fa-var-magic: "\f0d0";
+$fa-var-truck: "\f0d1";
+$fa-var-pinterest: "\f0d2";
+$fa-var-pinterest-square: "\f0d3";
+$fa-var-google-plus-square: "\f0d4";
+$fa-var-google-plus: "\f0d5";
+$fa-var-money: "\f0d6";
+$fa-var-caret-down: "\f0d7";
+$fa-var-caret-up: "\f0d8";
+$fa-var-caret-left: "\f0d9";
+$fa-var-caret-right: "\f0da";
+$fa-var-columns: "\f0db";
+$fa-var-sort: "\f0dc";
+$fa-var-sort-asc: "\f0dd";
+$fa-var-sort-desc: "\f0de";
+$fa-var-envelope: "\f0e0";
+$fa-var-linkedin: "\f0e1";
+$fa-var-undo: "\f0e2";
+$fa-var-gavel: "\f0e3";
+$fa-var-tachometer: "\f0e4";
+$fa-var-comment-o: "\f0e5";
+$fa-var-comments-o: "\f0e6";
+$fa-var-bolt: "\f0e7";
+$fa-var-sitemap: "\f0e8";
+$fa-var-umbrella: "\f0e9";
+$fa-var-clipboard: "\f0ea";
+$fa-var-lightbulb-o: "\f0eb";
+$fa-var-exchange: "\f0ec";
+$fa-var-cloud-download: "\f0ed";
+$fa-var-cloud-upload: "\f0ee";
+$fa-var-user-md: "\f0f0";
+$fa-var-stethoscope: "\f0f1";
+$fa-var-suitcase: "\f0f2";
+$fa-var-bell-o: "\f0a2";
+$fa-var-coffee: "\f0f4";
+$fa-var-cutlery: "\f0f5";
+$fa-var-file-text-o: "\f0f6";
+$fa-var-building-o: "\f0f7";
+$fa-var-hospital-o: "\f0f8";
+$fa-var-ambulance: "\f0f9";
+$fa-var-medkit: "\f0fa";
+$fa-var-fighter-jet: "\f0fb";
+$fa-var-beer: "\f0fc";
+$fa-var-h-square: "\f0fd";
+$fa-var-plus-square: "\f0fe";
+$fa-var-angle-double-left: "\f100";
+$fa-var-angle-double-right: "\f101";
+$fa-var-angle-double-up: "\f102";
+$fa-var-angle-double-down: "\f103";
+$fa-var-angle-left: "\f104";
+$fa-var-angle-right: "\f105";
+$fa-var-angle-up: "\f106";
+$fa-var-angle-down: "\f107";
+$fa-var-desktop: "\f108";
+$fa-var-laptop: "\f109";
+$fa-var-tablet: "\f10a";
+$fa-var-mobile: "\f10b";
+$fa-var-circle-o: "\f10c";
+$fa-var-quote-left: "\f10d";
+$fa-var-quote-right: "\f10e";
+$fa-var-spinner: "\f110";
+$fa-var-circle: "\f111";
+$fa-var-reply: "\f112";
+$fa-var-github-alt: "\f113";
+$fa-var-folder-o: "\f114";
+$fa-var-folder-open-o: "\f115";
+$fa-var-smile-o: "\f118";
+$fa-var-frown-o: "\f119";
+$fa-var-meh-o: "\f11a";
+$fa-var-gamepad: "\f11b";
+$fa-var-keyboard-o: "\f11c";
+$fa-var-flag-o: "\f11d";
+$fa-var-flag-checkered: "\f11e";
+$fa-var-terminal: "\f120";
+$fa-var-code: "\f121";
+$fa-var-reply-all: "\f122";
+$fa-var-mail-reply-all: "\f122";
+$fa-var-star-half-o: "\f123";
+$fa-var-location-arrow: "\f124";
+$fa-var-crop: "\f125";
+$fa-var-code-fork: "\f126";
+$fa-var-chain-broken: "\f127";
+$fa-var-question: "\f128";
+$fa-var-info: "\f129";
+$fa-var-exclamation: "\f12a";
+$fa-var-superscript: "\f12b";
+$fa-var-subscript: "\f12c";
+$fa-var-eraser: "\f12d";
+$fa-var-puzzle-piece: "\f12e";
+$fa-var-microphone: "\f130";
+$fa-var-microphone-slash: "\f131";
+$fa-var-shield: "\f132";
+$fa-var-calendar-o: "\f133";
+$fa-var-fire-extinguisher: "\f134";
+$fa-var-rocket: "\f135";
+$fa-var-maxcdn: "\f136";
+$fa-var-chevron-circle-left: "\f137";
+$fa-var-chevron-circle-right: "\f138";
+$fa-var-chevron-circle-up: "\f139";
+$fa-var-chevron-circle-down: "\f13a";
+$fa-var-html5: "\f13b";
+$fa-var-css3: "\f13c";
+$fa-var-anchor: "\f13d";
+$fa-var-unlock-alt: "\f13e";
+$fa-var-bullseye: "\f140";
+$fa-var-ellipsis-h: "\f141";
+$fa-var-ellipsis-v: "\f142";
+$fa-var-rss-square: "\f143";
+$fa-var-play-circle: "\f144";
+$fa-var-ticket: "\f145";
+$fa-var-minus-square: "\f146";
+$fa-var-minus-square-o: "\f147";
+$fa-var-level-up: "\f148";
+$fa-var-level-down: "\f149";
+$fa-var-check-square: "\f14a";
+$fa-var-pencil-square: "\f14b";
+$fa-var-external-link-square: "\f14c";
+$fa-var-share-square: "\f14d";
+$fa-var-compass: "\f14e";
+$fa-var-caret-square-o-down: "\f150";
+$fa-var-caret-square-o-up: "\f151";
+$fa-var-caret-square-o-right: "\f152";
+$fa-var-eur: "\f153";
+$fa-var-gbp: "\f154";
+$fa-var-usd: "\f155";
+$fa-var-inr: "\f156";
+$fa-var-jpy: "\f157";
+$fa-var-rub: "\f158";
+$fa-var-krw: "\f159";
+$fa-var-btc: "\f15a";
+$fa-var-file: "\f15b";
+$fa-var-file-text: "\f15c";
+$fa-var-sort-alpha-asc: "\f15d";
+$fa-var-sort-alpha-desc: "\f15e";
+$fa-var-sort-amount-asc: "\f160";
+$fa-var-sort-amount-desc: "\f161";
+$fa-var-sort-numeric-asc: "\f162";
+$fa-var-sort-numeric-desc: "\f163";
+$fa-var-thumbs-up: "\f164";
+$fa-var-thumbs-down: "\f165";
+$fa-var-youtube-square: "\f166";
+$fa-var-youtube: "\f167";
+$fa-var-xing: "\f168";
+$fa-var-xing-square: "\f169";
+$fa-var-youtube-play: "\f16a";
+$fa-var-dropbox: "\f16b";
+$fa-var-stack-overflow: "\f16c";
+$fa-var-instagram: "\f16d";
+$fa-var-flickr: "\f16e";
+$fa-var-adn: "\f170";
+$fa-var-bitbucket: "\f171";
+$fa-var-bitbucket-square: "\f172";
+$fa-var-tumblr: "\f173";
+$fa-var-tumblr-square: "\f174";
+$fa-var-long-arrow-down: "\f175";
+$fa-var-long-arrow-up: "\f176";
+$fa-var-long-arrow-left: "\f177";
+$fa-var-long-arrow-right: "\f178";
+$fa-var-apple: "\f179";
+$fa-var-windows: "\f17a";
+$fa-var-android: "\f17b";
+$fa-var-linux: "\f17c";
+$fa-var-dribbble: "\f17d";
+$fa-var-skype: "\f17e";
+$fa-var-foursquare: "\f180";
+$fa-var-trello: "\f181";
+$fa-var-female: "\f182";
+$fa-var-male: "\f183";
+$fa-var-gittip: "\f184";
+$fa-var-sun-o: "\f185";
+$fa-var-moon-o: "\f186";
+$fa-var-archive: "\f187";
+$fa-var-bug: "\f188";
+$fa-var-vk: "\f189";
+$fa-var-weibo: "\f18a";
+$fa-var-renren: "\f18b";
+$fa-var-pagelines: "\f18c";
+$fa-var-stack-exchange: "\f18d";
+$fa-var-arrow-circle-o-right: "\f18e";
+$fa-var-arrow-circle-o-left: "\f190";
+$fa-var-caret-square-o-left: "\f191";
+$fa-var-dot-circle-o: "\f192";
+$fa-var-wheelchair: "\f193";
+$fa-var-vimeo-square: "\f194";
+$fa-var-try: "\f195";
+$fa-var-plus-square-o: "\f196";
+
diff --git a/app/assets/stylesheets/fontawesome/bootstrap.less b/app/assets/stylesheets/fontawesome/bootstrap.less
deleted file mode 100644
index 444e298..0000000
--- a/app/assets/stylesheets/fontawesome/bootstrap.less
+++ /dev/null
@@ -1,78 +0,0 @@
-/* BOOTSTRAP SPECIFIC CLASSES
- * -------------------------- */
-
-/* Bootstrap 2.0 sprites.less reset */
-[class^="icon-"],
-[class*=" icon-"] {
- display: inline;
- width: auto;
- height: auto;
- line-height: normal;
- vertical-align: baseline;
- background-image: none;
- background-position: 0% 0%;
- background-repeat: repeat;
- margin-top: 0;
-}
-
-/* more sprites.less reset */
-.icon-white,
-.nav-pills > .active > a > [class^="icon-"],
-.nav-pills > .active > a > [class*=" icon-"],
-.nav-list > .active > a > [class^="icon-"],
-.nav-list > .active > a > [class*=" icon-"],
-.navbar-inverse .nav > .active > a > [class^="icon-"],
-.navbar-inverse .nav > .active > a > [class*=" icon-"],
-.dropdown-menu > li > a:hover > [class^="icon-"],
-.dropdown-menu > li > a:hover > [class*=" icon-"],
-.dropdown-menu > .active > a > [class^="icon-"],
-.dropdown-menu > .active > a > [class*=" icon-"],
-.dropdown-submenu:hover > a > [class^="icon-"],
-.dropdown-submenu:hover > a > [class*=" icon-"] {
- background-image: none;
-}
-
-
-/* keeps Bootstrap styles with and without icons the same */
-.btn, .nav {
- [class^="icon-"],
- [class*=" icon-"] {
-// display: inline;
- &.icon-large { line-height: .9em; }
- &.icon-spin { display: inline-block; }
- }
-}
-.nav-tabs, .nav-pills {
- [class^="icon-"],
- [class*=" icon-"] {
- &, &.icon-large { line-height: .9em; }
- }
-}
-.btn {
- [class^="icon-"],
- [class*=" icon-"] {
- &.pull-left, &.pull-right {
- &.icon-2x { margin-top: .18em; }
- }
- &.icon-spin.icon-large { line-height: .8em; }
- }
-}
-.btn.btn-small {
- [class^="icon-"],
- [class*=" icon-"] {
- &.pull-left, &.pull-right {
- &.icon-2x { margin-top: .25em; }
- }
- }
-}
-.btn.btn-large {
- [class^="icon-"],
- [class*=" icon-"] {
- margin-top: 0; // overrides bootstrap default
- &.pull-left, &.pull-right {
- &.icon-2x { margin-top: .05em; }
- }
- &.pull-left.icon-2x { margin-right: .2em; }
- &.pull-right.icon-2x { margin-left: .2em; }
- }
-}
diff --git a/app/assets/stylesheets/fontawesome/core.less b/app/assets/stylesheets/fontawesome/core.less
deleted file mode 100644
index 815d329..0000000
--- a/app/assets/stylesheets/fontawesome/core.less
+++ /dev/null
@@ -1,132 +0,0 @@
-/* FONT AWESOME CORE
- * -------------------------- */
-
-[class^="icon-"],
-[class*=" icon-"] {
- font-family: FontAwesome;
- font-weight: normal;
- font-style: normal;
- text-decoration: inherit;
- -webkit-font-smoothing: antialiased;
- *margin-right: .3em; // fixes ie7 issues
-}
-
-[class^="icon-"]:before,
-[class*=" icon-"]:before {
- text-decoration: inherit;
- display: inline-block;
- speak: none;
-}
-
-/* makes the font 33% larger relative to the icon container */
-.icon-large:before {
- vertical-align: -10%;
- font-size: 4/3em;
-}
-
-/* makes sure icons active on rollover in links */
-a {
- [class^="icon-"],
- [class*=" icon-"] {
- &, &:before { display: inline; }
- }
-}
-
-/* increased font size for icon-large */
-[class^="icon-"],
-[class*=" icon-"] {
- &.icon-fixed-width {
- display: inline-block;
- width: 18/14em;
- text-align: center;
- &.icon-large {
- width: 22/14em;
- }
- }
-}
-
-ul.icons-ul {
- list-style-type: none;
- text-indent: -10/14em;
- margin-left: 30/14em;
-
- > li {
- .icon-li {
- width: 10/14em;
- display: inline-block;
- text-align: center;
- }
- }
-}
-
-// allows usage of the hide class directly on font awesome icons
-[class^="icon-"],
-[class*=" icon-"] {
- &.hide {
- display: none;
- }
-}
-
-.icon-muted { color: @iconMuted; }
-.icon-light { color: @iconLight; }
-.icon-dark { color: @iconDark; }
-
-// Icon Borders
-// -------------------------
-
-.icon-border {
- border: solid 1px @borderColor;
- padding: .2em .25em .15em;
- .border-radius(3px);
-}
-
-// Icon Sizes
-// -------------------------
-
-.icon-2x {
- font-size: 2em;
- &.icon-border {
- border-width: 2px;
- .border-radius(4px);
- }
-}
-.icon-3x {
- font-size: 3em;
- &.icon-border {
- border-width: 3px;
- .border-radius(5px);
- }
-}
-.icon-4x {
- font-size: 4em;
- &.icon-border {
- border-width: 4px;
- .border-radius(6px);
- }
-}
-
-.icon-5x {
- font-size: 5em;
- &.icon-border {
- border-width: 5px;
- .border-radius(7px);
- }
-}
-
-
-// Floats & Margins
-// -------------------------
-
-// Quick floats
-.pull-right { float: right; }
-.pull-left { float: left; }
-
-[class^="icon-"],
-[class*=" icon-"] {
- &.pull-left {
- margin-right: .3em;
- }
- &.pull-right {
- margin-left: .3em;
- }
-}
diff --git a/app/assets/stylesheets/fontawesome/extras.less b/app/assets/stylesheets/fontawesome/extras.less
deleted file mode 100644
index 3d16eb6..0000000
--- a/app/assets/stylesheets/fontawesome/extras.less
+++ /dev/null
@@ -1,79 +0,0 @@
-/* EXTRAS
- * -------------------------- */
-
-/* Stacked and layered icon */
-.icon-stack();
-
-/* Animated rotating icon */
-.icon-spin {
- display: inline-block;
- -moz-animation: spin 2s infinite linear;
- -o-animation: spin 2s infinite linear;
- -webkit-animation: spin 2s infinite linear;
- animation: spin 2s infinite linear;
-}
-
-@-moz-keyframes spin {
- 0% { -moz-transform: rotate(0deg); }
- 100% { -moz-transform: rotate(359deg); }
-}
-@-webkit-keyframes spin {
- 0% { -webkit-transform: rotate(0deg); }
- 100% { -webkit-transform: rotate(359deg); }
-}
-@-o-keyframes spin {
- 0% { -o-transform: rotate(0deg); }
- 100% { -o-transform: rotate(359deg); }
-}
-@-ms-keyframes spin {
- 0% { -ms-transform: rotate(0deg); }
- 100% { -ms-transform: rotate(359deg); }
-}
-@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(359deg); }
-}
-
-/* Icon rotations and mirroring */
-.icon-rotate-90:before{
- -webkit-transform: rotate(90deg);
- -moz-transform: rotate(90deg);
- -ms-transform: rotate(90deg);
- -o-transform: rotate(90deg);
- transform: rotate(90deg);
- filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-}
-
-.icon-rotate-180:before{
- -webkit-transform: rotate(180deg);
- -moz-transform: rotate(180deg);
- -ms-transform: rotate(180deg);
- -o-transform: rotate(180deg);
- transform: rotate(180deg);
- filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
-}
-
-.icon-rotate-270:before{
- -webkit-transform: rotate(270deg);
- -moz-transform: rotate(270deg);
- -ms-transform: rotate(270deg);
- -o-transform: rotate(270deg);
- transform: rotate(270deg);
- filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
-}
-
-.icon-flip-horizontal:before {
- -webkit-transform: scale(-1, 1);
- -moz-transform: scale(-1, 1);
- -ms-transform: scale(-1, 1);
- -o-transform: scale(-1, 1);
- transform: scale(-1, 1);
-}
-
-.icon-flip-vertical:before {
- -webkit-transform: scale(1, -1);
- -moz-transform: scale(1, -1);
- -ms-transform: scale(1, -1);
- -o-transform: scale(1, -1);
- transform: scale(1, -1);
-}
\ No newline at end of file
diff --git a/app/assets/stylesheets/fontawesome/font-awesome-ie7.less b/app/assets/stylesheets/fontawesome/font-awesome-ie7.less
deleted file mode 100644
index 9e5ac0e..0000000
--- a/app/assets/stylesheets/fontawesome/font-awesome-ie7.less
+++ /dev/null
@@ -1,413 +0,0 @@
-/*!
- * Font Awesome 3.1.0
- * the iconic font designed for Bootstrap
- * -------------------------------------------------------
- * The full suite of pictographic icons, examples, and documentation
- * can be found at: http://fontawesome.io
- *
- * License
- * -------------------------------------------------------
- * - The Font Awesome font is licensed under the SIL Open Font License v1.1 -
- * http://scripts.sil.org/OFL
- * - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
- * http://opensource.org/licenses/mit-license.html
- * - Font Awesome documentation licensed under CC BY 3.0 License -
- * http://creativecommons.org/licenses/by/3.0/
- * - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
- * "Font Awesome by Dave Gandy - http://fontawesome.io"
-
- * Contact
- * -------------------------------------------------------
- * Email: dave@fontawesome.io
- * Twitter: http://twitter.com/fortaweso_me
- * Work: Lead Product Designer @ http://kyruus.com
- */
-
-.icon-large {
- font-size: 4/3em;
- margin-top: -4px;
- padding-top: 3px;
- margin-bottom: -4px;
- padding-bottom: 3px;
- vertical-align: middle;
-}
-
-.nav {
- [class^="icon-"],
- [class*=" icon-"] {
- vertical-align: inherit;
- margin-top: -4px;
- padding-top: 3px;
- margin-bottom: -4px;
- padding-bottom: 3px;
- &.icon-large {
- vertical-align: -25%;
- }
- }
-}
-
-.nav-pills, .nav-tabs {
- [class^="icon-"],
- [class*=" icon-"] {
- &.icon-large {
- line-height: .75em;
- margin-top: -7px;
- padding-top: 5px;
- margin-bottom: -5px;
- padding-bottom: 4px;
- }
- }
-}
-
-ul.icons-ul {
- text-indent: -1em;
- margin-left: 30/14em;
-
- > li {
- .icon-li {
- width: 1em;
- margin-right: 0;
- }
- }
-}
-
-.btn {
- [class^="icon-"],
- [class*=" icon-"] {
- &.pull-left, &.pull-right { vertical-align: inherit; }
- &.icon-large {
- margin-top: -.5em;
- }
- }
-}
-
-a [class^="icon-"],
-a [class*=" icon-"] {
- cursor: pointer;
-}
-
-.ie7icon(@inner) { *zoom: ~"expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '@{inner}')"; }
-
-.icon-glass { .ie7icon(''); }
-.icon-music { .ie7icon(''); }
-.icon-search { .ie7icon(''); }
-.icon-envelope { .ie7icon(''); }
-.icon-heart { .ie7icon(''); }
-.icon-star { .ie7icon(''); }
-.icon-star-empty { .ie7icon(''); }
-.icon-user { .ie7icon(''); }
-.icon-film { .ie7icon(''); }
-.icon-th-large { .ie7icon(''); }
-.icon-th { .ie7icon(''); }
-.icon-th-list { .ie7icon(''); }
-.icon-ok { .ie7icon(''); }
-.icon-remove { .ie7icon(''); }
-.icon-zoom-in { .ie7icon(''); }
-
-.icon-zoom-out { .ie7icon(''); }
-.icon-off { .ie7icon(''); }
-.icon-signal { .ie7icon(''); }
-.icon-cog { .ie7icon(''); }
-.icon-trash { .ie7icon(''); }
-.icon-home { .ie7icon(''); }
-.icon-file { .ie7icon(''); }
-.icon-time { .ie7icon(''); }
-.icon-road { .ie7icon(''); }
-.icon-download-alt { .ie7icon(''); }
-.icon-download { .ie7icon(''); }
-.icon-upload { .ie7icon(''); }
-.icon-inbox { .ie7icon(''); }
-.icon-play-circle { .ie7icon(''); }
-.icon-repeat { .ie7icon(''); }
-
-.icon-refresh { .ie7icon(''); }
-.icon-list-alt { .ie7icon(''); }
-.icon-lock { .ie7icon(''); }
-.icon-flag { .ie7icon(''); }
-.icon-headphones { .ie7icon(''); }
-.icon-volume-off { .ie7icon(''); }
-.icon-volume-down { .ie7icon(''); }
-.icon-volume-up { .ie7icon(''); }
-.icon-qrcode { .ie7icon(''); }
-.icon-barcode { .ie7icon(''); }
-.icon-tag { .ie7icon(''); }
-.icon-tags { .ie7icon(''); }
-.icon-book { .ie7icon(''); }
-.icon-bookmark { .ie7icon(''); }
-.icon-print { .ie7icon(''); }
-
-.icon-camera { .ie7icon(''); }
-.icon-font { .ie7icon(''); }
-.icon-bold { .ie7icon(''); }
-.icon-italic { .ie7icon(''); }
-.icon-text-height { .ie7icon(''); }
-.icon-text-width { .ie7icon(''); }
-.icon-align-left { .ie7icon(''); }
-.icon-align-center { .ie7icon(''); }
-.icon-align-right { .ie7icon(''); }
-.icon-align-justify { .ie7icon(''); }
-.icon-list { .ie7icon(''); }
-.icon-indent-left { .ie7icon(''); }
-.icon-indent-right { .ie7icon(''); }
-.icon-facetime-video { .ie7icon(''); }
-.icon-picture { .ie7icon(''); }
-
-.icon-pencil { .ie7icon(''); }
-.icon-map-marker { .ie7icon(''); }
-.icon-adjust { .ie7icon(''); }
-.icon-tint { .ie7icon(''); }
-.icon-edit { .ie7icon(''); }
-.icon-share { .ie7icon(''); }
-.icon-check { .ie7icon(''); }
-.icon-move { .ie7icon(''); }
-.icon-step-backward { .ie7icon(''); }
-.icon-fast-backward { .ie7icon(''); }
-.icon-backward { .ie7icon(''); }
-.icon-play { .ie7icon(''); }
-.icon-pause { .ie7icon(''); }
-.icon-stop { .ie7icon(''); }
-.icon-forward { .ie7icon(''); }
-
-.icon-fast-forward { .ie7icon(''); }
-.icon-step-forward { .ie7icon(''); }
-.icon-eject { .ie7icon(''); }
-.icon-chevron-left { .ie7icon(''); }
-.icon-chevron-right { .ie7icon(''); }
-.icon-plus-sign { .ie7icon(''); }
-.icon-minus-sign { .ie7icon(''); }
-.icon-remove-sign { .ie7icon(''); }
-.icon-ok-sign { .ie7icon(''); }
-.icon-question-sign { .ie7icon(''); }
-.icon-info-sign { .ie7icon(''); }
-.icon-screenshot { .ie7icon(''); }
-.icon-remove-circle { .ie7icon(''); }
-.icon-ok-circle { .ie7icon(''); }
-.icon-ban-circle { .ie7icon(''); }
-
-.icon-arrow-left { .ie7icon(''); }
-.icon-arrow-right { .ie7icon(''); }
-.icon-arrow-up { .ie7icon(''); }
-.icon-arrow-down { .ie7icon(''); }
-.icon-share-alt { .ie7icon(''); }
-.icon-resize-full { .ie7icon(''); }
-.icon-resize-small { .ie7icon(''); }
-.icon-plus { .ie7icon(''); }
-.icon-minus { .ie7icon(''); }
-.icon-asterisk { .ie7icon(''); }
-.icon-exclamation-sign { .ie7icon(''); }
-.icon-gift { .ie7icon(''); }
-.icon-leaf { .ie7icon(''); }
-.icon-fire { .ie7icon(''); }
-.icon-eye-open { .ie7icon(''); }
-
-.icon-eye-close { .ie7icon(''); }
-.icon-warning-sign { .ie7icon(''); }
-.icon-plane { .ie7icon(''); }
-.icon-calendar { .ie7icon(''); }
-.icon-random { .ie7icon(''); }
-.icon-comment { .ie7icon(''); }
-.icon-magnet { .ie7icon(''); }
-.icon-chevron-up { .ie7icon(''); }
-.icon-chevron-down { .ie7icon(''); }
-.icon-retweet { .ie7icon(''); }
-.icon-shopping-cart { .ie7icon(''); }
-.icon-folder-close { .ie7icon(''); }
-.icon-folder-open { .ie7icon(''); }
-.icon-resize-vertical { .ie7icon(''); }
-.icon-resize-horizontal { .ie7icon(''); }
-
-.icon-bar-chart { .ie7icon(''); }
-.icon-twitter-sign { .ie7icon(''); }
-.icon-facebook-sign { .ie7icon(''); }
-.icon-camera-retro { .ie7icon(''); }
-.icon-key { .ie7icon(''); }
-.icon-cogs { .ie7icon(''); }
-.icon-comments { .ie7icon(''); }
-.icon-thumbs-up { .ie7icon(''); }
-.icon-thumbs-down { .ie7icon(''); }
-.icon-star-half { .ie7icon(''); }
-.icon-heart-empty { .ie7icon(''); }
-.icon-signout { .ie7icon(''); }
-.icon-linkedin-sign { .ie7icon(''); }
-.icon-pushpin { .ie7icon(''); }
-.icon-external-link { .ie7icon(''); }
-
-.icon-signin { .ie7icon(''); }
-.icon-trophy { .ie7icon(''); }
-.icon-github-sign { .ie7icon(''); }
-.icon-upload-alt { .ie7icon(''); }
-.icon-lemon { .ie7icon(''); }
-.icon-phone { .ie7icon(''); }
-.icon-check-empty { .ie7icon(''); }
-.icon-bookmark-empty { .ie7icon(''); }
-.icon-phone-sign { .ie7icon(''); }
-.icon-twitter { .ie7icon(''); }
-.icon-facebook { .ie7icon(''); }
-.icon-github { .ie7icon(''); }
-.icon-unlock { .ie7icon(''); }
-.icon-credit-card { .ie7icon(''); }
-.icon-rss { .ie7icon(''); }
-
-.icon-hdd { .ie7icon(''); }
-.icon-bullhorn { .ie7icon(''); }
-.icon-bell { .ie7icon(''); }
-.icon-certificate { .ie7icon(''); }
-.icon-hand-right { .ie7icon(''); }
-.icon-hand-left { .ie7icon(''); }
-.icon-hand-up { .ie7icon(''); }
-.icon-hand-down { .ie7icon(''); }
-.icon-circle-arrow-left { .ie7icon(''); }
-.icon-circle-arrow-right { .ie7icon(''); }
-.icon-circle-arrow-up { .ie7icon(''); }
-.icon-circle-arrow-down { .ie7icon(''); }
-.icon-globe { .ie7icon(''); }
-.icon-wrench { .ie7icon(''); }
-.icon-tasks { .ie7icon(''); }
-
-.icon-filter { .ie7icon(''); }
-.icon-briefcase { .ie7icon(''); }
-.icon-fullscreen { .ie7icon(''); }
-
-.icon-group { .ie7icon(''); }
-.icon-link { .ie7icon(''); }
-.icon-cloud { .ie7icon(''); }
-.icon-beaker { .ie7icon(''); }
-.icon-cut { .ie7icon(''); }
-.icon-copy { .ie7icon(''); }
-.icon-paper-clip { .ie7icon(''); }
-.icon-save { .ie7icon(''); }
-.icon-sign-blank { .ie7icon(''); }
-.icon-reorder { .ie7icon(''); }
-.icon-list-ul { .ie7icon(''); }
-.icon-list-ol { .ie7icon(''); }
-.icon-strikethrough { .ie7icon(''); }
-.icon-underline { .ie7icon(''); }
-.icon-table { .ie7icon(''); }
-
-.icon-magic { .ie7icon(''); }
-.icon-truck { .ie7icon(''); }
-.icon-pinterest { .ie7icon(''); }
-.icon-pinterest-sign { .ie7icon(''); }
-.icon-google-plus-sign { .ie7icon(''); }
-.icon-google-plus { .ie7icon(''); }
-.icon-money { .ie7icon(''); }
-.icon-caret-down { .ie7icon(''); }
-.icon-caret-up { .ie7icon(''); }
-.icon-caret-left { .ie7icon(''); }
-.icon-caret-right { .ie7icon(''); }
-.icon-columns { .ie7icon(''); }
-.icon-sort { .ie7icon(''); }
-.icon-sort-down { .ie7icon(''); }
-.icon-sort-up { .ie7icon(''); }
-
-.icon-envelope-alt { .ie7icon(''); }
-.icon-linkedin { .ie7icon(''); }
-.icon-undo { .ie7icon(''); }
-.icon-legal { .ie7icon(''); }
-.icon-dashboard { .ie7icon(''); }
-.icon-comment-alt { .ie7icon(''); }
-.icon-comments-alt { .ie7icon(''); }
-.icon-bolt { .ie7icon(''); }
-.icon-sitemap { .ie7icon(''); }
-.icon-umbrella { .ie7icon(''); }
-.icon-paste { .ie7icon(''); }
-.icon-lightbulb { .ie7icon(''); }
-.icon-exchange { .ie7icon(''); }
-.icon-cloud-download { .ie7icon(''); }
-.icon-cloud-upload { .ie7icon(''); }
-
-.icon-user-md { .ie7icon(''); }
-.icon-stethoscope { .ie7icon(''); }
-.icon-suitcase { .ie7icon(''); }
-.icon-bell-alt { .ie7icon(''); }
-.icon-coffee { .ie7icon(''); }
-.icon-food { .ie7icon(''); }
-.icon-file-alt { .ie7icon(''); }
-.icon-building { .ie7icon(''); }
-.icon-hospital { .ie7icon(''); }
-.icon-ambulance { .ie7icon(''); }
-.icon-medkit { .ie7icon(''); }
-.icon-fighter-jet { .ie7icon(''); }
-.icon-beer { .ie7icon(''); }
-.icon-h-sign { .ie7icon(''); }
-.icon-plus-sign-alt { .ie7icon(''); }
-
-.icon-double-angle-left { .ie7icon(''); }
-.icon-double-angle-right { .ie7icon(''); }
-.icon-double-angle-up { .ie7icon(''); }
-.icon-double-angle-down { .ie7icon(''); }
-.icon-angle-left { .ie7icon(''); }
-.icon-angle-right { .ie7icon(''); }
-.icon-angle-up { .ie7icon(''); }
-.icon-angle-down { .ie7icon(''); }
-.icon-desktop { .ie7icon(''); }
-.icon-laptop { .ie7icon(''); }
-.icon-tablet { .ie7icon(''); }
-.icon-mobile-phone { .ie7icon(''); }
-.icon-circle-blank { .ie7icon(''); }
-.icon-quote-left { .ie7icon(''); }
-.icon-quote-right { .ie7icon(''); }
-
-.icon-spinner { .ie7icon(''); }
-.icon-circle { .ie7icon(''); }
-.icon-reply { .ie7icon(''); }
-.icon-folder-close-alt { .ie7icon(''); }
-.icon-folder-open-alt { .ie7icon(''); }
-.icon-expand-alt { .ie7icon(''); }
-.icon-collapse-alt { .ie7icon(''); }
-.icon-smile { .ie7icon(''); }
-.icon-frown { .ie7icon(''); }
-.icon-meh { .ie7icon(''); }
-.icon-gamepad { .ie7icon(''); }
-.icon-keyboard { .ie7icon(''); }
-.icon-flag-alt { .ie7icon(''); }
-.icon-flag-checkered { .ie7icon(''); }
-
-.icon-terminal { .ie7icon(''); }
-.icon-code { .ie7icon(''); }
-.icon-reply-all { .ie7icon(''); }
-.icon-mail-reply-all { .ie7icon(''); }
-.icon-star-half-full,
-.icon-star-half-empty { .ie7icon(''); }
-.icon-location-arrow { .ie7icon(''); }
-.icon-crop { .ie7icon(''); }
-.icon-code-fork { .ie7icon(''); }
-.icon-unlink { .ie7icon(''); }
-.icon-question { .ie7icon(''); }
-.icon-info { .ie7icon(''); }
-.icon-exclamation { .ie7icon(''); }
-.icon-superscript { .ie7icon(''); }
-.icon-subscript { .ie7icon(''); }
-.icon-eraser { .ie7icon(''); }
-.icon-puzzle-piece { .ie7icon(''); }
-
-.icon-microphone { .ie7icon(''); }
-.icon-microphone-off { .ie7icon(''); }
-.icon-shield { .ie7icon(''); }
-.icon-calendar-empty { .ie7icon(''); }
-.icon-fire-extinguisher { .ie7icon(''); }
-.icon-rocket { .ie7icon(''); }
-.icon-maxcdn { .ie7icon(''); }
-.icon-chevron-sign-left { .ie7icon(''); }
-.icon-chevron-sign-right { .ie7icon(''); }
-.icon-chevron-sign-up { .ie7icon(''); }
-.icon-chevron-sign-down { .ie7icon(''); }
-.icon-html5 { .ie7icon(''); }
-.icon-css3 { .ie7icon(''); }
-.icon-anchor { .ie7icon(''); }
-.icon-unlock-alt { .ie7icon(''); }
-
-.icon-bullseye { .ie7icon(''); }
-.icon-ellipsis-horizontal { .ie7icon(''); }
-.icon-ellipsis-vertical { .ie7icon(''); }
-.icon-rss-sign { .ie7icon(''); }
-.icon-play-sign { .ie7icon(''); }
-.icon-ticket { .ie7icon(''); }
-.icon-minus-sign-alt { .ie7icon(''); }
-.icon-check-minus { .ie7icon(''); }
-.icon-level-up { .ie7icon(''); }
-.icon-level-down { .ie7icon(''); }
-.icon-check-sign { .ie7icon(''); }
-.icon-edit-sign { .ie7icon(''); }
-.icon-external-link-sign { .ie7icon(''); }
-.icon-share-sign { .ie7icon(''); }
diff --git a/app/assets/stylesheets/fontawesome/font-awesome.less b/app/assets/stylesheets/fontawesome/font-awesome.less
deleted file mode 100644
index 0a9518e..0000000
--- a/app/assets/stylesheets/fontawesome/font-awesome.less
+++ /dev/null
@@ -1,32 +0,0 @@
-/*!
- * Font Awesome 3.1.0
- * the iconic font designed for Bootstrap
- * -------------------------------------------------------
- * The full suite of pictographic icons, examples, and documentation
- * can be found at: http://fontawesome.io
- *
- * License
- * -------------------------------------------------------
- * - The Font Awesome font is licensed under the SIL Open Font License v1.1 -
- * http://scripts.sil.org/OFL
- * - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
- * http://opensource.org/licenses/mit-license.html
- * - Font Awesome documentation licensed under CC BY 3.0 License -
- * http://creativecommons.org/licenses/by/3.0/
- * - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
- * "Font Awesome by Dave Gandy - http://fontawesome.io"
-
- * Contact
- * -------------------------------------------------------
- * Email: dave@fontawesome.io
- * Twitter: http://twitter.com/fortaweso_me
- * Work: Lead Product Designer @ http://kyruus.com
- */
-
-@import "variables.less";
-@import "mixins.less";
-@import "path.less";
-@import "core.less";
-@import "bootstrap.less";
-@import "extras.less";
-@import "icons.less";
diff --git a/app/assets/stylesheets/fontawesome/font-awesome.scss b/app/assets/stylesheets/fontawesome/font-awesome.scss
new file mode 100644
index 0000000..96d2f22
--- /dev/null
+++ b/app/assets/stylesheets/fontawesome/font-awesome.scss
@@ -0,0 +1,17 @@
+/*!
+ * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */
+
+@import "variables";
+@import "mixins";
+@import "path";
+@import "core";
+@import "larger";
+@import "fixed-width";
+@import "list";
+@import "bordered-pulled";
+@import "spinning";
+@import "rotated-flipped";
+@import "stacked";
+@import "icons";
diff --git a/app/assets/stylesheets/fontawesome/icons.less b/app/assets/stylesheets/fontawesome/icons.less
deleted file mode 100644
index 027933a..0000000
--- a/app/assets/stylesheets/fontawesome/icons.less
+++ /dev/null
@@ -1,330 +0,0 @@
-/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
- readers do not read off random characters that represent icons */
-.icon-glass:before { content: "\f000"; }
-.icon-music:before { content: "\f001"; }
-.icon-search:before { content: "\f002"; }
-.icon-envelope:before { content: "\f003"; }
-.icon-heart:before { content: "\f004"; }
-.icon-star:before { content: "\f005"; }
-.icon-star-empty:before { content: "\f006"; }
-.icon-user:before { content: "\f007"; }
-.icon-film:before { content: "\f008"; }
-.icon-th-large:before { content: "\f009"; }
-.icon-th:before { content: "\f00a"; }
-.icon-th-list:before { content: "\f00b"; }
-.icon-ok:before { content: "\f00c"; }
-.icon-remove:before { content: "\f00d"; }
-.icon-zoom-in:before { content: "\f00e"; }
-
-.icon-zoom-out:before { content: "\f010"; }
-.icon-off:before { content: "\f011"; }
-.icon-signal:before { content: "\f012"; }
-.icon-cog:before { content: "\f013"; }
-.icon-trash:before { content: "\f014"; }
-.icon-home:before { content: "\f015"; }
-.icon-file:before { content: "\f016"; }
-.icon-time:before { content: "\f017"; }
-.icon-road:before { content: "\f018"; }
-.icon-download-alt:before { content: "\f019"; }
-.icon-download:before { content: "\f01a"; }
-.icon-upload:before { content: "\f01b"; }
-.icon-inbox:before { content: "\f01c"; }
-.icon-play-circle:before { content: "\f01d"; }
-.icon-repeat:before,
-.icon-rotate-right:before { content: "\f01e"; }
-
-/* F020 doesn't work in Safari. all shifted one down */
-.icon-refresh:before { content: "\f021"; }
-.icon-list-alt:before { content: "\f022"; }
-.icon-lock:before { content: "\f023"; }
-.icon-flag:before { content: "\f024"; }
-.icon-headphones:before { content: "\f025"; }
-.icon-volume-off:before { content: "\f026"; }
-.icon-volume-down:before { content: "\f027"; }
-.icon-volume-up:before { content: "\f028"; }
-.icon-qrcode:before { content: "\f029"; }
-.icon-barcode:before { content: "\f02a"; }
-.icon-tag:before { content: "\f02b"; }
-.icon-tags:before { content: "\f02c"; }
-.icon-book:before { content: "\f02d"; }
-.icon-bookmark:before { content: "\f02e"; }
-.icon-print:before { content: "\f02f"; }
-
-.icon-camera:before { content: "\f030"; }
-.icon-font:before { content: "\f031"; }
-.icon-bold:before { content: "\f032"; }
-.icon-italic:before { content: "\f033"; }
-.icon-text-height:before { content: "\f034"; }
-.icon-text-width:before { content: "\f035"; }
-.icon-align-left:before { content: "\f036"; }
-.icon-align-center:before { content: "\f037"; }
-.icon-align-right:before { content: "\f038"; }
-.icon-align-justify:before { content: "\f039"; }
-.icon-list:before { content: "\f03a"; }
-.icon-indent-left:before { content: "\f03b"; }
-.icon-indent-right:before { content: "\f03c"; }
-.icon-facetime-video:before { content: "\f03d"; }
-.icon-picture:before { content: "\f03e"; }
-
-.icon-pencil:before { content: "\f040"; }
-.icon-map-marker:before { content: "\f041"; }
-.icon-adjust:before { content: "\f042"; }
-.icon-tint:before { content: "\f043"; }
-.icon-edit:before { content: "\f044"; }
-.icon-share:before { content: "\f045"; }
-.icon-check:before { content: "\f046"; }
-.icon-move:before { content: "\f047"; }
-.icon-step-backward:before { content: "\f048"; }
-.icon-fast-backward:before { content: "\f049"; }
-.icon-backward:before { content: "\f04a"; }
-.icon-play:before { content: "\f04b"; }
-.icon-pause:before { content: "\f04c"; }
-.icon-stop:before { content: "\f04d"; }
-.icon-forward:before { content: "\f04e"; }
-
-.icon-fast-forward:before { content: "\f050"; }
-.icon-step-forward:before { content: "\f051"; }
-.icon-eject:before { content: "\f052"; }
-.icon-chevron-left:before { content: "\f053"; }
-.icon-chevron-right:before { content: "\f054"; }
-.icon-plus-sign:before { content: "\f055"; }
-.icon-minus-sign:before { content: "\f056"; }
-.icon-remove-sign:before { content: "\f057"; }
-.icon-ok-sign:before { content: "\f058"; }
-.icon-question-sign:before { content: "\f059"; }
-.icon-info-sign:before { content: "\f05a"; }
-.icon-screenshot:before { content: "\f05b"; }
-.icon-remove-circle:before { content: "\f05c"; }
-.icon-ok-circle:before { content: "\f05d"; }
-.icon-ban-circle:before { content: "\f05e"; }
-
-.icon-arrow-left:before { content: "\f060"; }
-.icon-arrow-right:before { content: "\f061"; }
-.icon-arrow-up:before { content: "\f062"; }
-.icon-arrow-down:before { content: "\f063"; }
-.icon-share-alt:before,
-.icon-mail-forward:before { content: "\f064"; }
-.icon-resize-full:before { content: "\f065"; }
-.icon-resize-small:before { content: "\f066"; }
-.icon-plus:before { content: "\f067"; }
-.icon-minus:before { content: "\f068"; }
-.icon-asterisk:before { content: "\f069"; }
-.icon-exclamation-sign:before { content: "\f06a"; }
-.icon-gift:before { content: "\f06b"; }
-.icon-leaf:before { content: "\f06c"; }
-.icon-fire:before { content: "\f06d"; }
-.icon-eye-open:before { content: "\f06e"; }
-
-.icon-eye-close:before { content: "\f070"; }
-.icon-warning-sign:before { content: "\f071"; }
-.icon-plane:before { content: "\f072"; }
-.icon-calendar:before { content: "\f073"; }
-.icon-random:before { content: "\f074"; }
-.icon-comment:before { content: "\f075"; }
-.icon-magnet:before { content: "\f076"; }
-.icon-chevron-up:before { content: "\f077"; }
-.icon-chevron-down:before { content: "\f078"; }
-.icon-retweet:before { content: "\f079"; }
-.icon-shopping-cart:before { content: "\f07a"; }
-.icon-folder-close:before { content: "\f07b"; }
-.icon-folder-open:before { content: "\f07c"; }
-.icon-resize-vertical:before { content: "\f07d"; }
-.icon-resize-horizontal:before { content: "\f07e"; }
-
-.icon-bar-chart:before { content: "\f080"; }
-.icon-twitter-sign:before { content: "\f081"; }
-.icon-facebook-sign:before { content: "\f082"; }
-.icon-camera-retro:before { content: "\f083"; }
-.icon-key:before { content: "\f084"; }
-.icon-cogs:before { content: "\f085"; }
-.icon-comments:before { content: "\f086"; }
-.icon-thumbs-up:before { content: "\f087"; }
-.icon-thumbs-down:before { content: "\f088"; }
-.icon-star-half:before { content: "\f089"; }
-.icon-heart-empty:before { content: "\f08a"; }
-.icon-signout:before { content: "\f08b"; }
-.icon-linkedin-sign:before { content: "\f08c"; }
-.icon-pushpin:before { content: "\f08d"; }
-.icon-external-link:before { content: "\f08e"; }
-
-.icon-signin:before { content: "\f090"; }
-.icon-trophy:before { content: "\f091"; }
-.icon-github-sign:before { content: "\f092"; }
-.icon-upload-alt:before { content: "\f093"; }
-.icon-lemon:before { content: "\f094"; }
-.icon-phone:before { content: "\f095"; }
-.icon-check-empty:before { content: "\f096"; }
-.icon-bookmark-empty:before { content: "\f097"; }
-.icon-phone-sign:before { content: "\f098"; }
-.icon-twitter:before { content: "\f099"; }
-.icon-facebook:before { content: "\f09a"; }
-.icon-github:before { content: "\f09b"; }
-.icon-unlock:before { content: "\f09c"; }
-.icon-credit-card:before { content: "\f09d"; }
-.icon-rss:before { content: "\f09e"; }
-
-.icon-hdd:before { content: "\f0a0"; }
-.icon-bullhorn:before { content: "\f0a1"; }
-.icon-bell:before { content: "\f0a2"; }
-.icon-certificate:before { content: "\f0a3"; }
-.icon-hand-right:before { content: "\f0a4"; }
-.icon-hand-left:before { content: "\f0a5"; }
-.icon-hand-up:before { content: "\f0a6"; }
-.icon-hand-down:before { content: "\f0a7"; }
-.icon-circle-arrow-left:before { content: "\f0a8"; }
-.icon-circle-arrow-right:before { content: "\f0a9"; }
-.icon-circle-arrow-up:before { content: "\f0aa"; }
-.icon-circle-arrow-down:before { content: "\f0ab"; }
-.icon-globe:before { content: "\f0ac"; }
-.icon-wrench:before { content: "\f0ad"; }
-.icon-tasks:before { content: "\f0ae"; }
-
-.icon-filter:before { content: "\f0b0"; }
-.icon-briefcase:before { content: "\f0b1"; }
-.icon-fullscreen:before { content: "\f0b2"; }
-
-.icon-group:before { content: "\f0c0"; }
-.icon-link:before { content: "\f0c1"; }
-.icon-cloud:before { content: "\f0c2"; }
-.icon-beaker:before { content: "\f0c3"; }
-.icon-cut:before { content: "\f0c4"; }
-.icon-copy:before { content: "\f0c5"; }
-.icon-paper-clip:before { content: "\f0c6"; }
-.icon-save:before { content: "\f0c7"; }
-.icon-sign-blank:before { content: "\f0c8"; }
-.icon-reorder:before { content: "\f0c9"; }
-.icon-list-ul:before { content: "\f0ca"; }
-.icon-list-ol:before { content: "\f0cb"; }
-.icon-strikethrough:before { content: "\f0cc"; }
-.icon-underline:before { content: "\f0cd"; }
-.icon-table:before { content: "\f0ce"; }
-
-.icon-magic:before { content: "\f0d0"; }
-.icon-truck:before { content: "\f0d1"; }
-.icon-pinterest:before { content: "\f0d2"; }
-.icon-pinterest-sign:before { content: "\f0d3"; }
-.icon-google-plus-sign:before { content: "\f0d4"; }
-.icon-google-plus:before { content: "\f0d5"; }
-.icon-money:before { content: "\f0d6"; }
-.icon-caret-down:before { content: "\f0d7"; }
-.icon-caret-up:before { content: "\f0d8"; }
-.icon-caret-left:before { content: "\f0d9"; }
-.icon-caret-right:before { content: "\f0da"; }
-.icon-columns:before { content: "\f0db"; }
-.icon-sort:before { content: "\f0dc"; }
-.icon-sort-down:before { content: "\f0dd"; }
-.icon-sort-up:before { content: "\f0de"; }
-
-.icon-envelope-alt:before { content: "\f0e0"; }
-.icon-linkedin:before { content: "\f0e1"; }
-.icon-undo:before,
-.icon-rotate-left:before { content: "\f0e2"; }
-.icon-legal:before { content: "\f0e3"; }
-.icon-dashboard:before { content: "\f0e4"; }
-.icon-comment-alt:before { content: "\f0e5"; }
-.icon-comments-alt:before { content: "\f0e6"; }
-.icon-bolt:before { content: "\f0e7"; }
-.icon-sitemap:before { content: "\f0e8"; }
-.icon-umbrella:before { content: "\f0e9"; }
-.icon-paste:before { content: "\f0ea"; }
-.icon-lightbulb:before { content: "\f0eb"; }
-.icon-exchange:before { content: "\f0ec"; }
-.icon-cloud-download:before { content: "\f0ed"; }
-.icon-cloud-upload:before { content: "\f0ee"; }
-
-.icon-user-md:before { content: "\f0f0"; }
-.icon-stethoscope:before { content: "\f0f1"; }
-.icon-suitcase:before { content: "\f0f2"; }
-.icon-bell-alt:before { content: "\f0f3"; }
-.icon-coffee:before { content: "\f0f4"; }
-.icon-food:before { content: "\f0f5"; }
-.icon-file-alt:before { content: "\f0f6"; }
-.icon-building:before { content: "\f0f7"; }
-.icon-hospital:before { content: "\f0f8"; }
-.icon-ambulance:before { content: "\f0f9"; }
-.icon-medkit:before { content: "\f0fa"; }
-.icon-fighter-jet:before { content: "\f0fb"; }
-.icon-beer:before { content: "\f0fc"; }
-.icon-h-sign:before { content: "\f0fd"; }
-.icon-plus-sign-alt:before { content: "\f0fe"; }
-
-.icon-double-angle-left:before { content: "\f100"; }
-.icon-double-angle-right:before { content: "\f101"; }
-.icon-double-angle-up:before { content: "\f102"; }
-.icon-double-angle-down:before { content: "\f103"; }
-.icon-angle-left:before { content: "\f104"; }
-.icon-angle-right:before { content: "\f105"; }
-.icon-angle-up:before { content: "\f106"; }
-.icon-angle-down:before { content: "\f107"; }
-.icon-desktop:before { content: "\f108"; }
-.icon-laptop:before { content: "\f109"; }
-.icon-tablet:before { content: "\f10a"; }
-.icon-mobile-phone:before { content: "\f10b"; }
-.icon-circle-blank:before { content: "\f10c"; }
-.icon-quote-left:before { content: "\f10d"; }
-.icon-quote-right:before { content: "\f10e"; }
-
-.icon-spinner:before { content: "\f110"; }
-.icon-circle:before { content: "\f111"; }
-.icon-reply:before,
-.icon-mail-reply:before { content: "\f112"; }
-.icon-folder-close-alt:before { content: "\f114"; }
-.icon-folder-open-alt:before { content: "\f115"; }
-.icon-expand-alt:before { content: "\f116"; }
-.icon-collapse-alt:before { content: "\f117"; }
-.icon-smile:before { content: "\f118"; }
-.icon-frown:before { content: "\f119"; }
-.icon-meh:before { content: "\f11a"; }
-.icon-gamepad:before { content: "\f11b"; }
-.icon-keyboard:before { content: "\f11c"; }
-.icon-flag-alt:before { content: "\f11d"; }
-.icon-flag-checkered:before { content: "\f11e"; }
-
-.icon-terminal:before { content: "\f120"; }
-.icon-code:before { content: "\f121"; }
-.icon-reply-all:before, { content: "\f122"; }
-.icon-mail-reply-all:before { content: "\f122"; }
-.icon-star-half-full:before,
-.icon-star-half-empty:before { content: "\f123"; }
-.icon-location-arrow:before { content: "\f124"; }
-.icon-crop:before { content: "\f125"; }
-.icon-code-fork:before { content: "\f126"; }
-.icon-unlink:before { content: "\f127"; }
-.icon-question:before { content: "\f128"; }
-.icon-info:before { content: "\f129"; }
-.icon-exclamation:before { content: "\f12a"; }
-.icon-superscript:before { content: "\f12b"; }
-.icon-subscript:before { content: "\f12c"; }
-.icon-eraser:before { content: "\f12d"; }
-.icon-puzzle-piece:before { content: "\f12e"; }
-
-.icon-microphone:before { content: "\f130"; }
-.icon-microphone-off:before { content: "\f131"; }
-.icon-shield:before { content: "\f132"; }
-.icon-calendar-empty:before { content: "\f133"; }
-.icon-fire-extinguisher:before { content: "\f134"; }
-.icon-rocket:before { content: "\f135"; }
-.icon-maxcdn:before { content: "\f136"; }
-.icon-chevron-sign-left:before { content: "\f137"; }
-.icon-chevron-sign-right:before { content: "\f138"; }
-.icon-chevron-sign-up:before { content: "\f139"; }
-.icon-chevron-sign-down:before { content: "\f13a"; }
-.icon-html5:before { content: "\f13b"; }
-.icon-css3:before { content: "\f13c"; }
-.icon-anchor:before { content: "\f13d"; }
-.icon-unlock-alt:before { content: "\f13e"; }
-
-.icon-bullseye:before { content: "\f140"; }
-.icon-ellipsis-horizontal:before { content: "\f141"; }
-.icon-ellipsis-vertical:before { content: "\f142"; }
-.icon-rss-sign:before { content: "\f143"; }
-.icon-play-sign:before { content: "\f144"; }
-.icon-ticket:before { content: "\f145"; }
-.icon-minus-sign-alt:before { content: "\f146"; }
-.icon-check-minus:before { content: "\f147"; }
-.icon-level-up:before { content: "\f148"; }
-.icon-level-down:before { content: "\f149"; }
-.icon-check-sign:before { content: "\f14a"; }
-.icon-edit-sign:before { content: "\f14b"; }
-.icon-external-link-sign:before { content: "\f14c"; }
-.icon-share-sign:before { content: "\f14d"; }
diff --git a/app/assets/stylesheets/fontawesome/mixins.less b/app/assets/stylesheets/fontawesome/mixins.less
deleted file mode 100644
index 4f8858e..0000000
--- a/app/assets/stylesheets/fontawesome/mixins.less
+++ /dev/null
@@ -1,34 +0,0 @@
-// Mixins
-// --------------------------
-
-.border-radius(@radius) {
- -webkit-border-radius: @radius;
- -moz-border-radius: @radius;
- border-radius: @radius;
-}
-
-.icon-stack(@width: 2em, @height: 2em, @top-font-size: 1em, @base-font-size: 2em) {
- .icon-stack {
- position: relative;
- display: inline-block;
- width: @width;
- height: @height;
- line-height: @width;
- vertical-align: -35%;
- [class^="icon-"],
- [class*=" icon-"] {
- display: block;
- text-align: center;
- position: absolute;
- width: 100%;
- height: 100%;
- font-size: @top-font-size;
- line-height: inherit;
- *line-height: @height;
- }
- .icon-stack-base {
- font-size: @base-font-size;
- *line-height: @height / @base-font-size;
- }
- }
-}
diff --git a/app/assets/stylesheets/fontawesome/path.less b/app/assets/stylesheets/fontawesome/path.less
deleted file mode 100644
index 8162d79..0000000
--- a/app/assets/stylesheets/fontawesome/path.less
+++ /dev/null
@@ -1,15 +0,0 @@
-/* FONT PATH
- * -------------------------- */
-
-@font-face {
- font-family: 'FontAwesome';
- src: url('@{FontAwesomePath}/fontawesome-webfont.eot?v=@{FontAwesomeVersion}');
- src: url('@{FontAwesomePath}/fontawesome-webfont.eot?#iefix&v=@{FontAwesomeVersion}') format('embedded-opentype'),
- url('@{FontAwesomePath}/fontawesome-webfont.woff?v=@{FontAwesomeVersion}') format('woff'),
- url('@{FontAwesomePath}/fontawesome-webfont.ttf?v=@{FontAwesomeVersion}') format('truetype'),
- url('@{FontAwesomePath}/fontawesome-webfont.svg#fontawesomeregular?v=@{FontAwesomeVersion}') format('svg');
-// src: url('@{FontAwesomePath}/FontAwesome.otf') format('opentype'); // used when developing fonts
-
- font-weight: normal;
- font-style: normal;
-}
diff --git a/app/assets/stylesheets/fontawesome/variables.less b/app/assets/stylesheets/fontawesome/variables.less
deleted file mode 100644
index 649decc..0000000
--- a/app/assets/stylesheets/fontawesome/variables.less
+++ /dev/null
@@ -1,9 +0,0 @@
-// Variables
-// --------------------------
-
-@FontAwesomePath: "/fonts";
-@FontAwesomeVersion: "3.1.0";
-@borderColor: #eee;
-@iconMuted: #eee;
-@iconLight: #fff;
-@iconDark: #333;
\ No newline at end of file
diff --git a/app/assets/stylesheets/manager.scss b/app/assets/stylesheets/manager.scss
new file mode 100644
index 0000000..8aae1f4
--- /dev/null
+++ b/app/assets/stylesheets/manager.scss
@@ -0,0 +1,209 @@
+/* manager.css */
+#manager_box_place{
+ position:fixed;
+ height:0;
+ width:100%;
+ z-index:1500;
+ top:0px;
+ margin:0px;
+ padding:0px;
+ display:none;
+
+}
+#manager_box{
+ position:relative;
+ width:98%;
+ height:98%;
+ overflow:auto;
+
+ margin:auto;
+ margin-top:0px;
+
+ background:white;
+
+ box-shadow: rgba(0,0,0,0.8) 1px 1px 50px;
+
+
+
+
+}
+
+#manager_box_place.manager_box_place_active{
+ height:95%;
+
+
+}
+
+
+
+
+
+
+
+
+
+#image_files .image_file .img {
+ text-align:center;
+ width:150px;
+ height:150px;
+ margin:0px;
+
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ -moz-background-size: contain;
+ -webkit-background-size: contain;
+
+
+}
+
+
+#image_files .image_file .name {
+
+ padding:4px 0px 2px 0px;
+ font-size:10px;
+ text-align:center;
+
+}
+
+#image_files .image_file {
+ float:left;
+ padding:8px;
+ margin:2px;
+ border:4px solid white;
+
+ /* webkit */
+ -webkit-transition-property: background-color;
+ -webkit-transition-duration: 0.5s;
+
+ /* Firefox */
+ -moz-transition-property: background-color;
+ -moz-transition-duration: 0.5s;
+
+ /* standardisé */
+ transition-property: background-color;
+ transition-duration: 0.5s;
+
+
+
+}
+
+#image_files .image_file.active {
+
+ background-color: rgba(46,119,187,0.3);
+
+}
+
+
+
+
+
+
+
+/* Aperçu des images */
+
+#image_files_navbar{
+left:300px;
+background:rgba(247,245,246,0.9);
+}
+
+#image_files_big_container{
+
+ position:absolute;
+ top:0px;
+ left:0px;
+ bottom:0px;
+ right:0px;
+
+
+
+
+
+ #image_files_container{
+
+ position:absolute;
+ top:0px;
+ left:300px;
+ bottom:0px;
+ right:0px;
+ overflow:auto;
+ background:white;
+
+ padding:20px;
+ padding-bottom:60px;
+ }
+ #albums_navbar{
+ position:absolute;
+
+ width:299px;
+ bottom:0px;
+ left:0px;
+ border-top:1px solid rgba(191,191,191,1);
+ height:51px;
+ background:rgba(220,220,220,1);
+ a{
+ color:#5e5e5e;
+ font-size:1.5em;
+ position:absolute;
+ top:10px;
+
+ }
+ #add_album{
+ left:10px;
+ }
+
+ #edit_current_album{
+
+ right:10px;
+ }
+
+ #remove_current_album{
+
+ right:50px;
+ }
+ }
+
+ #albums{
+ padding-bottom:60px;
+ position:absolute;
+ top:0px;
+ width:300px;
+ bottom:0px;
+ left:0px;
+ overflow:auto;
+ background:rgba(230,230,230,1);
+ border-right:1px solid rgba(191,191,191,1);
+
+
+
+ ul{
+ padding-top: 1.2em;
+ li{
+ border-top:1px solid rgba(191,191,191,0.5) ;
+ position:static;
+
+
+ a{
+ position:static;
+ color:rgba(0,0,0,0.8);
+ &:hover, &.active{
+ background:rgba(220,220,220,1);
+
+ }
+ }
+
+ #edit_current_album{
+ position:absolute;
+ top:10px;
+ }
+
+ }
+
+
+ }
+
+ }
+
+
+}
+
diff --git a/app/assets/stylesheets/pane_hover.scss b/app/assets/stylesheets/pane_hover.scss
new file mode 100644
index 0000000..dc6b3f1
--- /dev/null
+++ b/app/assets/stylesheets/pane_hover.scss
@@ -0,0 +1,55 @@
+
+/* pane_hover */
+#qi_pane_hover{
+ position:fixed;
+ top:40px;
+ left:0px;
+ bottom:0px;
+ right:0px;
+ z-index:100;
+
+
+ .actions{
+ position:absolute;
+ bottom:0px;
+ left:0px;
+ right:0px;
+ text-align:right;
+ padding:5px;
+ border-top :1px solid rgba(127,127,127,0.2);
+
+
+ }
+
+
+}
+
+#qi_pane_hover #qi_pane_hover_content{
+ margin:auto;
+ position:relative;
+ max-width:100%;
+ max-height:90%;
+ background:white;
+ background: #f8f8f8;
+
+ box-shadow: rgba(0,0,0,0.7) 0px 0px 50px;
+
+
+
+
+ display:none;
+
+}
+
+#qi_pane_hover .content{
+
+ position:absolute;
+ top:0px;
+ right:0px;
+ left:0px;
+ bottom:37px;
+ overflow:auto;
+ padding:10px;
+
+
+}
diff --git a/app/assets/stylesheets/public.less b/app/assets/stylesheets/public.scss
similarity index 93%
rename from app/assets/stylesheets/public.less
rename to app/assets/stylesheets/public.scss
index 0ec4121..db7bd88 100644
--- a/app/assets/stylesheets/public.less
+++ b/app/assets/stylesheets/public.scss
@@ -1,15 +1,19 @@
@import "shared/formtastic";
-@import "public/framework/bootstrap.less";
+// Core variables and mixins
+@import "bootstrap/bootstrap";
// Font Awesome
-@import "fontawesome/font-awesome";
+//@import "fontawesome/font-awesome";
body{
-
+img{
+
+max-width:100%;
+}
width:100%;
height:100%;
margin : 0px;
@@ -24,6 +28,9 @@ h1, h2, h3, h4, h5{
font-weight:600;
text-align:left;
line-height:normal;
+
+margin: 10px 0;
+
}
h1{
@@ -161,7 +168,7 @@ font-size:1.2em;
#main{
text-align:justify;
clear:both;
- margin:10px 0;
+ margin:10px -10px;
p{
margin-bottom: 18px;
@@ -280,7 +287,7 @@ font-size:1.2em;
&:hover{
font-weight:bold;
color:white;
- text-decoration:none,
+ text-decoration:none;
}
}
@@ -328,3 +335,8 @@ border:0;
}
}
+
+ul, ol{
+padding: 0;
+margin: 0 0 10px 25px;
+}
diff --git a/app/assets/stylesheets/redactor.css b/app/assets/stylesheets/redactor.css
new file mode 100755
index 0000000..718781c
--- /dev/null
+++ b/app/assets/stylesheets/redactor.css
@@ -0,0 +1,817 @@
+/*
+ Icon font
+*/
+@font-face {
+ font-family: 'RedactorFont';
+ src: url('redactor-font.eot');
+}
+@font-face {
+ font-family: 'RedactorFont';
+ src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggi/NUAAAC8AAAAYGNtYXAaVcx2AAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zm8dIFkAAAFwAAATSGhlYWQACVb9AAAUuAAAADZoaGVhA+ECBQAAFPAAAAAkaG10eEEBA94AABUUAAAAkGxvY2FVlFE8AAAVpAAAAEptYXhwAC8AkgAAFfAAAAAgbmFtZRHEcG0AABYQAAABZnBvc3QAAwAAAAAXeAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmHwHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYf//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAwAAACUCAAGSAAQACQANAAA3EQURBQEFEQURATUXBwACAP4AAdv+SgG2/tySkiUBbgH+lAEBSgH+3AEBJv7/3G9sAAAGAAAASQIAAW4ABAAJAA4AEwAYAB0AABMhFSE1FSEVITUVIRUhNSczFSM1FTMVIzUVMxUjNZIBbv6SAW7+kgFu/pKSSUlJSUlJAW5JSW5JSW5JSdxJSW5JSW5JSQAAAAACAAAAJQH3AZIAFgAuAAAlLgMnBzIuAic+AyMXNh4CByUnMg4CBx4DIxcnHgMXNi4CBwH3Dik/XUABAR04Vjg+WDUYAQFNeEcZEv7MAQENHDMlHzIfEQEBASZUTDYHCSBIZj4lGCQaEARqFi5HLzJFKhJqDC1RZSzVPQoWIxkbJBQID0wCCQ4VDxo4KA8PAAACAG4AJQGSAZIABAAzAAA3IQchJzceAzMyPgI3PgMnNyMXDgMHDgMjIi4CJy4DNycjBx4DF24BJQH+3QFABRIUGg0QGBUQCAYKBgQBAUABAQEEBAQCCAgKBQYJCQcEAgUCAwEBPwEBAwcJCEkkJD8HCgYEBAYKBwcRFRkPtcMGCQkHAwMFAwEBAwUDAwcJCQbDtQ8ZFREHAAUAAP//AgABtwAGAA4AFgBHAF8AAAEzFTMVIzUfAQc1IzUzNS8BNxUzFSMVFx4DFRwBDgEHDgMHMh4CFx4DHwEjJzwBJjQjLgMrARUjNTMyHgIXBzMyPgI3PgM1NC4CJy4DKwEVAUkjS24mkZFvb96RkW9vDAMFAwECAwICBQUGBAECAgIBAQICAgEbIBMBAQIEBQUCCh0qCAwKCQM3DgMFBQMCAQIBAQEBAgECAwQGAw4BtpYgtv9cXEolSUhcXEklSlUDCAoNBwQJBwcCAwUDAgEBAQIBAQMEBANCLgEBAQIGBwYCSLYBAwUDRAECAgECBAQGAwQFBQQBAgIBATIAAAAAAwBtAAABkgGTAAMADAARAAAlIzcXBzM3MxczAyMDFyEVITUBI0YjI7ZKF2MXSmVbZQEBJP7c5nh4eUlJASb+2iRJSQAKAAAAJQIAAZIABAAJAA4AEwAYAB0AIgAnACwAMQAANxEFEQU3FzUHFTU3NScVJwcVFzUVJxU3NRUHFRc1NxUXNQclBxUXNRUnFTc1FQcVFzUAAgD+ALeSkpKSJW1tbW1tbSWSkgEkbW1tbW1tJQFuAf6UASUBSgFIbQFIAUq4AUgBSm8BSgFIbQFIAUrbSAFKAQEBSAFKbwFKAUhtAUgBSgAAAAIACQAlAgABkgAWAC4AACUOAxU1DgMHJj4CFzU0HgIXBT4DNxU1FD4CNy4DNRUmDgIXAgA5VTkcQVxAKA8RGEh3Thc2Vz/+PAY3S1UlECAxICYyHQw9Z0chCt8wRi8VAWsFDxsjGS1kUiwLaQETKUYxYBAUDwgDTRABCRMlGhoiFwkBPhAQJzkZAAAAAgBJAEkBtwFuAEcAjwAAAQ4DFRQeAhceAxc+Azc+AzU0LgInLgMHJg4CBwYiBiYHNAYmIicwLgE0NTQ+Ajc+Azc1DgMHJw4DFRQeAhceAxc+Azc+AzU0LgInLgMHJg4CBwYiBiYVJgYmIjUiJjQmNTQ+Ajc+Azc1DgMHATkJDQkEAwYKBgcOEBAJCA4NDAUGCAUDAwQHBQUKCgwGBQoICAMBAgIBAQEBAQEBAQMGCgYGDxITCxMhHBYJzQkNCQQDBwkHBg4QEQgIDg0MBgUIBQMCBQcFBAoLDAYFCQkIAwECAgEBAQEBAQEBAwcJBgcPERQLEyEcFwkBIgwYHBsQCxgUEgcICwgDAQECBggGBQ0MDwYIDA0KBgUIBAQBAQICBQECAgEBAQECAQQCBQEKEhQRCggQDAwDFwgQFBQNAQwYHBsQCxgUEgcICwgDAQECBggGBQ0MDwYIDA0KBgUIBAQBAQICBQECAgEBAQECAQQCBQEKEhQRCggQDAwDFwgQFBQNAAT//wBJAgABbgAEAAkADgASAAATIRUhNRchFSE1FSEVITUHNQcXAAIA/gC3AUn+twFJ/rclk5MBbklJbklJbklJSbdcWwAAAAUAAABJAgABbgAEAAkADgAaAG0AABMhFSE1FSEVITUVIRUhNSczNSM1IwcVNxUjFRc+Azc+Azc0PgE0NTQuAicuAyMiBioBByIOAiMVPgM3Mj4BMjM6AR4BFx4CFBUcAQYUBw4DBw4DDwEVMzUjPgM3MZIBbv6SAW7+kgFu/pKNRBgUFhYYIAUHBQMBAgICAQEBAQEDBAICBgcHBQEEAwQCAgMEBAICBAQDAgIDAwMCAgMDAwEBAgEBAQEBAgICAQQGCQULRC0BAwQEAgFuSUluSUluSUlrFF0GFAZJFJEFBwYEAQIDBAMBAgMDAwIDBwUFAgIEAgEBAQEBAhUBAgIBAQEBAQIBAQIDBAIBAgMCAQICAwMCAQUHCQYNExQBBAMFAgADAAAASQIAAW4ALAAxAGwAACUiLgInNTMeAzMyPgI1NC4CIyIOAgcjNT4DMzIeAhUUDgIjJzMVIzUnIg4CByMVDgMVFB4CFxUzHgMzMj4CNzMVDgMjIi4CNTQ+AjMyHgIXFSMuAyMBbgoUEhEIHgUKCwsGEyEZDg4ZIRMGCwsKBR4IERIUCh41KBcXKDUet5KSJQYLCwoFHgQHBQICBQcEHgUKCwsGBgsLCgUeCBESFAoeNSgXFyg1HgoUEhEIHgUKCwsGSQMGBwU0AgQDAQ0XHhESHhcNAQMEAjQFBwYDFyg1Hx41KBe3SUkvAQMEAhgFCw0OBwcNDQsGFwIEAwEBAwQCNAUHBgMXKDUeHzUoFwMGBwU0AgQDAQAAAAEAAAC3AgABAAAEAAATIRUhNQACAP4AAQBJSQABAJIASQGSAZIADAAAAQ8CFzcHNxc3DwEXAQcpQQvBC0ApQAvBC0EBWdYBOAE6AdgBOgE4AQAAAAQAAABJAgABbgAEAAkADgASAAATIRUhNRchFSE1FSEVITUHNRcHAAIA/gC3AUn+twFJ/re3k5MBbklJbklJbklJSbdcWwAAAAMAAAAlAgABkgAEAAkAEgAANxEFEQUBBREFEQc/ARcVJTU3FwACAP4AAdv+SgG2tiQwPv6Sbm4lAW4B/pQBAUoB/twBASa4AV5eSgFIk5MABAAlAAAB2wG3AAMAGgAeADUAAAEVJzMHHgIGDwEOAS4BJy4BNDY/AT4BHgEXARcnFTceATI2PwE+AS4BJy4CBg8BDgEeARcB29vbKgMDAQICcwIGBgYCAwMBAnQCBQYGAv5029sqAwYGBQJzAgEBAgMCBgYGAnICAgEDAgG33NwrAgYGBgJzAgEBAgMDBQYGAnMCAQECA/51AdvaKgMDAQJzAgUGBgMCAwECAnMCBQYGAgAABAAA/9sCAAHbAAMAGgAeADUAACU1Fwc3LgI2PwE+AR4BFx4BFAYPAQ4BIiYnBycXNQcuASIGDwEOAR4BFx4CNj8BPgEuAScBJdvbKgMDAQICcwIGBgYCAwMBAnQCBQYGAnTb2yoDBgYFAnMCAQECAwIGBgYCcgICAQMC/9zbASwCBgYGAnICAgEDAgMGBgUCcwIBAwN1AdzbKgMDAQJzAgUGBgMCAwECAnICBgYGAgABAG4AJQFuAZIAEgAAJREjESM1Ii4CNTQ+AjsBESMBSSRKFigeEREeKBaTJSUBSf63khEeKBcWKB4R/pMAAAAAAwAlAAEB3AG2AAoAVwB4AAAlMwcnMzUjNxcjFQcOAwcOAyMiLgInLgM1ND4CNz4DOwE1NC4CJy4DIyIOAgcOAwc1PgM3PgIyMzIeAhceAx0BIzU1IyIOAgcOAxUUHgIXHgMzMj4CNz4DPQEBkkpcXEpKXFxK6wIGBgcEAwgICQUIDw4LBQUHBQIDBQkGBQ8SFAwlAQMDAgMFBwgFBAoJCQQFCQkJBQQJCQkEBQkKCQUNFRENBQUIBQI0FQgMCggDAwUDAQECAwICBQUHAwUJCQcCAwUCApKRkZORkZMHBAYFBQECAwIBAgUHBQULDQ8JCRANCwQFBgUCCQMGBQQCAgICAQEBAgEBAwQFAy8CAwMCAQEBAQIFCAUGDhIXDXgYSwECAwICBgYIBQQGBgUCAgMCAQIEBgQECgsOBwQAAAAEACUASgHbAW4AAwAMAC0AegAANyM3FwczNzMXMwMjAyUVFA4CBw4DIyIuAicuAzU0PgI3PgM7ATcuAyMqAQ4BBw4DBxU+Azc+AzMyHgIXHgMdASMiDgIHDgMVFB4CFx4DMzI+Ajc+AzcVMzU0LgInrjUbGok4EUsSOE1ETQF/AQMFAwMHCQoFBAYGBQIDAwIBAgMEAwMJCw0IFiIFDhIWDQYKCgoFBAoJCgQFCgoJBQUJCgoFBAkHBgIDAwMBJg0WEw8GBgkGAwIFCAUFDA4QCQUJCQgEBAcHBgI3AgUIBsV1dXZHRwEf/uFlBAcOCwsEBAYEAwICAwICBQYHAwUJBwUCAgMCAWIFCAYCAQEBAQMCBAIwAwUEAwIBAgEBAQIDAQIEBgYDCQMEBwQFCw4QCgkPDgsFBQcFAgEBAwICBQUHAxh7DhcTDwUAAAIASQBJAbcBkwAEAIEAABMhFSE1Fx4DFx4DFRQOAgcOAyMiLgInLgMnFR4DFx4DMzI+Ajc+AzU0LgInLgMvAS4DJy4DNTQ+Ajc+AzMyHgIXHgMXNS4DJy4DIyIOAgcOAxUUHgIXHgMfAUkBbv6SvwQIBgYCAgMDAQIDBQQDCAkLBgYNDAwGBg0NDQYGCwwNBgYNDAwHDxoXEggHCwgDAgUHBAUMDxIKHAcNCQcDAgMDAQIDBQMDCAkKBgYLCgsGBQsLCgYGCwwLBgYLDAsGDBcUEQcICwcDAgQHBAUMERUNIAEAJSUxAgMFBAMDBgYHAwUICAYDAgQDAQECAwMCBQcIBEEDBAUDAgECAQEDBgkGBQ8SFQwJEA8NBgYKCggDCwIFBQQDAgUFBgMFBwcFAwIDAwEBAgMCAgQGBgM9AgUDBAEBAgEBAwcJBgYPERMLCA8ODAQFCgoJBQsAAAQAAABJAgABbgAEAAkADgATAAA/ARcHJxc3FwcnJScHFzcXJwcXNwAltiO4AbYluCMB/yO4JbYBuCO2Jdsdkh6TAZQekhwBHZIekwGUHpIcAAAAAAUAAP/bAgAB2wAEAAkADgATABgAABcRIREhASERIREHITUhFRUhNSEVFSE1IRUAAgD+AAHb/koBtkn+3AEk/twBJP7cASQlAgD+AAHc/kkBt5JJSW5JSW5JSQAAAwCTAEkBbQGSABcALwBbAAA3Mh4CFx4DFwYUDgEHDgMrATczNzIeAhceAhQXBhQOAQcOAysBNzMDMzI+Ajc+Ayc2LgInLgMnPgM3PgMnNi4CJy4DKwED+AcNCQkDBAMEAQEBBAQEAgkKDQcqASgBBQsIBwIDAwQBAQQCBAEICAsFKgEoZGQRGRgRCAYLBgQBAQMEBwQGCg8OCggMDQgFAwcDAwEBBAYLBgcQFBcOZAHeAQMEAwMICQwHBgsJCAIDBAMBYYECAgMDAgYHCQUFCQcGAgIEAgFN/uoDBQgGBQ4RFQsKEQ8NBgUJBgQBAQMFBwUECwwOCAsSDw0FBggFAv63AAADACUAAAHbAbcABAANABEAADcRIREhEyMDMzczFzMDBxcjNyUBtv5K/URMOBBLETdLIho0GgABt/5JAW7+20hIASU1eHgAAAACAEIAHwG8AZkAIQBLAAAlBycOAS4BJwcXBw4BIiYvAS4BNDY/AT4BMhYfAR4BFAYHJy4BIgYPAQ4BFBYXHgE+AT8BLgMnLgI2PwE+AhYXBxc3PgE0JicBvJQEBQsMCwYhHg8PJygnDw8PDw8P1w8nKCcPDw8QEA8lCxscHAvFCwwLCgsbHRsLJwMFBgUCCgwDBQhSBg8QEgl+JoYLCwoL9pQEAQECAwMgHg8PDw8PDxAmKCcP1w8QEA8PDycoJw9+CwoLC8YLGx0bCwoLAQsLJgIDBAUCChcXFQhSBgYBBAV9JYYLHBwbCwAAAAMAAABJAgABbgAEAAkADgAAEyEVITUXIRUhNRczFSM1AAIA/gCSAW7+kpPb2wFuSUluSUluSUkAAwAAAEkCAAFuAAQACQAOAAATIRUhNRUhFSE1FTMVIzUAAgD+AAFt/pPc3AFuSUluSUluSUkAAAADAAAASQIAAW4ABAAJAA4AABMhFSE1FSEVITUVIRUhNQAB//4BAf/+AQIA/gABbklJbklJbklJAAMAAABJAgABbgAEAAkADgAAEyEHIScHIRchNxchByEnbgElAf7dAW0B/wH9/wFtASUB/t0BAW5JSW5JSW5JSQAGAAAAJwIAAZUACAANABQAGAAdACEAADc1IxEhFTMRIQEhFSE1FyMVIRUhNQcjNxcXITUhFScXIzdJSQG3Sf5JAUn+kwFtSiX+twFu27hcXG3+2wElKSlJICdJASVK/twBSdzcSbcl3EltbSUlJW5JSQAAAAEAAAABAADCHXSvXw889QALAgAAAAAAz3WLJQAAAADPdYsl////2wIAAdsAAAAIAAIAAAAAAAAAAQAAAeD/4AAAAgD//wAAAgAAAQAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAABAAAAAgAAAAIAAAACAAAAAgAAbgIAAAACAABtAgAAAAIAAAkCAABJAgD//wIAAAACAAAAAgAAAAIAAJICAAAAAgAAAAIAACUCAAAAAgAAbgIAACUCAAAlAgAASQIAAAACAAAAAgAAkwIAACUCAABCAgAAAAIAAAACAAAAAgAAAAIAAAAAAAAAAAoAFAAeAEAAcAC4AQQBhgGoAfoCQAMCAyYDuARGBFQEcASUBLwFFgVuBY4GLgbUB4IHrAfaCFwIgAj2CRIJLglKCWoJpAAAAAEAAAAkAJAACgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAYAAAAAQAAAAAAAgAOAGoAAQAAAAAAAwAYAC4AAQAAAAAABAAYAHgAAQAAAAAABQAWABgAAQAAAAAABgAMAEYAAQAAAAAACgAoAJAAAwABBAkAAQAYAAAAAwABBAkAAgAOAGoAAwABBAkAAwAYAC4AAwABBAkABAAYAHgAAwABBAkABQAWABgAAwABBAkABgAYAFIAAwABBAkACgAoAJAAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQAVgBlAHIAcwBpAG8AbgAgADEALgAwAFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0UmVkYWN0b3JGb250AFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0AFIAZQBnAHUAbABhAHIAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AABIoAAoAAAAAEeAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAADgEAAA4Bg0Rie09TLzIAAA74AAAAYAAAAGAIIvzVY21hcAAAD1gAAABMAAAATBpVzHZnYXNwAAAPpAAAAAgAAAAIAAAAEGhlYWQAAA+sAAAANgAAADYACVb9aGhlYQAAD+QAAAAkAAAAJAPhAgVobXR4AAAQCAAAAJAAAACQQQED3m1heHAAABCYAAAABgAAAAYAJFAAbmFtZQAAEKAAAAFmAAABZhHEcG1wb3N0AAASCAAAACAAAAAgAAMAAAEABAQAAQEBDVJlZGFjdG9yRm9udAABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeKZviU+HQFHQAAAT8PHQAAAUQRHQAAAAkdAAAN+BIAJQEBDRkbHSAlKi80OT5DSE1SV1xhZmtwdXp/hImOk5idoqessba7wFJlZGFjdG9yRm9udFJlZGFjdG9yRm9udHUwdTF1MjB1RTYwMHVFNjAxdUU2MDJ1RTYwM3VFNjA0dUU2MDV1RTYwNnVFNjA3dUU2MDh1RTYwOXVFNjBBdUU2MEJ1RTYwQ3VFNjBEdUU2MEV1RTYwRnVFNjEwdUU2MTF1RTYxMnVFNjEzdUU2MTR1RTYxNXVFNjE2dUU2MTd1RTYxOHVFNjE5dUU2MUF1RTYxQnVFNjFDdUU2MUR1RTYxRXVFNjFGAAACAYkAIgAkAgABAAQABwAKAA0AQQCYAPEBSQH6Ai8CxwMhA98EGwTXBYEFkQW0BfEGLwagBxEHOgf0CLUJaQmsCfwKhAq5C0QLdAuiC9AMAQxo/JQO/JQO/JQO+5QOi7AVi/gB+JSLi/wB/JSLBfhv990V/EqLi/u5+EqLi/e5Bfu4+5QVi/dv9yb7Avsm+wEFDvcm+AIV+AKLi0L8AouL1AWL+wIV+AKLi0L8AouL1AWL+wIV+AKLi0L8AouL1AX7JvdwFdSLi0JCi4vUBYv7AhXUi4tCQouL1AWL+wIV1IuLQkKLi9QFDviLsBVky0yq+0KWCIshBYuLQMb7LPcT9z33GsW4i4sIiyEF92Wr9wT7QV77Cgj7yfdpFYvIBYuLb3ImSOFBtnqLiwiLfIvXBe6F9yJ7nGSl0PsO6Ps2YwgO9wLUFfe4i4tn+7iLi68FysoVnHmngrGLsounlJydnJ2Up4uyCIv3SUyLi/tXBYt8hoCDg4ODgId8i32Lf4+Dk4OTh5aLmgiL91dLi4v7SQWLZJRvnXkIDvfd+EoVrouL+yrWi4tr+wKLi/dKBbH7kxX3JS/7JS+L1fsDi4uw9wOLi9QF+3LTFfsl5/cl54tC9wOLi2b7A4uLQQWXNhWTg499i3iLf4mBhoSGg4SHgYmOio6KjYiNiI6GjoQIpklri3i5BYuMio2KjYaZhZKEiwiBi4tDbouL90q1iwWfi5mHk4MIVEcVmYsFk4uRjY+Pjo+NkYuUi5SJkoiOh4+FjYOLCH2Li1kFDve393oVRYuu9wyu+wwF+0r7DRXVi6LU7ouiQtWLJve6MIsm+7oFjGcV97iLi0L7uIuL1AUOi7AVi/gB+JSLi/wB/JSLBfdLrxX3JouL1Psmi4tCBYv3AhX3JouL1Psmi4tCBWb3SxX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBbD3cBWLQvcmi4vU+yaLBfe4ixX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBQ74lPdzFfss+xNAUIuLCIv1BftCgExsZEte9wr3BPdB92VrCIv1BYuLxV73PfsaCPxYLBWcsvcim+6RCIs/i5oFi4u2nOHVJs5vpIuLCItOBfs2s/sOLqVGCA73zfe2FXNsgGiLY4tpk3Ccd513n4Gji6CLnJKZmpqakpyLn4uehZt+mH+ZfJJ7i32LgIeChQiIiYmKiYuKi4mMioyKjoqPi5GLpJOknKOco6KcqJYIi6EFWXhlcnRrCPthixV0bH9oi2OLaZNwnXecd6CBoougi5ySmpqZmpKci5+LnoWbfph/mX2Seot+i3+IgoQIiImJioqLiYuKjIqMiY6Kj4uRi6SUpJujnKOinKmWCIuhBVh4ZnJzawgOi/gCFfiUi4tC/JSLi9QF90v7AhX33YuLQvvdi4vUBYv7AhX33YuLQvvdi4vUBWZCFYv3S/snL/cnMAUO9yb4AhX4AouLQvwCi4vUBYv7AhX4AouLQvwCi4vUBYv7AhX4AouLQvwCi4vUBfsh9hXPi4ufc4uL6HeLdYWLd6GRi0Jzi4t3Bav7JRWXl5KTjY6PkI2PjY+Mj4yPi5CLlIiThJCFkYKOf4uHi4aKhoqGioaKhokIi3YFkI6QjZCNkIyPjI+LkIuPio6IjoiMh4uGi4iLiImIiYeJh4eHiIiDgX18CIB+i3jPi4ufXosFjo+QkJGRCIuLBQ74AtQVcItyk3aYCIu/qYsFmIWZh5uLvYu0sIu5i7pisFmLe4t9h36FCG2Li78FoJikk6aL3IvMSYs6iztKSTqLCPtL90sV9yaLi0L7JouL1AVmuhV8i3yHfoUIbYuLcwWAfYR6i3iLeZJ5ln0Ii3SpiwWYhZqHmoubi5mPmJEIqYuLVwV2fnKDcIs6i0rNi9uL3MzN3Iumi6SDoH4Ii1dtiwV+kX2Pe4sIDov3lBX4lIuLQvyUi4vUBQ73m/ftFWL7a0qLgFL3VYuWxEuLtPdry4uWxPtVi4BSzIsFDov4AhX4lIuLQvyUi4vUBfdL+wIV992Li0L73YuL1AWL+wIV992Li0L73YuL1AX7S0IVi/dL9ycv+ycwBQ6LsBWL+AH4lIuL/AH8lIsF+G/33RX8SouL+7n4SouL97kF+0r7SxWvi7vqySyLQvwCi4vU9wL3JvcC+yYFDvhv+EsVi/tw+2/3cPdviwVhYBWShIyChoUI+wf7BwWFhoKMhJKEkoqUkJEI9wj3BwWQkJWKkYQI/CD8HxX3b4r7b/dvi/tuBbW1FZKElYqQkAj3B/cHBZCQipWEkoSRgo2FhQj7BvsHBYWGjYGRhQgO97n3kxWL93D3b/tv+2+KBbW3FYSSipSQkQj3B/cGBZGRlIqShJKEjIGGhgj7CPsHBYaGgYyFkgj7CPsJFftvjPdv+3CL928FYWEVhJKBjIaGCPsH+wcFhoaMgZKEkoSUipGRCPcG9wYFkZGJlIWSCA733bAVi/fdZ4uL+91Bi4v3JgVPi1q8i8iLx7y8x4sI9yeLi/wBZosFDvgm9yYV1Ysv+yUv9yXVi4v3J0GL5/cl5/slQYuL+ycF+3+EFYWCgoSBhoGGgIh/i3WLeZF+mH6XhZ2Looujkp2blpqXopGriwiwi4uUBYuUiJKFj4SQgo1/i3+Lf4l/iH+If4V+hAiLugWWkJeOl46XjZiMmIusi6KEmH6ZfZFyi2gIi/sMV4uLowWL1hV2iwV3i32IhIaDhoeCi36LgY6EkIWQhpOIlIuZi5aQkpaTlo+ai58Ii48FDvdC91kVVoum9wml+wkF+x37ChXDi5zS1oudRMOLPvezR4s++7MF+BPwFYuHBYt3h3uDgIOAf4V9i4GLg46GkYWRiJOLlIuYj5WTkJSQmY6giwihiwWt7RV9mXOSaYt8i36Kfol/iH6Hf4YIi1sFmJOYkJiPl46YjZmLl4uViJGHkoaOhIuCCIuCZYsFaYtyhXt/e3+DeItyi3SReZl+mH6ehaOLmIuXjZWQlpCTk5KUCItzwouL9w8Fi6+EpX2ZCA7U95QV+AKLi2b8AouLsAX3U1oVloeUhZGEkYSOgouCi36GgYKEgoR/iHuLe4t6jnuRepB6lHqXCItKBZqEm4Wch5yIm4mci7OLqZOfm5+alKOLq4ujhZ9/mn6bd5dwlAhvlgV3kX6ShZGFkIiTi5OLl4+UlJGTkZeOm4uai5mImoaZhpqEmYIIi8gFfJF8kHuPfI58jXuLaYtxg3h6d3uCdItui3WQeZd+l32hf61+CKuABQ6L928Vr6n3S/snZ277S/cmBYuLFfdL9yevbvtL+ydnqAX4lIsVZ6n7S/snr273S/cmBYuLFftL9ydnbvdL+yevqAUOi2YVi/iU+JSLi/yU/JSLBfhv+HAV/EqLi/xL+EqLi/hLBUL7JhX7uIuL1Pe4i4tCBYv7AhX7uIuL1Pe4i4tCBYv7AhX7uIuL1Pe4i4tCBQ73jPdyFZ6LmYiUg5ODj36LeYt6h3+DhIOEfYd3iwhii4vstIsFi/cVFZuLloiShJKFjoKLfYt+iIGEhYSFgIh7iwhii4vYtIsFJvuqFfCLBbWLqJKemp2ZlKKLqoulhZ9/mn+ZeZRzjZ+NmpKVl5aXkJuLoIungqB5mHqZcJJoiwgmi4v73QUOsIsVi/hL+EqLi/xL/EqLBfeR+AIVR4s/+7nDi5vT1oucQ8KLQPe5BWlWFaX7DFeLpfcMBQ74UPeKFfso+yiHjwV9h3uNfJMIamupbXx8BWJiSYtitAh8mgVitIvNtLQI92v3awW0tM2LtGIImnwFtGKLSWJiCGb3EhVuqFyKbm4I+1n7WgVtbotcp26ob7qLqKkIsrEFg4+EkIWScKaGsJ+gCN3dBZuapIyifwj7EvsRsWb3GvcaBaiojLpuqAgOi/gCFfiUi4tC/JSLi9QF9yb7AhX4AouLQvwCi4vUBfcn+wIV92+Li0L7b4uL1AUOi/gCFfiUi4tC/JSLi9QFi/sCFfgBi4tC/AGLi9QFi/sCFfdwi4tC+3CLi9QFDov4AhX4k4uLQvyTi4vUBYv7AhX4k4uLQvyTi4vUBYv7AhX4lIuLQvyUi4vUBQ73AvgCFfe4i4tC+7iLi9QF+wL7AhX4lIuLQvyUi4vUBfcC+wIV97iLi0L7uIuL1AUO1LIVi9RCi4v3ufhLi4tB1IuL+7j8S4sF99333RX8AYuL+3D4AYuL93AF1UIVZouL+0v73YuLZvgCi4v3cAX7b0IV+0yL5/cB5/sBBfcBZhX7uYuLsPe5i4tmBWL3AhW0QkKLq9QFDviUFPiUFYsMCgAAAAADAgABkAAFAAABTAFmAAAARwFMAWYAAAD1ABkAhAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAEAAAOYfAeD/4P/gAeAAIAAAAAEAAAAAAAAAAAAAACAAAAAAAAIAAAADAAAAFAADAAEAAAAUAAQAOAAAAAoACAACAAIAAQAg5h///f//AAAAAAAg5gD//f//AAH/4xoEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAQAAhlBJsl8PPPUACwIAAAAAAM91iyUAAAAAz3WLJf///9sCAAHbAAAACAACAAAAAAAAAAEAAAHg/+AAAAIA//8AAAIAAAEAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAQAAAAIAAAACAAAAAgAAAAIAAG4CAAAAAgAAbQIAAAACAAAJAgAASQIA//8CAAAAAgAAAAIAAAACAACSAgAAAAIAAAACAAAlAgAAAAIAAG4CAAAlAgAAJQIAAEkCAAAAAgAAAAIAAJMCAAAlAgAAQgIAAAACAAAAAgAAAAIAAAACAAAAAABQAAAkAAAAAAAOAK4AAQAAAAAAAQAYAAAAAQAAAAAAAgAOAGoAAQAAAAAAAwAYAC4AAQAAAAAABAAYAHgAAQAAAAAABQAWABgAAQAAAAAABgAMAEYAAQAAAAAACgAoAJAAAwABBAkAAQAYAAAAAwABBAkAAgAOAGoAAwABBAkAAwAYAC4AAwABBAkABAAYAHgAAwABBAkABQAWABgAAwABBAkABgAYAFIAAwABBAkACgAoAJAAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQAVgBlAHIAcwBpAG8AbgAgADEALgAwAFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0UmVkYWN0b3JGb250AFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0AFIAZQBnAHUAbABhAHIAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('woff');
+ font-weight: normal;
+ font-style: normal;
+}
+/* =Selection
+-----------------------------------------------------------------------------*/
+.redactor_box ::selection {
+ background: #ffff9e;
+}
+.redactor_box ::-moz-selection {
+ background: #ffff9e;
+}
+.redactor_box img::selection {
+ background: transparent;
+}
+.redactor_box img::-moz-selection {
+ background: transparent;
+}
+/*
+ BOX
+
+.redactor_box {
+ position: relative;
+ overflow: visible;
+ background: #fff;
+}
+
+*/
+.redactor_box iframe {
+ display: block;
+ margin: 0;
+ padding: 0;
+ border: 1px solid #eee;
+}
+.redactor_box textarea {
+ position: relative;
+ display: block;
+ overflow: auto;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ outline: none;
+ border: none;
+ background-color: #222;
+ box-shadow: none;
+ color: #ccc;
+ font-size: 13px;
+ font-family: Menlo, Monaco, monospace, sans-serif;
+ resize: none;
+}
+.redactor_box textarea:focus {
+ outline: none;
+}
+.redactor_box,
+.redactor_box textarea {
+ z-index: auto !important;
+}
+.redactor_box_fullscreen {
+ z-index: 99 !important;
+}
+#redactor_modal_overlay,
+#redactor_modal,
+.redactor_dropdown {
+ z-index: 100 !important;
+}
+/*
+ AIR
+
+*/
+body .redactor_air {
+ position: absolute;
+ z-index: 502;
+}
+/*
+ FULLSCREEN
+*/
+body .redactor_box_fullscreen {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+}
+/*
+ LINK TOOLTIP
+*/
+.redactor-link-tooltip {
+ position: absolute;
+ z-index: 49999;
+ padding: 10px;
+ line-height: 1;
+ display: inline-block;
+ background-color: #000;
+ color: #555 !important;
+}
+.redactor-link-tooltip,
+.redactor-link-tooltip a {
+ font-size: 12px;
+ font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;
+}
+.redactor-link-tooltip a {
+ color: #ccc;
+ margin: 0 5px;
+ text-decoration: none;
+}
+.redactor-link-tooltip a:hover {
+ color: #fff;
+}
+/*
+ IMAGE BOX
+*/
+#redactor-image-box img {
+ width: 100%;
+}
+/*
+.redactor_editor {
+ position: relative;
+ overflow: auto;
+ margin: 0 !important;
+ padding: 10px 20px;
+ padding-bottom: 5px;
+ outline: none;
+ background: none;
+ background: #fff;
+ box-shadow: none !important;
+ white-space: normal;
+ border: 1px solid #eee;
+}
+*/
+.redactor_editor:focus {
+ outline: none;
+}
+
+.redactor_editor .redactor_placeholder {
+ color: #999 !important;
+ display: block !important;
+}
+
+/*
+ TOOLBAR
+*/
+.redactor_toolbar {
+ position: relative;
+ top: 0;
+ left: 0;
+ margin: 0 !important;
+ padding: 0 !important;
+ list-style: none !important;
+ font-size: 14px !important;
+ font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;
+ line-height: 1 !important;
+ background: #fff;
+ border: none;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ z-index: 3;
+}
+.redactor_toolbar:after {
+ content: "";
+ display: table;
+ clear: both;
+}
+.redactor_toolbar.redactor-toolbar-overflow {
+ overflow-y: auto;
+ height: 29px;
+ white-space: nowrap;
+}
+.redactor_toolbar.redactor-toolbar-external {
+ z-index: 999;
+ box-shadow: none;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+}
+body .redactor_air .redactor_toolbar {
+ padding-right: 2px !important;
+}
+.redactor_toolbar li {
+ vertical-align: top;
+ display: inline-block;
+ margin: 0 !important;
+ padding: 0 !important;
+ outline: none;
+ list-style: none !important;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.redactor_toolbar li a {
+ display: block;
+ color: #333;
+ text-align: center;
+ padding: 9px 10px;
+ outline: none;
+ border: none;
+ text-decoration: none;
+ cursor: pointer;
+ zoom: 1;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.redactor_toolbar li a:hover {
+ outline: none;
+ background-color: #1f78d8;
+ color: #fff;
+}
+.redactor_toolbar li a:hover i:before {
+ color: #fff;
+}
+.redactor_toolbar li a:active,
+.redactor_toolbar li a.redactor_act {
+ outline: none;
+ background-color: #ccc;
+ color: #444;
+}
+.redactor_toolbar li a.redactor-btn-image {
+ width: 14px;
+ height: 14px;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+.redactor_button_disabled {
+ filter: alpha(opacity=30);
+ -moz-opacity: 0.3;
+ opacity: 0.3;
+}
+.redactor_button_disabled:hover {
+ outline: none;
+ background-color: transparent !important;
+ cursor: default;
+}
+.redactor_toolbar li a.fa-redactor-btn {
+ display: inline-block;
+ padding: 9px 10px 8px 10px;
+ line-height: 1;
+}
+.redactor_toolbar.redactor-toolbar-typewriter {
+ box-shadow: none;
+ background: rgba(240, 240, 240, 0.9);
+}
+.redactor_toolbar.redactor-toolbar-typewriter li a:hover {
+ outline: none;
+ background-color: #1f78d8;
+ color: #fff;
+}
+.redactor_toolbar.redactor-toolbar-typewriter li a:active,
+.redactor_toolbar.redactor-toolbar-typewriter li a.redactor_act {
+ outline: none;
+ background-color: #ccc;
+ color: #444;
+}
+.re-icon {
+ font-family: 'RedactorFont';
+ speak: none;
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.re-icon i:before {
+ position: relative;
+ font-size: 14px;
+}
+.re-video:before {
+ content: "\e600";
+}
+.re-unorderedlist:before {
+ content: "\e601";
+}
+.re-undo:before {
+ content: "\e602";
+}
+.re-underline:before {
+ content: "\e603";
+}
+.re-textdirection:before {
+ content: "\e604";
+}
+.re-fontcolor:before {
+ content: "\e605";
+}
+.re-table:before {
+ content: "\e606";
+}
+.re-redo:before {
+ content: "\e607";
+}
+.re-quote:before {
+ content: "\e608";
+}
+.re-outdent:before {
+ content: "\e609";
+}
+.re-orderedlist:before {
+ content: "\e60a";
+}
+.re-link:before {
+ content: "\e60b";
+}
+.re-horizontalrule:before {
+ content: "\e60c";
+}
+.re-italic:before {
+ content: "\e60d";
+}
+.re-indent:before {
+ content: "\e60e";
+}
+.re-image:before {
+ content: "\e60f";
+}
+.re-fullscreen:before {
+ content: "\e610";
+}
+.re-normalscreen:before {
+ content: "\e611";
+}
+.re-formatting:before {
+ content: "\e612";
+}
+.re-fontsize:before {
+ content: "\e613";
+}
+.re-fontfamily:before {
+ content: "\e614";
+}
+.re-deleted:before {
+ content: "\e615";
+}
+.re-html:before {
+ content: "\e616";
+}
+.re-clips:before {
+ content: "\e617";
+}
+.re-bold:before {
+ content: "\e618";
+}
+.re-backcolor:before {
+ content: "\e619";
+}
+.re-file:before {
+ content: "\e61a";
+}
+.re-alignright:before {
+ content: "\e61b";
+}
+.re-alignment:before,
+.re-alignleft:before {
+ content: "\e61c";
+}
+.re-alignjustify:before {
+ content: "\e61d";
+}
+.re-aligncenter:before {
+ content: "\e61e";
+}
+.re-gallery:before {
+ content: "\e61f";
+}
+/*
+ Toolbar classes
+*/
+.redactor_format_blockquote {
+ padding-left: 10px;
+ color: #666 !important;
+ font-style: italic;
+}
+.redactor_format_pre {
+ font-family: monospace, sans-serif;
+}
+.redactor_format_h1,
+.redactor_format_h2,
+.redactor_format_h3,
+.redactor_format_h4,
+.redactor_format_h5 {
+ font-weight: bold;
+}
+.redactor_format_h1 {
+ font-size: 30px;
+ line-height: 36px;
+}
+.redactor_format_h2 {
+ font-size: 24px;
+ line-height: 36px;
+}
+.redactor_format_h3 {
+ font-size: 20px;
+ line-height: 30px;
+}
+.redactor_format_h4 {
+ font-size: 16px;
+ line-height: 26px;
+}
+.redactor_format_h5 {
+ font-size: 14px;
+ line-height: 23px;
+}
+.redactor-toolbar-typewriter .redactor_dropdown .redactor_format_h1,
+.redactor-toolbar-typewriter .redactor_dropdown .redactor_format_h2,
+.redactor-toolbar-typewriter .redactor_dropdown .redactor_format_h3,
+.redactor-toolbar-typewriter .redactor_dropdown .redactor_format_h4,
+.redactor-toolbar-typewriter .redactor_dropdown .redactor_format_h5 {
+ font-size: 1em;
+ line-height: 1.6em;
+ text-transform: uppercase;
+}
+.redactor-toolbar-typewriter .redactor_dropdown .redactor_format_h2 {
+ font-size: .85em;
+}
+/*
+ Typewriter
+*/
+.redactor_editor.redactor-editor-typewriter {
+ background: #f5f5f5 !important;
+ padding: 25px 50px !important;
+}
+.redactor_editor.redactor-editor-typewriter div,
+.redactor_editor.redactor-editor-typewriter p,
+.redactor_editor.redactor-editor-typewriter ul,
+.redactor_editor.redactor-editor-typewriter ol,
+.redactor_editor.redactor-editor-typewriter table,
+.redactor_editor.redactor-editor-typewriter dl,
+.redactor_editor.redactor-editor-typewriter blockquote,
+.redactor_editor.redactor-editor-typewriter pre,
+.redactor_editor.redactor-editor-typewriter h1,
+.redactor_editor.redactor-editor-typewriter h2,
+.redactor_editor.redactor-editor-typewriter h3,
+.redactor_editor.redactor-editor-typewriter h4,
+.redactor_editor.redactor-editor-typewriter h5,
+.redactor_editor.redactor-editor-typewriter h6 {
+ font-family: 'Courier New', 'Lucida Console', Consolas, Monaco, monospace, sans-serif;
+ font-size: 18px !important;
+ line-height: 1.5em !important;
+ margin-bottom: 1.5em !important;
+}
+.redactor_editor.redactor-editor-typewriter h2 {
+ font-size: 14px !important;
+}
+.redactor_editor.redactor-editor-typewriter h1,
+.redactor_editor.redactor-editor-typewriter h2,
+.redactor_editor.redactor-editor-typewriter h3,
+.redactor_editor.redactor-editor-typewriter h4,
+.redactor_editor.redactor-editor-typewriter h5,
+.redactor_editor.redactor-editor-typewriter h6 {
+ text-transform: uppercase;
+}
+.redactor_editor.redactor-editor-typewriter a {
+ color: #000 !important;
+ text-decoration: underline !important;
+}
+/*
+ WYM
+*/
+.redactor_editor.redactor_editor_wym {
+ padding: 10px 7px 0 7px !important;
+ background: #f6f6f6 !important;
+}
+.redactor_editor.redactor_editor_wym div,
+.redactor_editor.redactor_editor_wym p,
+.redactor_editor.redactor_editor_wym ul,
+.redactor_editor.redactor_editor_wym ol,
+.redactor_editor.redactor_editor_wym table,
+.redactor_editor.redactor_editor_wym dl,
+.redactor_editor.redactor_editor_wym pre,
+.redactor_editor.redactor_editor_wym h1,
+.redactor_editor.redactor_editor_wym h2,
+.redactor_editor.redactor_editor_wym h3,
+.redactor_editor.redactor_editor_wym h4,
+.redactor_editor.redactor_editor_wym h5,
+.redactor_editor.redactor_editor_wym h6,
+.redactor_editor.redactor_editor_wym blockquote {
+ margin-top: 0;
+ margin-bottom: 5px !important;
+ padding: 10px !important;
+ border: 1px solid #e4e4e4 !important;
+ background-color: #fff !important;
+ z-index: 0;
+}
+.redactor_editor.redactor_editor_wym blockquote:before {
+ content: '';
+}
+.redactor_editor.redactor_editor_wym img {
+ position: relative;
+ z-index: 1;
+}
+.redactor_editor.redactor_editor_wym div {
+ border: 1px dotted #aaa !important;
+}
+.redactor_editor.redactor_editor_wym pre {
+ border: 2px dashed #e4e4e4 !important;
+ background-color: #f8f8f8 !important;
+}
+.redactor_editor.redactor_editor_wym ul,
+.redactor_editor.redactor_editor_wym ol {
+ padding-left: 2em !important;
+}
+.redactor_editor.redactor_editor_wym ul li ul,
+.redactor_editor.redactor_editor_wym ol li ul,
+.redactor_editor.redactor_editor_wym ul li ol,
+.redactor_editor.redactor_editor_wym ol li ol {
+ border: none !important;
+}
+/*
+ DROPDOWN
+*/
+.redactor_dropdown {
+ position: absolute;
+ top: 28px;
+ left: 0;
+ padding: 10px;
+ width: 200px;
+ background-color: #fff;
+ box-shadow: 0 1px 5px #bbb;
+ font-size: 13px;
+ font-family: Helvetica, Arial, Verdana, Tahoma, sans-serif;
+ line-height: 21px;
+}
+.redactor-toolbar-typewriter .redactor_dropdown {
+ font-family: 'Courier New', 'Lucida Console', Consolas, Monaco, monospace, sans-serif;
+ background-color: #f5f5f5;
+}
+.redactor_separator_drop {
+ padding: 0 !important;
+ border-top: 1px solid #ddd;
+ font-size: 0;
+ line-height: 0;
+}
+.redactor_dropdown a {
+ display: block;
+ padding: 3px 5px;
+ color: #000;
+ text-decoration: none;
+}
+.redactor_dropdown a:hover {
+ background-color: #dde4ef;
+ color: #444 !important;
+ text-decoration: none;
+}
+/*
+ MODAL
+*/
+#redactor_modal_overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ margin: auto;
+ width: 100%;
+ height: 100%;
+ background-color: #000 !important;
+ filter: alpha(opacity=30);
+ -moz-opacity: 0.3;
+ opacity: 0.3;
+}
+#redactor_modal {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ padding: 0;
+ background: #fff;
+ color: #000;
+ font-size: 12px !important;
+ font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;
+ box-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
+}
+#redactor_modal header {
+ padding: 20px 30px 5px 30px;
+ font-size: 16px;
+}
+#redactor_modal section {
+ padding: 20px 30px;
+}
+#redactor_modal label {
+ display: block !important;
+ float: none !important;
+ margin: 10px 0 3px 0 !important;
+ padding: 0 !important;
+ font-size: 12px !important;
+}
+#redactor_modal footer:after {
+ content: "";
+ display: table;
+ clear: both;
+}
+#redactor_modal footer div {
+ float: left;
+}
+#redactor_modal input[type="radio"],
+#redactor_modal input[type="checkbox"] {
+ position: relative;
+ top: -1px;
+}
+#redactor_modal input[type="text"],
+#redactor_modal input[type="password"],
+#redactor_modal input[type="email"],
+#redactor_modal textarea {
+ position: relative;
+ z-index: 2;
+ margin: 0;
+ padding: 1px 2px;
+ height: 23px;
+ border: 1px solid #ccc;
+ border-radius: 1px;
+ background-color: white;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
+ color: #333;
+ font-size: 13px;
+ font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;
+ line-height: 1;
+ -moz-transition: border 0.3s ease-in;
+ transition: border 0.3s ease-in;
+}
+#redactor_modal textarea {
+ display: block;
+ margin-top: 4px;
+ line-height: 1.4em;
+}
+#redactor_modal input:focus,
+#redactor_modal textarea:focus {
+ outline: none;
+ border-color: #5ca9e4;
+ box-shadow: 0 0 0 2px rgba(70, 161, 231, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2) inset;
+}
+#redactor_modal_close {
+ position: absolute;
+ top: 5px;
+ right: 3px;
+ width: 20px;
+ height: 20px;
+ color: #999;
+ font-size: 26px;
+ cursor: pointer;
+}
+#redactor_modal_close:hover {
+ color: #000;
+}
+.redactor_input {
+ width: 99%;
+ font-size: 14px;
+}
+.redactor_modal_box {
+ overflow: auto;
+ margin-bottom: 10px;
+ height: 350px;
+}
+#redactor_image_box {
+ overflow: auto;
+ margin-bottom: 10px;
+ height: 270px;
+}
+#redactor_image_box_select {
+ display: block;
+ margin-bottom: 15px !important;
+ width: 200px;
+}
+#redactor_image_box img {
+ margin-right: 10px;
+ margin-bottom: 10px;
+ max-width: 100px;
+ cursor: pointer;
+}
+#redactor_tabs {
+ margin-bottom: 18px;
+}
+#redactor_tabs a {
+ display: inline-block;
+ margin-right: 2px;
+ padding: 4px 14px;
+ border: 1px solid #d2d2d2;
+ border-radius: 3px;
+ background: #fff;
+ color: #000;
+ text-decoration: none;
+ line-height: 1;
+}
+#redactor_tabs a:hover,
+#redactor_tabs a.redactor_tabs_act {
+ border-color: #eee;
+ color: #999 !important;
+ text-decoration: none !important;
+}
+.redactor_modal_btn_hidden {
+ display: none;
+}
+#redactor_modal footer button {
+ position: relative;
+ width: 100%;
+ padding: 10px 16px;
+ margin: 0;
+ outline: none;
+ border: none;
+ background-color: #ddd;
+ color: #000;
+ text-align: center;
+ text-decoration: none;
+ font-weight: normal;
+ font-size: 12px;
+ font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;
+ line-height: 1;
+ cursor: pointer;
+}
+#redactor_modal footer button:hover {
+ color: #777;
+ background: none;
+ background: #bbb;
+ text-decoration: none;
+}
+#redactor_modal footer button.redactor_modal_delete_btn {
+ background: none;
+ color: #fff;
+ background-color: #b52525;
+}
+#redactor_modal footer button.redactor_modal_delete_btn:hover {
+ color: rgba(255, 255, 255, 0.6);
+ background-color: #881b1b;
+}
+#redactor_modal footer button.redactor_modal_action_btn {
+ background: none;
+ color: #fff;
+ background-color: #2461b5;
+}
+#redactor_modal footer button.redactor_modal_action_btn:hover {
+ color: rgba(255, 255, 255, 0.6);
+ background-color: #1a4580;
+}
+/* Drag and Drop Area */
+.redactor_droparea {
+ position: relative;
+ margin: auto;
+ margin-bottom: 5px;
+ width: 100%;
+}
+.redactor_droparea .redactor_dropareabox {
+ position: relative;
+ z-index: 1;
+ padding: 60px 0;
+ width: 99%;
+ border: 1px dashed #ddd;
+ background: #fff;
+ text-align: center;
+}
+.redactor_droparea .redactor_dropareabox,
+.redactor_dropalternative {
+ color: #555;
+ font-size: 12px;
+}
+.redactor_dropalternative {
+ margin: 4px 0 2px 0;
+}
+.redactor_dropareabox.hover {
+ border-color: #aaa;
+ background: #efe3b8;
+}
+.redactor_dropareabox.error {
+ border-color: #dcc3c3;
+ background: #f7e5e5;
+}
+.redactor_dropareabox.drop {
+ border-color: #e0e5d6;
+ background: #f4f4ee;
+}
+/* =ProgressBar
+-----------------------------------------------------------------------------*/
+#redactor-progress {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ z-index: 1000000;
+ height: 10px;
+}
+#redactor-progress span {
+ display: block;
+ width: 100%;
+ height: 100%;
+ background-color: #3d58a8;
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+ background-size: 40px 40px;
+}
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@-o-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
diff --git a/app/assets/stylesheets/shared/formtastic.scss b/app/assets/stylesheets/shared/formtastic.scss
new file mode 100644
index 0000000..1f15de8
--- /dev/null
+++ b/app/assets/stylesheets/shared/formtastic.scss
@@ -0,0 +1,145 @@
+/* -------------------------------------------------------------------------------------------------
+
+It's *strongly* suggested that you don't modify this file. Instead, load a new stylesheet after
+this one in your layouts (eg formtastic_changes.css) and override the styles to suit your needs.
+This will allow you to update formtastic.css with new releases without clobbering your own changes.
+
+This stylesheet forms part of the Formtastic Rails Plugin
+(c) 2008 Justin French
+
+--------------------------------------------------------------------------------------------------*/
+
+
+/* NORMALIZE AND RESET - obviously inspired by Yahoo's reset.css, but scoped to just form.formtastic
+--------------------------------------------------------------------------------------------------*/
+form.formtastic, form.formtastic ul, form.formtastic ol, form.formtastic li, form.formtastic fieldset, form.formtastic legend, form.formtastic textarea, form.formtastic select, form.formtastic p { margin:0; padding:0; }
+form.formtastic fieldset { border:0; }
+form.formtastic em, form.formtastic strong { font-style:normal; font-weight:normal; }
+form.formtastic ol, form.formtastic ul { list-style:none; }
+form.formtastic abbr, form.formtastic acronym { border:0; font-variant:normal; }
+form.formtastic input, form.formtastic textarea, form.formtastic select { font-family:inherit; font-size:inherit; font-weight:inherit; }
+form.formtastic input, form.formtastic textarea, form.formtastic select { font-size:100%; }
+form.formtastic legend { white-space:normal; color:#000; }
+
+
+/* SEMANTIC ERRORS
+--------------------------------------------------------------------------------------------------*/
+form.formtastic ul.errors { color:#cc0000; margin:0.5em 0 1.5em 25%; list-style:square; }
+form.formtastic ul.errors li { padding:0; border:none; display:list-item; }
+
+
+/* FIELDSETS & LISTS
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset { overflow:auto; } /* clearing contained floats */
+form.formtastic fieldset.inputs { }
+form.formtastic fieldset.buttons { padding-left:25%; }
+form.formtastic fieldset ol { }
+form.formtastic fieldset.buttons li { float:left; padding-right:0.5em; }
+
+/* INPUT LIs
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li { padding:0.5em 0; margin-top:-0.5em; margin-bottom:1em; } /* padding and negative margin juggling is for Firefox */
+form.formtastic fieldset > ol > li { overflow:auto; } /* clearing contained floats */
+
+form.formtastic fieldset > ol > li.required { }
+form.formtastic fieldset > ol > li.optional { }
+form.formtastic fieldset > ol > li.error { }
+
+
+/* LABELS
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li label { display:block; width:25%; float:left; padding-top:.2em; }
+form.formtastic fieldset > ol > li > li label { line-height:100%; padding-top:0; }
+form.formtastic fieldset > ol > li > li label input { line-height:100%; vertical-align:middle; margin-top:-0.1em;}
+
+
+/* NESTED FIELDSETS AND LEGENDS (radio, check boxes and date/time inputs use nested fieldsets)
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li fieldset { position:relative; }
+form.formtastic fieldset > ol > li fieldset legend { position:absolute; width:95%; padding-top:0.1em; left: 0px; }
+form.formtastic fieldset > ol > li fieldset legend span { position:absolute; }
+form.formtastic fieldset > ol > li fieldset legend.label label { position:absolute; }
+form.formtastic fieldset > ol > li fieldset ol { float:left; width:74%; margin:0; padding:0 0 0 25%; }
+form.formtastic fieldset > ol > li fieldset ol li { padding:0; border:0; }
+
+
+/* INLINE HINTS
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li p.inline-hints { color:#666; margin:0.5em 0 0 25%; }
+
+
+/* INLINE ERRORS
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li p.inline-errors { color:#cc0000; margin:0.5em 0 0 25%; }
+form.formtastic fieldset > ol > li ul.errors { color:#cc0000; margin:0.5em 0 0 25%; list-style:square; }
+form.formtastic fieldset > ol > li ul.errors li { padding:0; border:none; display:list-item; }
+
+
+/* STRING, NUMERIC, PASSWORD, EMAIL, URL, PHONE & SEARCH OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li.string input,
+form.formtastic fieldset > ol > li.password input,
+form.formtastic fieldset > ol > li.numeric input,
+form.formtastic fieldset > ol > li.email input,
+form.formtastic fieldset > ol > li.url input,
+form.formtastic fieldset > ol > li.phone input,
+form.formtastic fieldset > ol > li.search input { width:72%; }
+
+form.formtastic fieldset > ol > li.string input[size],
+form.formtastic fieldset > ol > li.password input[size],
+form.formtastic fieldset > ol > li.numeric input[size],
+form.formtastic fieldset > ol > li.email input[size],
+form.formtastic fieldset > ol > li.url input[size],
+form.formtastic fieldset > ol > li.phone input[size],
+form.formtastic fieldset > ol > li.search input[size] { width:auto; max-width:72%; }
+
+
+/* TEXTAREA OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li.text textarea { width:72%; }
+form.formtastic fieldset > ol > li.text textarea[cols] { width:auto; max-width:72%; }
+
+
+/* HIDDEN OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset ol li.hidden { display:none; }
+
+/* BOOLEAN OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li.boolean label { padding-left:25%; width:auto; }
+form.formtastic fieldset > ol > li.boolean label input { margin:0 0.5em 0 0.2em; }
+
+
+/* RADIO OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li.radio { }
+form.formtastic fieldset > ol > li.radio fieldset { overflow:visible; }
+form.formtastic fieldset > ol > li.radio fieldset ol { margin-bottom:-0.5em; }
+form.formtastic fieldset > ol > li.radio fieldset ol li { margin:0.1em 0 0.5em 0; overflow:visible; }
+form.formtastic fieldset > ol > li.radio fieldset ol li label { float:none; width:100%; }
+form.formtastic fieldset > ol > li.radio fieldset ol li label input { margin-right:0.2em; }
+
+
+/* CHECK BOXES (COLLECTION) OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li.check_boxes { }
+form.formtastic fieldset > ol > li.check_boxes fieldset { overflow:visible; }
+form.formtastic fieldset > ol > li.check_boxes fieldset ol { margin-bottom:-0.5em; }
+form.formtastic fieldset > ol > li.check_boxes fieldset ol li { margin:0.1em 0 0.5em 0; overflow:visible; }
+form.formtastic fieldset > ol > li.check_boxes fieldset ol li label { float:none; width:100%; }
+form.formtastic fieldset > ol > li.check_boxes fieldset ol li label input { margin-right:0.2em; }
+
+
+/* DATE & TIME OVERRIDES
+--------------------------------------------------------------------------------------------------*/
+form.formtastic fieldset > ol > li.date fieldset ol li,
+form.formtastic fieldset > ol > li.time fieldset ol li,
+form.formtastic fieldset > ol > li.datetime fieldset ol li { float:left; width:auto; margin:0 .3em 0 0; }
+
+form.formtastic fieldset > ol > li.date fieldset ol li label,
+form.formtastic fieldset > ol > li.time fieldset ol li label,
+form.formtastic fieldset > ol > li.datetime fieldset ol li label { display:none; }
+
+form.formtastic fieldset > ol > li.date fieldset ol li label input,
+form.formtastic fieldset > ol > li.time fieldset ol li label input,
+form.formtastic fieldset > ol > li.datetime fieldset ol li label input { display:inline; margin:0; padding:0; }
diff --git a/app/assets/stylesheets/vendor/select2.less b/app/assets/stylesheets/vendor/select2.scss
similarity index 100%
rename from app/assets/stylesheets/vendor/select2.less
rename to app/assets/stylesheets/vendor/select2.scss
diff --git a/app/helpers/icon_helper.rb b/app/helpers/icon_helper.rb
index 689a286..97ad358 100644
--- a/app/helpers/icon_helper.rb
+++ b/app/helpers/icon_helper.rb
@@ -2,19 +2,20 @@
module IconHelper
- def i(icon_name, options = {:icon => true})
- if options[:icon]
-
- raw (' ')
-
+ def i(icon, html_options={}, text="")
+ ic(icon, html_options, text, true)
+ end
- else
-
- raw (' ')
- end
-
-
-
+ def ic(icon, html_options={}, text="", round=false)
+ html_options = {} if html_options == nil
+ content_class = "fa fa-#{icon} "
+ content_class += "icon " if round
+ content_class << " #{html_options[:class]}" if html_options.key?(:class)
+ html_options[:class] = content_class
+
+ html = content_tag(:i, nil, html_options)
+ html << " #{text}" unless text.blank?
+ html.html_safe
end
diff --git a/app/inputs/qi_cible_select_input.rb b/app/inputs/qi_cible_select_input.rb
new file mode 100644
index 0000000..a4978ca
--- /dev/null
+++ b/app/inputs/qi_cible_select_input.rb
@@ -0,0 +1,30 @@
+class QiCibleSelectInput < Formtastic::Inputs::TextInput
+ include FormtasticBootstrap::Inputs::Base
+
+ def to_html
+ r = rand(1000000000000000000000000000)
+
+
+ input_wrapping do
+ label_html +
+ template.content_tag(:fieldset, template.text_field_tag("cible_name", (object.cible ? object.cible.cible_name : "aucuns élément séléctionné"), :id =>"name_#{r}" ) +
+ self.manager_select_cible_link(method, options, r) + builder.hidden_field(method.to_s+"_id", input_html_options.merge!(:id => "input_id_"+r.to_s)) +
+ builder.hidden_field(method.to_s+"_type", input_html_options.merge!(:id => "input_type_"+r.to_s)) )
+ end
+
+ end
+
+
+ def manager_select_cible_link(method, options, r)
+
+ template.content_tag(:a, "Modifier ce lien", :href => "#", :onclick => "select_cible_from_manager('"+r.to_s+"');return false;")
+
+ end
+
+end
+
+
+
+
+
+
diff --git a/app/inputs/qi_date_picker_input.rb b/app/inputs/qi_date_picker_input.rb
new file mode 100644
index 0000000..375ee2a
--- /dev/null
+++ b/app/inputs/qi_date_picker_input.rb
@@ -0,0 +1,12 @@
+
+class QiDatePickerInput < Formtastic::Inputs::TextInput
+ include FormtasticBootstrap::Inputs::Base
+
+ def to_html
+ r = rand(1000000000000000000000000000)
+ bootstrap_wrapping do
+ builder.text_field(method.to_s, input_html_options.merge!(:class => "datepicker form-control"))
+ end
+ end
+
+end
diff --git a/app/inputs/qi_datetime_picker_input.rb b/app/inputs/qi_datetime_picker_input.rb
new file mode 100644
index 0000000..85d93b1
--- /dev/null
+++ b/app/inputs/qi_datetime_picker_input.rb
@@ -0,0 +1,12 @@
+
+class QiDatetimePickerInput < Formtastic::Inputs::TextInput
+ include FormtasticBootstrap::Inputs::Base
+
+ def to_html
+ r = rand(1000000000000000000000000000)
+ bootstrap_wrapping do
+ builder.text_field(method.to_s, input_html_options.merge!(:class => "datetimepicker form-control"))
+ end
+ end
+
+end
diff --git a/app/inputs/qi_image_select_input.rb b/app/inputs/qi_image_select_input.rb
new file mode 100644
index 0000000..c50041d
--- /dev/null
+++ b/app/inputs/qi_image_select_input.rb
@@ -0,0 +1,34 @@
+class QiImageSelectInput < Formtastic::Inputs::TextInput
+ include FormtasticBootstrap::Inputs::Base
+
+ def to_html
+ r = rand(1000000000000000000000000000)
+
+
+
+ label_html +
+ template.content_tag(:fieldset, image_preview(method, options, r) + builder.hidden_field(method.to_s, input_html_options.merge!(:id => "input_"+r.to_s)) )
+
+
+ end
+
+
+ def manager_select_link(method, options, r)
+ template.content_tag(:a, "Modifier cette image", :href => "#", :onclick => "select_image_from_manager('"+r.to_s+"');return false;")
+ end
+
+ def image_preview(method, options,r)
+ if object.send("#{method}?") and ImageFile.exists?(object.send("#{method}"))
+ template.content_tag(:span, template.image_tag(object.image_file.file.large.medium.small.thumb.url, :id => "img_"+r.to_s, :onclick => "select_image_from_manager('"+r.to_s+"');return false;"), :class => "preview ")
+ else
+ template.content_tag(:span, template.image_tag("admin/default_image.png", :id => "img_"+r.to_s, :onclick => "select_image_from_manager('"+r.to_s+"');return false;"), :class => "preview ")
+ end
+ end
+
+end
+
+
+
+
+
+
diff --git a/app/inputs/qi_time_picker_input.rb b/app/inputs/qi_time_picker_input.rb
new file mode 100644
index 0000000..9637f4a
--- /dev/null
+++ b/app/inputs/qi_time_picker_input.rb
@@ -0,0 +1,12 @@
+
+class QiTimePickerInput < Formtastic::Inputs::TextInput
+ include FormtasticBootstrap::Inputs::Base
+
+ def to_html
+ r = rand(1000000000000000000000000000)
+ bootstrap_wrapping do
+ builder.text_field(method.to_s, input_html_options.merge!(:class => "timepicker form-control"))
+ end
+ end
+
+end
diff --git a/app/views/admin/admin_auths/new.haml b/app/views/admin/admin_auths/new.haml
index 2a18888..0849bb8 100644
--- a/app/views/admin/admin_auths/new.haml
+++ b/app/views/admin/admin_auths/new.haml
@@ -3,8 +3,8 @@
= form_tag admin_admin_auths_path do
%h2.form-signin-heading Se connecter
- = text_field_tag :login, params[:login], :placeholder => "email"
- = password_field_tag :password, "", :placeholder => "mot de passe"
+ = text_field_tag :login, params[:login], :placeholder => "email", :class => "form-control"
+ = password_field_tag :password, "", :placeholder => "mot de passe", :class => "form-control"
%p
diff --git a/app/views/admin/admins/_admin.html.haml b/app/views/admin/admins/_admin.html.haml
index ce8ee95..ac6af9a 100644
--- a/app/views/admin/admins/_admin.html.haml
+++ b/app/views/admin/admins/_admin.html.haml
@@ -7,7 +7,7 @@
%td.actions
- = link_to i(:trash), [:admin, admin], :confirm => 'Voulez-vous vraiment supprimer cet admin ?', :method => :delete, :remote => true
+ = link_to i(:"trash-o"), [:admin, admin], :confirm => 'Voulez-vous vraiment supprimer cet admin ?', :method => :delete, :remote => true
= link_to i(:pencil), edit_admin_admin_path(admin), :remote => true
diff --git a/app/views/admin/admins/_form.html.haml b/app/views/admin/admins/_form.html.haml
index 6d371a8..27ffe23 100644
--- a/app/views/admin/admins/_form.html.haml
+++ b/app/views/admin/admins/_form.html.haml
@@ -1,41 +1,34 @@
-#myModal.modal.fade{"aria-hidden" => "true", "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1"}
-
-
-
-
- .modal-header
- %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
- %h3#myModalLabel
- -if @admin.id
- Modifier un admin
- -else
- Ajouter un admin
- .modal-body
-
- =semantic_form_for [:admin, @admin], :remote => true do |f|
- = f.inputs do
-
- = f.input :email, :label => "Email :"
-
-
- = f.input :username, :label => "Login :"
-
-
- = f.input :name, :label => "Nom :"
-
-
-
- = f.input :firstname, :label => "Prénom :"
- = f.input :password, :label => "Mot de passe :"
-
- = f.input :password_confirmation, :label => "Confirmation :"
+=semantic_form_for [:admin, @admin], :remote => true do |f|
+ .content
+ %h3
+ -if @admin.id
+ Modifier un admin
+ -else
+ Ajouter un admin
+
+ = f.inputs do
+
+ = f.input :email, :label => "Email :"
+
+
+ = f.input :username, :label => "Login :"
-
- .modal-footer
- %button.btn{"aria-hidden" => "true", "data-dismiss" => "modal"} Annuler
- %button.btn.btn-primary{"aria-hidden" => "true", "data-dismiss" => "modal", :onclick => "$(this).closest('.modal').find('form').submit();"} Sauvegarder
-
\ No newline at end of file
+ = f.input :name, :label => "Nom :"
+
+
+
+ = f.input :firstname, :label => "Prénom :"
+
+
+ = f.input :password, :label => "Mot de passe :"
+
+
+ = f.input :password_confirmation, :label => "Confirmation :"
+
+
+ .actions= f.submit "Sauvegarder", :class => "btn btn-primary"
+
diff --git a/app/views/admin/admins/create.js.erb b/app/views/admin/admins/create.js.erb
index 12301e6..4bc6130 100644
--- a/app/views/admin/admins/create.js.erb
+++ b/app/views/admin/admins/create.js.erb
@@ -1 +1,2 @@
-$('#admin_rows').html("<%= escape_javascript(render(@admins))%>");
\ No newline at end of file
+$('#admin_rows').html("<%= escape_javascript(render(@admins))%>");
+close_pane_hover();
\ No newline at end of file
diff --git a/app/views/admin/admins/edit.js.erb b/app/views/admin/admins/edit.js.erb
index ed21283..6c8f015 100644
--- a/app/views/admin/admins/edit.js.erb
+++ b/app/views/admin/admins/edit.js.erb
@@ -1 +1 @@
-$('<%= escape_javascript(render(:partial => "form"))%>').modal('show');
\ No newline at end of file
+show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900);
\ No newline at end of file
diff --git a/app/views/admin/admins/index.html.haml b/app/views/admin/admins/index.html.haml
index 6d938e0..090a4a5 100644
--- a/app/views/admin/admins/index.html.haml
+++ b/app/views/admin/admins/index.html.haml
@@ -1,4 +1,4 @@
-= link_to 'Ajouter un administrateur', new_admin_admin_path, :remote => true, :class => "btn btn-success btn-large", :style => "float:right;"
+= link_to 'Ajouter un administrateur', new_admin_admin_path, :remote => true, :class => "btn btn-primary", :style => "float:right;"
%h1 Liste des administrateurs
@@ -19,7 +19,7 @@
- %td{:style => "width:70px"}
+ %td{:style => "width:100px"}
diff --git a/app/views/admin/admins/new.js.erb b/app/views/admin/admins/new.js.erb
index 4c8f617..6c8f015 100644
--- a/app/views/admin/admins/new.js.erb
+++ b/app/views/admin/admins/new.js.erb
@@ -1,4 +1 @@
-
-
-
-$('<%= escape_javascript(render(:partial => "form"))%>').modal('show');
\ No newline at end of file
+show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900);
\ No newline at end of file
diff --git a/app/views/admin/admins/update.js.erb b/app/views/admin/admins/update.js.erb
index 964745b..3c75f21 100644
--- a/app/views/admin/admins/update.js.erb
+++ b/app/views/admin/admins/update.js.erb
@@ -1 +1,3 @@
-$('#admin_row_<%= @admin.id %>').replaceWith("<%= escape_javascript(render(@admin))%>");
\ No newline at end of file
+$('#admin_row_<%= @admin.id %>').replaceWith("<%= escape_javascript(render(@admin))%>");
+
+close_pane_hover();
\ No newline at end of file
diff --git a/app/views/admin/albums/_album.html.haml b/app/views/admin/albums/_album.html.haml
index 446cd3e..74d3b3a 100644
--- a/app/views/admin/albums/_album.html.haml
+++ b/app/views/admin/albums/_album.html.haml
@@ -1,9 +1,4 @@
-%li{:class => (" active" if album.id == params[:album_id].to_i).to_s}
+%li{}
- =link_to album.name, admin_image_files_path(:album_id => album.id, :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "album_"+album.id.to_s,:data_album_id => album.id, :data_album_path => admin_album_path(:format => "js",:album_id => album.id, :manager => params[:manager], :multiple => params[:multiple], :id => album.id), :data_edit_album_path => edit_admin_album_path(:format => "js",:album_id => album.id, :manager => params[:manager], :multiple => params[:multiple], :id => album.id)
+ =link_to album.name, admin_image_files_path(:album_id => album.id, :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "album_"+album.id.to_s,:data_album_id => album.id, :data_album_path => admin_album_path(:format => "js",:album_id => album.id, :manager => params[:manager], :multiple => params[:multiple], :id => album.id), :data_edit_album_path => edit_admin_album_path(:format => "js",:album_id => album.id, :manager => params[:manager], :multiple => params[:multiple], :id => album.id),:class => (" active" if album.id == params[:album_id].to_i).to_s
- -if album.id == params[:album_id].to_i
-
- = link_to i(:pencil),edit_admin_album_url(:id => params[:album_id], :album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "edit_current_album", :style => "display:inline-block; margin-right:5px;"
-
- = link_to i(:trash), admin_album_url(:id => params[:album_id],:album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "remove_current_album", :method => :delete, :confirm => "Voulez-vous vraiment supprimer cet album ? Attention, toutes les images de celui-ci seront définitivement supprimées.", :style => "display:inline-block;"
\ No newline at end of file
diff --git a/app/views/admin/albums/_albums.html.haml b/app/views/admin/albums/_albums.html.haml
index 0bb4791..cc591ce 100644
--- a/app/views/admin/albums/_albums.html.haml
+++ b/app/views/admin/albums/_albums.html.haml
@@ -1,5 +1,3 @@
%ul.nav.nav-list
- =render @albums
-
- %li
- = link_to i(:plus), new_admin_album_url(:album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "add_album"
+ =render @albums
+
diff --git a/app/views/admin/albums/_albums_navbar.html.haml b/app/views/admin/albums/_albums_navbar.html.haml
new file mode 100644
index 0000000..839c39b
--- /dev/null
+++ b/app/views/admin/albums/_albums_navbar.html.haml
@@ -0,0 +1,4 @@
+= link_to ic(:plus), new_admin_album_url(:album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "add_album"
+= link_to ic(:pencil),edit_admin_album_url(:id => params[:album_id], :album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "edit_current_album", :style => "display:inline-block; margin-right:5px;"
+
+= link_to ic(:"trash-o"), admin_album_url(:id => params[:album_id],:album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :id => "remove_current_album", :method => :delete, :confirm => "Voulez-vous vraiment supprimer cet album ? Attention, toutes les images de celui-ci seront définitivement supprimées.", :style => "display:inline-block;"
\ No newline at end of file
diff --git a/app/views/admin/albums/update.js.erb b/app/views/admin/albums/update.js.erb
index e914805..7f37b68 100644
--- a/app/views/admin/albums/update.js.erb
+++ b/app/views/admin/albums/update.js.erb
@@ -1,2 +1,2 @@
-$("#album_<%=@album.id %>").replaceWith("<%= escape_javascript(render(@album))%>");
+$('#albums').html("<%= escape_javascript(render(:partial => "albums")) %>");
image_files_load();
\ No newline at end of file
diff --git a/app/views/admin/image_files/_image_file.html.haml b/app/views/admin/image_files/_image_file.html.haml
index 37c05ed..9c0862b 100644
--- a/app/views/admin/image_files/_image_file.html.haml
+++ b/app/views/admin/image_files/_image_file.html.haml
@@ -5,6 +5,6 @@
.name
=image_file.name ? truncate(image_file.name, :length => 17) : raw(" ")
- = link_to i(:ok), "#",:onclick => "manager_send_image_file("+image_file.id.to_s+");return false;" if params[:manager] and !params[:multiple]
+ = link_to i(:"check"), "#",:onclick => "manager_send_image_file("+image_file.id.to_s+");return false;" if params[:manager] and !params[:multiple]
\ No newline at end of file
diff --git a/app/views/admin/image_files/_index_block.html.haml b/app/views/admin/image_files/_index_block.html.haml
index 1169d6d..90701f4 100644
--- a/app/views/admin/image_files/_index_block.html.haml
+++ b/app/views/admin/image_files/_index_block.html.haml
@@ -1,159 +1,165 @@
#image_files_content
#image_files_big_container.container-fluid
- .row-fluid
- .span3#albums=render :partial => "admin/albums/albums"
+ #albums=render :partial => "admin/albums/albums"
+ #albums_navbar
+ =render :partial => "admin/albums/albums_navbar"
+
+
+
+
-
-
- .span9
- =render :partial => "image_files_container"
+ =render :partial => "image_files_container"
%form#fileupload{:action => admin_image_files_path(:id => @image_file.id, :album_id => params[:album_id], :manager => params[:manager], :multiple => params[:multiple]),:method=>"POST", :enctype=>"multipart/form-data", :style => "display:inline;"}
%input{:name => "redirect", :type => "hidden", :value => "/"}/
- .navbar.navbar-fixed-bottom{:style => "position:absolute;"}
- .navbar-inner
- .container-fluid
+ %nav.navbar.navbar-default.navbar-fixed-bottom#image_files_navbar{:style => "position:absolute;"}
+
+ .container-fluid
+
+ %ul.nav.navbar-nav.navbar-right
- .pull-right{:style => ""}
-
- .fileupload-progress.fade{:style => "float:left;"}
- #upload_details{:style => ""}
- .content
- .fileupload-buttonbar
- %button.btn.btn-warning.cancel{:type => "reset"}
- %i.icon-ban-circle.icon-white
- %span Cancel upload
- %span.fileupload-loading
-
- %table.table.table-striped{:role => "presentation"}
- %tbody.ulpoad_files
-
-
-
- .progress-extended{:style => "float:left;padding: 10px;font-size:14px;line-height:20px;"}
-
+ .fileupload-progress.fade{:style => "float:left;"}
+ #upload_details{:style => ""}
+ .content
+ .fileupload-buttonbar
+ %button.btn.btn-warning.cancel{:type => "reset"}
+ %i.icon-ban-circle.icon-white
+ %span Cancel upload
+ %span.fileupload-loading
+
+ %table.table.table-striped{:role => "presentation"}
+ %tbody.ulpoad_files
+
+
+
+ .progress-extended{:style => "float:left;padding: 10px;font-size:14px;line-height:20px;"}
+
+
+ .progress.progress-success.progress-striped.active{"aria-valuemax" => "100", "aria-valuemin" => "0", :role => "progressbar",:style => "width:200px;float:left;margin: 10px;height:20px;"}
+ .bar{:style => "width:0%;"}
- .progress.progress-success.progress-striped.active{"aria-valuemax" => "100", "aria-valuemin" => "0", :role => "progressbar",:style => "width:200px;float:left;margin: 10px;height:20px;"}
- .bar{:style => "width:0%;"}
-
- %div{:style => "float:left;padding: 10px;height:20px;"}
- %input#grid_slider{:type=>"text", :value=>""}
-
- :coffeescript
- initialize_slider()
-
-
-
-
- .brand Images
+ %div{:style => "float:left;padding: 10px;height:20px;"}
+ %input#grid_slider{:type=>"text", :value=>""}
+ :coffeescript
+ initialize_slider()
+
+
+
+
+ .navbar-header
+ %span.navbar-brand Images
+
-
-
-
-
-
- .container.nav-collapse
- %ul.nav#multiple_selection
-
- %li.dropdown#multiple_menu
- %a#multiple_selection_text{:href => "#", :class => "dropdown-toggle", :data => {:toggle => "dropdown"}}
- %b.caret
-
- %ul.dropdown-menu
- -if params[:multiple]
- %li
- %a{:href => "#", :onclick => "manager_send_multiple_image_files();return false;"} Sélectionner ces images
- %li
- %a{:href => "#", :onclick => "delete_multiple_images();return false;"} Supprimer ces images
+
- %li.divider
- %li
- %a{:href => "#", :onclick => "unselect_all_image();return false;"} Tout désélectionner
- %li
- %a{:href => "#", :onclick => "select_all_image();return false;"} Tout sélectionner
+
+
+ .collapse.navbar-collapse
+ %ul.nav.navbar-nav#multiple_selection
+
+ %li.dropdown#multiple_menu
+ %a#multiple_selection_text{:href => "#", :class => "dropdown-toggle", :data => {:toggle => "dropdown"}}
+ %b.caret
-
- %ul.nav
- %li
- %a{:href => "#", :onclick => "$(this).next('input').click();return false;"}
- %span.fileinput-button{}
- %i.icon-plus.icon-white
- %span Ajouter des images
- %input{:multiple => "", :name => "files[]", :type => "file", :style => "display:none;"}
-
+ %ul.dropdown-menu
+
+ %li
+ %a{:href => "#", :onclick => "delete_multiple_images();return false;"} Supprimer ces images
+
+ %li.divider
+ %li
+ %a{:href => "#", :onclick => "unselect_all_image();return false;"} Tout désélectionner
+ %li
+ %a{:href => "#", :onclick => "select_all_image();return false;"} Tout sélectionner
+
+ %ul.nav.navbar-nav
+ %li
+ -if params[:multiple]
+ %li
+ %a{:href => "#", :onclick => "manager_send_multiple_image_files();return false;"}=ic :"check-circle"
+
+
+ %ul.nav.navbar-nav
+ %li
+ %a{:href => "#", :onclick => "$(this).next('input').click();return false;"}
+ %span.fileinput-button{}
+ %i.icon-plus.icon-white
+ %span Ajouter des images
+ %input{:multiple => "", :name => "files[]", :type => "file", :style => "display:none;"}
+
+
-
-
-
-
-
- :plain
-
-
-
-
+
+ :plain
+
+
+
+
+
- :coffeescript
- $('#fileupload').fileupload({
- paramName:"files",
- dataType:"script",
- autoUpload:true,
- filesContainer:".ulpoad_files"
-
- }).bind('fileuploadadded',(e, data)->
- $("#upload_details").show();
- ).bind('fileuploadfinished',(e, data)->
- $("#upload_details").hide();
- )
+
+ :coffeescript
+ $('#fileupload').fileupload({
+ paramName:"files",
+ dataType:"script",
+ autoUpload:true,
+ filesContainer:".ulpoad_files"
+
+ }).bind('fileuploadadded',(e, data)->
+ $("#upload_details").show();
+ ).bind('fileuploadfinished',(e, data)->
+ $("#upload_details").hide();
+ )
diff --git a/app/views/admin/image_files/_show.html.haml b/app/views/admin/image_files/_show.html.haml
index 46db077..b52b43f 100644
--- a/app/views/admin/image_files/_show.html.haml
+++ b/app/views/admin/image_files/_show.html.haml
@@ -5,7 +5,7 @@
=render :partial => "form"
#right_bar_clone
#right_bar_clone_buttons_left
- = link_to i(:trash_stroke, :gray_light), admin_image_file_path(:id => @image_file.id, :manager => params[:manager], :multiple => params[:multiple]), :confirm => 'Voulez-vous vraiment supprimer cette image ?', :method => :delete, :remote => true
+ = link_to i(:"trash-o"), admin_image_file_path(:id => @image_file.id, :manager => params[:manager], :multiple => params[:multiple]), :confirm => 'Voulez-vous vraiment supprimer cette image ?', :method => :delete, :remote => true
= link_to i(:rotate, :gray_light, "12x14"), rotate_admin_image_file_path(:id => @image_file.id, :manager => params[:manager], :multiple => params[:multiple]), :remote => true, :onclick => "set_busy();"
= link_to i(:rotate_right, :gray_light, "12x14"), rotate_admin_image_file_path(:id => @image_file.id, :manager => params[:manager], :multiple => params[:multiple], :direction => :right), :remote => true, :onclick => "set_busy();"
diff --git a/app/views/admin/image_files/index.html.haml b/app/views/admin/image_files/index.html.haml
index 891b211..875977c 100644
--- a/app/views/admin/image_files/index.html.haml
+++ b/app/views/admin/image_files/index.html.haml
@@ -1,2 +1,3 @@
-=render :partial => "index_block"
\ No newline at end of file
+%div{:style => ("position:absolute;bottom:0px;left:0px;right:0px;top:52px;" if !params[:manager])}
+ =render :partial => "index_block"
\ No newline at end of file
diff --git a/app/views/admin/image_files/index.js.erb b/app/views/admin/image_files/index.js.erb
index bafeae4..1d46987 100644
--- a/app/views/admin/image_files/index.js.erb
+++ b/app/views/admin/image_files/index.js.erb
@@ -1,2 +1,5 @@
$('#image_files_content').html("<%= escape_javascript(render(:partial => "index_block")) %>");
+
+$('#image_files_content').html("<%= escape_javascript(render(:partial => "index_block")) %>");
+
set_image_files_img_size();
diff --git a/app/views/admin/menu_items/_form.html.haml b/app/views/admin/menu_items/_form.html.haml
index 91fe574..b36f6a2 100644
--- a/app/views/admin/menu_items/_form.html.haml
+++ b/app/views/admin/menu_items/_form.html.haml
@@ -1,10 +1,15 @@
= form.inputs do
= form.input :enabled, :label => "Publié ?"
= form.input :visible, :label => "Visible ?"
+
+
+
+
= form.input :name, :label => "Nom :"
= form.input :slug, :label => "slug :"# if current_admin.super_admin? || !@menu_item.super_admin
= #form.input :super_admin,:as => :boolean , :label => "Super Admin"# if current_admin.super_admin?
+
= form.input :menu_id,:as => :hidden
= form.input :parent_id,:as => :hidden
diff --git a/app/views/admin/menu_items/_menu_item.html.haml b/app/views/admin/menu_items/_menu_item.html.haml
index e3de6d3..04a5638 100644
--- a/app/views/admin/menu_items/_menu_item.html.haml
+++ b/app/views/admin/menu_items/_menu_item.html.haml
@@ -1,30 +1,37 @@
-#menu_item_row.menu_item_row.row-fluid{:id => menu_item.id,:"data-menu-item-id" => menu_item.id}
-
- .span1.receptable{:data => {:menu_id => @menu.id, :parent_id => menu_item.id}}
- .btn-group
- %span.handle.btn=i(:move, :icon => false)
- =link_to (menu_item.children.size > 0 ? i(:"folder-close", :icon => false) : i(:"folder-close-alt", :icon => false) )+(menu_item.children.size if menu_item.children.size > 0).to_s, admin_menu_items_path(:menu_id => menu_item.menu_id, :parent_id => menu_item.id), :remote => true, :class => "btn"
-
-
- .span2
+#menu_item_row.menu_item_row.row{:id => menu_item.id,:"data-menu-item-id" => menu_item.id}
+
+
+
+
+ .col-xs-3
+ .receptable{:style => "display:inline-block;width:110px;",:data => {:menu_id => (@menu.id if @menu), :parent_id => menu_item.id}}
+ -if @menu
+ .btn-group
+ %span.handle.btn.btn-default=ic(:arrows, :icon => false)
+ =link_to (menu_item.children.count > 0 ? ic(:"folder") : ic(:"folder-o") )+(menu_item.children.count if menu_item.children.count > 0).to_s, admin_menu_items_path(:menu_id => menu_item.menu_id, :parent_id => menu_item.id), :remote => true, :class => "btn btn-default"
+
+ =menu_item.menu_content_type.constantize::HUMAN_NAME
+
+ .col-xs-3=menu_item.name
+
+ .col-xs-4
+ -if @menu
+ =link_to "/"+menu_item.permalink.to_s+".html", "/"+menu_item.permalink.to_s+".html"
+ -else
+ =link_to archive_public_menu_item_path(menu_item), archive_public_menu_item_path(menu_item)
+
+ .col-xs-2.actions
+
- =menu_item.menu_content_type.constantize::HUMAN_NAME
-
- .span3=menu_item.name
-
- .span4
- ="/"+menu_item.permalink+".html"
-
- .span2.actions
-
+
+
+ =link_to i(:copy), clone_admin_menu_item_path(menu_item), :data => {:confirm => 'Voulez-vous vraiment cloner cet élément de menu ?'}
- =link_to i(:copy), clone_admin_menu_item_path(menu_item), :data => {:confirm => 'Voulez-vous vraiment cloner cet élément de menu ?'}
+ = link_to i(:"trash-o"), [:admin, menu_item], :data =>{:confirm => 'Voulez-vous vraiment supprimer cet élément de menu ?'}, :method => :delete #, if current_admin.super_admin? || !menu_item.super_admin
- = link_to i(:trash), [:admin, menu_item], :data =>{:confirm => 'Voulez-vous vraiment supprimer cet élément de menu ?'}, :method => :delete #, if current_admin.super_admin? || !menu_item.super_admin
+ = link_to i(:pencil), edit_admin_menu_item_path(menu_item)
- = link_to i(:pencil), edit_admin_menu_item_path(menu_item)
-
-
-
+
+
diff --git a/app/views/admin/menu_items/_new_form.html.haml b/app/views/admin/menu_items/_new_form.html.haml
index 40550c2..cf6a3bd 100644
--- a/app/views/admin/menu_items/_new_form.html.haml
+++ b/app/views/admin/menu_items/_new_form.html.haml
@@ -1,36 +1,25 @@
-#myModal.modal.hide.fade{"aria-hidden" => "true", "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1"}
-
-
-
-
- .modal-header
- %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
- %h3#myModalLabel
- Ajouter un élément de menu
- .modal-body
- = semantic_form_for [:admin,@menu_item], :remote => true do |form|
- .form1=render :partial => "form", :locals => {:form => form}
-
-
-
- #select_menu_item_content_type_bar.bar.dark_blue
- -MenuItem::ContentTypes.each do |menu_item_content_type|
- =link_to menu_item_content_type[:name], new_admin_menu_item_path(:menu_id => @menu_item.menu_id, :parent_id =>@menu_item.parent_id, :menu_item_content_type => menu_item_content_type[:slug] ), :onclick => "$('#menu_item_content_form').load($(this).attr('href')+' #menu_item_content_form');$('#select_menu_item_content_type_bar .active').removeClass('active');$(this).addClass('active');return false;",:class => ("active" if menu_item_content_type[:slug] == @menu_item.menu_content_type).to_s
- #menu_item_content_form.form2
- = form.inputs do
- = form.input :menu_content_type,:as => :hidden
- =render :partial => "admin/"+@menu_item.menu_content_type.tableize.to_s+"/form", :locals => {:form => form}
-
- .actions
- = form.submit "Sauvegarder"
-
-
-
- .modal-footer
- %button.btn{"aria-hidden" => "true", "data-dismiss" => "modal"} Annuler
- %button.btn.btn-primary{"aria-hidden" => "true", "data-dismiss" => "modal", :onclick => "$(this).closest('.modal').find('form').submit();"} Sauvegarder
-
+= semantic_form_for [:admin,@menu_item], :remote => true do |form|
+ .content
+ %h3 Ajouter un élément de menu
+ .form1=render :partial => "form", :locals => {:form => form}
+
+
+
+ #select_menu_item_content_type_bar.bar.dark_blue
+ -MenuItem::ContentTypes.each do |menu_item_content_type|
+ =link_to menu_item_content_type[:name], new_admin_menu_item_path(:menu_id => @menu_item.menu_id, :parent_id =>@menu_item.parent_id, :menu_item_content_type => menu_item_content_type[:slug] ), :onclick => "$('#menu_item_content_form').load($(this).attr('href')+' #menu_item_content_form');$('#select_menu_item_content_type_bar .btn-primary').removeClass('btn-primary');$(this).addClass('btn-primary');return false;",:class => "btn btn-default "+("btn-primary" if menu_item_content_type[:slug] == @menu_item.menu_content_type).to_s
+ #menu_item_content_form.form2
+ = form.inputs do
+ = form.input :menu_content_type,:as => :hidden
+ =render :partial => "admin/"+@menu_item.menu_content_type.tableize.to_s+"/form", :locals => {:form => form}
+
+
+
+ .actions
+ = form.submit "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/admin/menu_items/archives.html.haml b/app/views/admin/menu_items/archives.html.haml
new file mode 100644
index 0000000..785618a
--- /dev/null
+++ b/app/views/admin/menu_items/archives.html.haml
@@ -0,0 +1,10 @@
+%h1 Archives
+
+
+#menu_item_index
+ #sortable_menu_item=render @menu_items
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/admin/menu_items/import.html.haml b/app/views/admin/menu_items/import.html.haml
new file mode 100644
index 0000000..9e14904
--- /dev/null
+++ b/app/views/admin/menu_items/import.html.haml
@@ -0,0 +1,112 @@
+
+-@agendas.each do |actu|
+
+
+
+
+ -@event= Event.new(:skip_date => true,:stop_date => true, :start_at => (actu["start_at"] != "0000-00-00 00:00:00" ? actu["start_at"] : "2010-01-01 00:00:00"),:stop_at => (actu["finished_at"] != "0000-00-00 00:00:00" ? actu["finished_at"] : "2010-01-01 00:00:00"), :updated_at => actu["updated_at"], :created_at => actu["created_at"],:title => actu["title"],:description => HTMLEntities.new.decode(actu["description"]) )
+
+
+
+
+ -if @event.save
+
+
+
+
+ -content = ""
+ -begin
+
+ =@event.block.portlets << Portlet.create(:content => TextContent.new(:content => HTMLEntities.new.decode(actu["content"])))
+ -rescue
+
+ -else
+ =debug @event.errors
+
+
+
+
+
+
+
+
+
+-@album = Album.create(:name => "images actualité")
+
+
+
+
+-@actualitees.each do |actu|
+
+ -@article= Article.new(:enabled => true, :frontpage => true,:end_at => (actu["end_at"] != "0000-00-00 00:00:00" ? actu["end_at"] : "2010-01-01 00:00:00"), :published_at => (actu["start_at"] != "0000-00-00 00:00:00" ? actu["start_at"] : "2010-01-01 00:00:00"), :updated_at => actu["updated_at"], :created_at => actu["created_at"],:title => actu["title"],:description => HTMLEntities.new.decode(actu["description"]) )
+
+ -begin
+ -rep = false
+ -rep = @article.save
+ -rescue
+ %h2 erreur
+ =debug @article
+
+ -if rep
+ -content = ""
+ -begin
+
+ =@article.block.portlets << Portlet.create(:content => TextContent.new(:content => HTMLEntities.new.decode(actu["content"])))
+ -rescue
+
+
+ -@url = Rails.root.join("public", "system","images", actu["id"],"original",actu["image_file_name"])
+
+ -if File.exist?(@url)
+
+ =debug File.open(@url)
+ -@image_file = ImageFile.new(:file => File.open(@url))
+ -@image_file.album_id = @album.id
+ =debug @image_file.save
+ -@article.image_file_id = @image_file.id
+ -@article.save
+
+
+
+-@blocks.each do |block|
+ -if block["block_name_id"] == "1"
+ -lang_page = @lang_pages[block["lang_page_id"].to_i]
+ -page = @pages[lang_page["page_id"].to_i]
+
+
+
+ -if page and lang_page
+
+ -@menu_item= MenuItem.new(:id => page["id"].to_i,:position => page["position"].to_i,:enabled => true, :visible => true,:menu_id => 1,:archive_id => page["archive_id"], :archived_at => (page["archived_at"] != "0000-00-00 00:00:00" ? page["archived_at"] : "2010-01-01 00:00:00"), :updated_at => page["updated_at"], :created_at => page["created_at"], :menu_content_type => "Page",:name => lang_page["menu_title"], :slug => lang_page["slug"], :parent_id => (page["parent_id"] != "NULL" ? page["parent_id"].to_i : nil), :archived => (page["archived"] != "NULL" ? true : nil))
+
+
+
+
+ -content = Page.new(:title => HTMLEntities.new.decode(lang_page["title"]), :description => HTMLEntities.new.decode(lang_page["description"]), :keywords => HTMLEntities.new.decode(lang_page["keywords"]))
+
+
+
+ -@menu_item.menu_content = content
+
+ -if @menu_item.save!
+ -content = ""
+ -begin
+
+ =@menu_item.menu_content.blocks[0].portlets << Portlet.new(:content => TextContent.new(:content => HTMLEntities.new.decode(block["content"])))
+ -rescue
+ %h1
+ ALERT
+
+
+
+
+ =debug block
+
+ =debug lang_page
+ =debug page
+-MenuItem.all.each do |mi|
+
+ -if mi.created_at.year < 1980
+ -mi.created_at = "2010-08-01"
+ -mi.save
+ -mi.set_permalink
diff --git a/app/views/admin/menu_items/new.js.erb b/app/views/admin/menu_items/new.js.erb
index 1cdcd08..19df7fa 100644
--- a/app/views/admin/menu_items/new.js.erb
+++ b/app/views/admin/menu_items/new.js.erb
@@ -1 +1,3 @@
-$('<%= escape_javascript(render(:partial => "new_form"))%>').modal('show');
\ No newline at end of file
+
+
+show_pane_hover("<%= escape_javascript(render(:partial => "new_form"))%>",700,900);
\ No newline at end of file
diff --git a/app/views/admin/pages/_page.html.haml b/app/views/admin/pages/_page.html.haml
index e2c0341..4c27149 100644
--- a/app/views/admin/pages/_page.html.haml
+++ b/app/views/admin/pages/_page.html.haml
@@ -1,44 +1,69 @@
-#menu_item_block_edit
+#toolbar-text
- =render :partial => "admin/blocks/block", :locals => {:block => page.blocks[0], :sortable => true}
-
-
+#menu_item_block_edit{:style => "margin-right:330px;margin-top:45px;"}
+
+ =render :partial => "admin/blocks/block", :locals => {:block => page.blocks[0], :sortable => true}
+
+
#menu_item_inspector_container
- .accordion#menu_item_informations
-
- .accordion-group
- .inspector_handle
- .accordion-heading.navbar-inner.navbar-inverse
- %a.accordion-toggle{:href => "#collapseOne",:data => {:toggle => "collapse", :parent => "#menu_item_informations"}}
- Infos sur la page
-
-
- #collapseOne.accordion-body.collapse
- .accordion-inner
- =render :partial => "edit_form"
-
-
- .accordion-heading.navbar-inner.navbar-inverse
- %a.accordion-toggle{:href => "#collapse2",:data => {:toggle => "collapse", :parent => "#menu_item_informations"}}
- éléments
-
-
- #collapse2.accordion-body.collapse.in
- .accordion-inner
- .block_portlets_sortable#content_types
- -page.blocks[0].alloweds_types.each do |slug, name|
+
+
+
+
+
+
+
+ .accordion#menu_item_informations.panel-group
+ .panel.panel-default
+ .panel-heading
+ %h4.panel-title
+ %a.panel-toggle{:href => "#collapseOne",:data => {:toggle => "collapse", :parent => "#menu_item_informations"}}
+ Infos sur la page
+
+
+ #collapseOne.panel-collapse.collapse
+ .panel-body
+ =render :partial => "edit_form"
+
+ .panel.panel-default
+ .panel-heading
+ %h4.panel-title
+ %a.panel-toggle{:href => "#collapse2",:data => {:toggle => "collapse", :parent => "#menu_item_informations"}}
+ éléments
+
+
+ #collapse2.panel-collapse.collapse.in
+ .panel-body
+ .block_portlets_sortable#content_types
+ -page.blocks[0].alloweds_types.each do |slug, name|
- .portlet{:id => slug, :data_type => slug}
- =image_tag("admin/content_type/type_"+slug.to_s+".png", :alt => name, :class => "handle")
-
+ .content_type{:id => slug, :"data-type" => slug}
+ =image_tag("admin/content_type/type_"+slug.to_s+".png", :alt => name, :title => name, :class => "handle")
+
+
+ .panel.panel-default
+ .panel-heading
+ %h4.panel-title
+ %a.panel-toggle{:href => "#collapse3",:data => {:toggle => "collapse", :parent => "#menu_item_informations"}}
+ Modifier l'élément
+
+
+ #collapse3.panel-collapse.collapse
+ .panel-body
+
+ #element_form
+
+ %div
+ %a.btn.btn-default.portlet_handle{:href => "#", :data => {:portlet_id => nil}}
+ =ic :arrows
+ déplacer
+ =link_to ic(:"trash-o")+" Supprimer", "#", :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn btn-danger trash"
+
+
+
-
-
-
-
-
-
+
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index 13d86bd..6b49f2b 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -1,12 +1,12 @@
!!!
-%html{:lang => "en"}
+%html{:lang => "fr"}
%head
%meta{:charset => "utf-8"}/
%meta{:content => "IE=Edge,chrome=1", "http-equiv" => "X-UA-Compatible"}/
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}/
%title= @title || "Admin"
= csrf_meta_tags
- = stylesheet_link_tag :admin
+ = stylesheet_link_tag :admin, :media => :all
= javascript_include_tag "admin"
=javascript_include_tag "http://maps.google.com/maps/api/js?sensor=false®ion=FR"
@@ -19,48 +19,60 @@
%body.admin
- .navbar.navbar-inverse
- .navbar-inner{:style => "border-radius:0px;"}
- .container
- %a.btn.btn-navbar{:data => {:toggle => "collapse", :target => ".nav-collapse"}}
+ %nav.navbar.navbar-default.navbar-inverse{role: "navigation"}
+ .container-fluid
+ / Brand and toggle get grouped for better mobile display
+ .navbar-header
+ %button.navbar-toggle{"data-target" => "#bs-example-navbar-collapse-1", "data-toggle" => "collapse", type: "button"}
+ %span.sr-only Toggle navigation
%span.icon-bar
%span.icon-bar
%span.icon-bar
-
-
-
+ %a.navbar-brand{href: "/admin"}
+ Admin
-
- %a.brand{:href => "/admin"}
- =i(:home, :icon => false)
- Administration
- .collapse.nav-collapse
- %ul.nav
-
- %li= link_to "admins", admin_admins_path
- %li
- -Menu.all.each do |menu|
- = link_to "éléments de menu", admin_menu_items_path(:menu_id => menu.id)
- %li= link_to "Témoignages", admin_testimonies_path
-
- %ul.nav.pull-right
+ #bs-example-navbar-collapse-1.collapse.navbar-collapse
+ %ul.nav.navbar-nav
+ %li= link_to "admins", admin_admins_path
- %li.dropdown
- %a{:href => "#", :class => "dropdown-toggle", :data => {:toggle => "dropdown"}}
- =current_admin.firstname
- =current_admin.name
- %b.caret
- %ul.dropdown-menu
- %li.divider
- %li=link_to "se déconnecter", logout_admin_admin_auths_path
+ %li
+ -Menu.all.each do |menu|
+ = link_to "Pages", admin_menu_items_path(:menu_id => menu.id)
+
+ %li= link_to "témoignages", admin_testimonies_path
+
+
+
+
+ %li= link_to "Images", admin_image_files_path
+ %li= link_to "Fichiers", admin_data_files_path
+
+
+
+
+ %ul.nav.navbar-nav.navbar-right
+ %li.dropdown
+ %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"}
+ =current_admin.firstname
+ =current_admin.name
+ %b.caret
+ %ul.dropdown-menu
+ %li.divider
+ %li=link_to "se déconnecter", logout_admin_admin_auths_path
+
+
+
.container-fluid
= yield
-
+
+
+
#flashs= bootstrap_flash
+
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index de1ce26..4115a37 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -21,7 +21,7 @@
%body
%a{:id => "top_anchor"}
- #large
+ #large.container
#top
=link_to image_tag( "front/logo.png", :id => "logo", :alt => ""), "/"
@@ -30,11 +30,11 @@
=render(:partial => "public/shared/first_menu")
- #main.row-fluid
- .span8
+ #main.row
+ .col-md-8
=yield
- .span4.sidebar
+ .col-md-4.sidebar
=yield :sidebar
diff --git a/app/views/portlet.old/block_contents/_block_content.html.haml b/app/views/portlet.old/block_contents/_block_content.html.haml
new file mode 100644
index 0000000..aad17fe
--- /dev/null
+++ b/app/views/portlet.old/block_contents/_block_content.html.haml
@@ -0,0 +1,20 @@
+-style=""
+-if block_content.style== 2
+ -style += "background:#d8d8d8;"
+-if block_content.nbr_columns == 1
+ -block_content.blocks.each do |block|
+
+ .container_12{:style => "padding:0px;"+style.to_s}
+ .grid_12
+ =render :partial => "admin/blocks/block", :locals => {:block => block}
+ .clear
+-else
+ .container_12{:style => "padding:0px;"+style.to_s}
+ -i = 0
+ -block_content.blocks.each do |block|
+ -i+=1
+ .grid_6.col{:class => ("col_"+i.to_s)}
+
+ =render :partial => "admin/blocks/block", :locals => {:block => block}
+
+ .clear
\ No newline at end of file
diff --git a/app/views/portlet.old/block_contents/_form.html.haml b/app/views/portlet.old/block_contents/_form.html.haml
new file mode 100644
index 0000000..e5fd920
--- /dev/null
+++ b/app/views/portlet.old/block_contents/_form.html.haml
@@ -0,0 +1,89 @@
+
+=semantic_form_for( [:portlet, @block_content], :remote => true) do |f|
+ -if !@block_content.id
+ %table
+ %tr
+ %td Nombre de colonnes :
+ %td
+
+ %p
+ =f.radio_button :nbr_columns, 1
+ Une colonne
+ %p
+ =f.radio_button :nbr_columns, 2
+ Deux colonnes
+
+ %p
+ =f.radio_button :nbr_columns, 3
+ Trois colonnes
+
+ %p
+ =f.radio_button :nbr_columns, 4
+ Quatre colonnes
+
+ -else
+
+
+ #column_sliders{:style => "height:22px;"}
+ -for i in 1..(@block_content.nbr_columns.to_i-1)
+
+ .column_slider{:"data-slider-value"=>eval("@block_content.row#{i}_value.to_i"), :style => "width:100%;"}
+
+
+
+ :javascript
+ function compareNumbers(a, b)
+ {
+ return a - b;
+ }
+
+ $(".column_slider").slider({
+ max: 12,
+ min: 0,
+ step:1
+ }).on("slide", function(ev)
+ {
+ var return_array = new Array();
+
+ $("#column_sliders .column_slider").each(function(){
+ return_array.push($(this).data('slider').getValue());
+
+ });
+
+ var cols_values = [];
+ prev_value= 0;
+ $.each(return_array.sort(compareNumbers), function(index, value) {
+ cols_values.push(value-prev_value);
+
+
+ prev_value = value;
+
+ });
+
+ cols_values.push(12-prev_value);
+
+ $.each(cols_values, function(index, value) {
+
+ $("#row"+(index+1)).val(value);
+
+
+ });
+
+
+
+ });
+
+ =f.hidden_field :row1, :id => "row1"
+ =f.hidden_field :row2, :id => "row2"
+ =f.hidden_field :row3, :id => "row3"
+ =f.hidden_field :row4, :id => "row4"
+
+ -if BlockContent::STYLES.size > 0
+ Style :
+ = f.select :style, BlockContent::STYLES
+ %br
+
+
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/portlet.old/break_contents/_break_content.html.haml b/app/views/portlet.old/break_contents/_break_content.html.haml
new file mode 100644
index 0000000..a287381
--- /dev/null
+++ b/app/views/portlet.old/break_contents/_break_content.html.haml
@@ -0,0 +1 @@
+%hr
\ No newline at end of file
diff --git a/app/views/portlet.old/break_contents/_form.html.haml b/app/views/portlet.old/break_contents/_form.html.haml
new file mode 100644
index 0000000..25fd51f
--- /dev/null
+++ b/app/views/portlet.old/break_contents/_form.html.haml
@@ -0,0 +1,15 @@
+=semantic_form_for( [:portlet, @break_content], :remote => true) do |f|
+ %table.form_table
+ %tr
+ %td Trait ?
+ %td=f.check_box :line
+
+ -if BreakContent::STYLES.size > 0
+ %tr
+ %td Style :
+ %td= f.select :style, BreakContent::STYLES
+
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
diff --git a/app/views/portlet.old/download_contents/_download_content.html.haml b/app/views/portlet.old/download_contents/_download_content.html.haml
new file mode 100644
index 0000000..701df56
--- /dev/null
+++ b/app/views/portlet.old/download_contents/_download_content.html.haml
@@ -0,0 +1,8 @@
+
+%p
+ Titre :
+ =download_content.title
+
+%p
+ Téléchargement :
+ =download_content.data_file.abstract_file_name if download_content.data_file
diff --git a/app/views/portlet.old/download_contents/_form.html.haml b/app/views/portlet.old/download_contents/_form.html.haml
new file mode 100644
index 0000000..26ee980
--- /dev/null
+++ b/app/views/portlet.old/download_contents/_form.html.haml
@@ -0,0 +1,39 @@
+=semantic_form_for( [:portlet, @download_content], :remote => true) do |f|
+
+
+
+ %table.form_table
+
+ %tr
+ %td Titre :
+ %td=f.text_field :title
+
+ %tr
+ %td
+ -r = rand(1000000000000000000000000000)
+ Fichier :
+ %td
+ #name{:id => r}
+ =f.object.data_file.abstract_file_name if f.object.data_file
+ =f.hidden_field :data_file_id, :id => "input_"+r.to_s
+
+ =link_to "Modifier ce fichier", "#", :onclick => "select_file_from_manager('"+r.to_s+"');return false;"
+
+
+
+ -if DownloadContent::STYLES.size >0
+ %tr
+ %td Style :
+ %td= f.select :style, DownloadContent::STYLES
+
+
+
+
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
+
+
+
+
diff --git a/app/views/portlet.old/dynamic_contents/_dynamic_content.html.haml b/app/views/portlet.old/dynamic_contents/_dynamic_content.html.haml
new file mode 100644
index 0000000..aa8aa31
--- /dev/null
+++ b/app/views/portlet.old/dynamic_contents/_dynamic_content.html.haml
@@ -0,0 +1 @@
+=DynamicContent::NAMES[dynamic_content.name] if dynamic_content.name
\ No newline at end of file
diff --git a/app/views/portlet.old/dynamic_contents/_form.html.haml b/app/views/portlet.old/dynamic_contents/_form.html.haml
new file mode 100644
index 0000000..f4ce1e8
--- /dev/null
+++ b/app/views/portlet.old/dynamic_contents/_form.html.haml
@@ -0,0 +1,18 @@
+=semantic_form_for( [:portlet, @dynamic_content], :remote => true) do |f|
+
+
+ %table.form_table
+
+ %tr
+
+ %td= f.select :name, DynamicContent::NAMES.map {|u| [u[1], u[0]] }
+
+
+
+
+
+
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
diff --git a/app/views/portlet.old/event_contents/_event_content.html.haml b/app/views/portlet.old/event_contents/_event_content.html.haml
new file mode 100644
index 0000000..c70ffec
--- /dev/null
+++ b/app/views/portlet.old/event_contents/_event_content.html.haml
@@ -0,0 +1,48 @@
+
+-if event_content.image_file
+
+ -url =event_content.image_file.file.square.url
+
+
+
+
+-else
+ -url ="admin/default_image.png"
+-style = "float:left;"
+
+
+-styleimg=""
+
+
+
+
+%p.img{:style =>style}
+ =image_tag(url,:style => styleimg)
+
+
+
+%h3
+ Evenement -
+ =EventContent::TYPES[event_content.event_type.to_i-1][0]
+%h2=event_content.title
+%p= event_content.artist
+%p= l event_content.start_at
+%p
+ %strong=event_content.place
+ %br
+ =event_content.address
+
+%p= simple_format event_content.description
+
+
+-if event_content.with_cible?
+
+
+ - if event_content.cible
+ %strong
+ Liens vers
+ = event_content.cible.cible_name
+ ="s'ouvre dans une nouvelle page" if event_content.popup
+
+
+%p{:style => "clear:both;"}
\ No newline at end of file
diff --git a/app/views/portlet.old/event_contents/_form.html.haml b/app/views/portlet.old/event_contents/_form.html.haml
new file mode 100644
index 0000000..6dea246
--- /dev/null
+++ b/app/views/portlet.old/event_contents/_form.html.haml
@@ -0,0 +1,56 @@
+
+
+= semantic_form_for [:portlet, @event_content], :remote => true do |form|
+
+
+
+
+
+ %br
+
+
+ = form.inputs do
+
+
+ = form.input :event_type, :label => "Type d'événement :", :as => :select, :collection => EventContent::TYPES, :include_blank => false
+
+ .event_date_form{:style => "position:relative;z-index:1000;"}
+ -if form.object.errors.messages[:start_at_date] or form.object.errors.messages[:start_at_time]
+ %p.errors
+ Tout les champs doivent être remplis. Les dates doivent être au format jj/mm/yyyy et les heures au format hh:mm.
+ %p
+ =form.label :start_at_date, "Début :", :style=>"display:inline-block;width:50px"
+ =form.text_field :start_at_date, :id => "event_start_at_date", :class => "datepicker"
+ %span.event_time
+ =form.label :start_at_time, "heure :"
+ =form.text_field :start_at_time, :id => "event_start_at_time", :class => "timepicker", :style => "width:50px"
+
+
+
+ = form.input :image_file_id, :label => "Image :" , :as => :qi_image_select
+
+
+ = form.input :title, :label => "Titre :"
+ = form.input :artist, :label => "Artiste :"
+ = form.input :tremplin, :label => "Tremplin ?", :as => :boolean
+ = form.input :description, :label => "Description :", :as => :text
+
+ = form.input :place, :label => "Lieu :"
+ = form.input :address, :label => "Adresse :", :as => :text
+
+
+
+ = form.input :with_cible, :as => :boolean, :label => "Avec lien ?", :input_html => { :onchange => "if ($('#with_cible').is(':checked')) { $('#with_cible').closest('form').find('.cible_space').show(); }else{ $('#with_cible').closest('form').find('.cible_space').hide(); }", :id => "with_cible" }, :label_html => {:onchange => ""}
+
+
+
+
+ .cible_space{:style => ((!@event_content.cible and !@event_content.with_cible) ? "display:none;" : "display:block;" )}
+ = form.inputs do
+ = form.input :cible, :label => "Cible :" , :as => :qi_cible_select
+ = form.input :popup, :label => "Ouvrir dans une popup ?", :as => :boolean
+
+
+ = form.submit "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/portlet.old/gallery_contents/_form.html.haml b/app/views/portlet.old/gallery_contents/_form.html.haml
new file mode 100644
index 0000000..0a03a59
--- /dev/null
+++ b/app/views/portlet.old/gallery_contents/_form.html.haml
@@ -0,0 +1,9 @@
+= semantic_form_for [:portlet, @gallery_content], :remote => true do |form|
+
+ -if GalleryContent::STYLES.size > 0
+ Style :
+ = form.select :style, GalleryContent::STYLES
+
+ = form.submit "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/portlet.old/gallery_contents/_gallery_content.html.haml b/app/views/portlet.old/gallery_contents/_gallery_content.html.haml
new file mode 100644
index 0000000..e8e2953
--- /dev/null
+++ b/app/views/portlet.old/gallery_contents/_gallery_content.html.haml
@@ -0,0 +1,18 @@
+%h2=gallery_content.name
+.description
+ =raw gallery_content.description
+
+%p{:style => "text-align:center;"}=link_to "Ajouter des images", "#", :onclick => "select_gallery_images_from_manager('"+gallery_content.id.to_s+"');return false;", :class => "btn"
+
+.gallery_images
+ =render :collection => gallery_content.gallery_images, :partial => "portlet/gallery_images/gallery_image"
+ %p{:style => "clear:both;"}
+
+:javascript
+ $('.gallery_images').sortable({
+ itemSelector:".gallery_image",
+ nested:true
+ });
+
+
+
\ No newline at end of file
diff --git a/app/views/portlet.old/gallery_images/_form.html.haml b/app/views/portlet.old/gallery_images/_form.html.haml
new file mode 100644
index 0000000..d64ae28
--- /dev/null
+++ b/app/views/portlet.old/gallery_images/_form.html.haml
@@ -0,0 +1,32 @@
+#myModal.modal.fade{"aria-hidden" => "true", "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1"}
+
+
+
+
+ .modal-header
+ %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
+ %h3#myModalLabel Modifier les infos
+ .modal-body
+
+ = semantic_form_for [:portlet, @gallery_image], :remote => true do |form|
+ = form.inputs do
+ = form.input :title, :label => "Titre :"
+ = form.input :tags, :label => "Tags :"
+ = form.input :description, :label => "Description :", :as => :text, :input_html => {:class => "text_editor"}
+
+
+
+
+
+ .modal-footer
+ %button.btn{"aria-hidden" => "true", "data-dismiss" => "modal"} Annuler
+ %button.btn.btn-primary{"aria-hidden" => "true", "data-dismiss" => "modal", :onclick => "$(this).closest('.modal').find('form').submit();"} Sauvegarder
+
+
+
+
+
+
+
+
+
diff --git a/app/views/portlet.old/gallery_images/_gallery_image.html.haml b/app/views/portlet.old/gallery_images/_gallery_image.html.haml
new file mode 100644
index 0000000..39ec3d5
--- /dev/null
+++ b/app/views/portlet.old/gallery_images/_gallery_image.html.haml
@@ -0,0 +1,9 @@
+-if gallery_image.image_file
+ .gallery_image.image_square#gallery_image{:id => gallery_image.id, :data => { :title => gallery_image.title , :description => gallery_image.description, :id => gallery_image.id} }
+ .img{:style => "background-image : url('#{gallery_image.image_file.file.large.medium.small.thumb.url}');"}
+
+ .actions
+ =link_to i(:trash), [:portlet, gallery_image], :confirm => 'Voulez-vous vraiment supprimer cette image ?', :method => :delete, :remote => true
+ =link_to i(:pencil), edit_portlet_gallery_image_path(gallery_image), :remote => true
+
+
\ No newline at end of file
diff --git a/app/views/portlet.old/gallery_images/create.js.erb b/app/views/portlet.old/gallery_images/create.js.erb
new file mode 100644
index 0000000..8b50597
--- /dev/null
+++ b/app/views/portlet.old/gallery_images/create.js.erb
@@ -0,0 +1 @@
+$('#portlet_<%= @gallery_content.portlet.id %> .gallery_images').prepend("<%= escape_javascript(render(@gallery_images)) %>");
\ No newline at end of file
diff --git a/app/views/portlet.old/gallery_images/destroy.js.erb b/app/views/portlet.old/gallery_images/destroy.js.erb
new file mode 100644
index 0000000..c4e8f8a
--- /dev/null
+++ b/app/views/portlet.old/gallery_images/destroy.js.erb
@@ -0,0 +1,4 @@
+
+$("#gallery_image_<%= @gallery_image.id.to_s %>").fadeOut(500).delay(6000).remove();
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/gallery_images/edit.js.erb b/app/views/portlet.old/gallery_images/edit.js.erb
new file mode 100644
index 0000000..0412d2c
--- /dev/null
+++ b/app/views/portlet.old/gallery_images/edit.js.erb
@@ -0,0 +1,2 @@
+
+$('<%= escape_javascript(render(:partial => "form"))%>').modal('show');
diff --git a/app/views/portlet.old/gallery_images/reorder.js.erb b/app/views/portlet.old/gallery_images/reorder.js.erb
new file mode 100644
index 0000000..e69de29
diff --git a/app/views/portlet.old/gallery_images/update.js.erb b/app/views/portlet.old/gallery_images/update.js.erb
new file mode 100644
index 0000000..7f4b7c8
--- /dev/null
+++ b/app/views/portlet.old/gallery_images/update.js.erb
@@ -0,0 +1,5 @@
+close_pane_hover();
+$('#gallery_image_<%= @gallery_image.id %>').effect("highlight", 1000);
+
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/html_contents/_form.html.haml b/app/views/portlet.old/html_contents/_form.html.haml
new file mode 100644
index 0000000..347a6e9
--- /dev/null
+++ b/app/views/portlet.old/html_contents/_form.html.haml
@@ -0,0 +1,60 @@
+.html_content_form
+
+ =semantic_form_for( [:portlet, @html_content], :remote => true) do |f|
+
+
+ =f.text_area :content, :style => "width:98%;height:400px;", :class => "inputText", :id => "ace_editor_textarea"
+
+ %pre#ace_editor_pre{:style => "margin:0px;"}
+
+
+
+
+ %table.form_table
+ %tr
+ %td Style :
+ %td= f.select :content_type, HtmlContent::CONTENT_TYPES
+
+
+
+ .action
+ %button{:onclick => "$(this).closest('.html_content_form').toggleClass('large');editor.resize() ;return false;"} zoom
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
+
+
+
+
+
+
+ -if HtmlContent::STYLES.size > 0
+ %table.form_table
+ %tr
+ %td Style :
+ %td= f.select :style, HtmlContent::STYLES
+
+
+
diff --git a/app/views/portlet.old/html_contents/_html_content.html.haml b/app/views/portlet.old/html_contents/_html_content.html.haml
new file mode 100644
index 0000000..bfdff74
--- /dev/null
+++ b/app/views/portlet.old/html_contents/_html_content.html.haml
@@ -0,0 +1,11 @@
+-begin
+ =render :inline => html_content.content, :type => html_content.content_type
+-rescue Exception=>e
+ -if html_content.content_type == "haml"
+ %h3= e.message
+ %p
+ à la ligne
+ = e.original_exception.line
+
+ -else
+ %h3= e.message
diff --git a/app/views/portlet.old/image_contents/_form.html.haml b/app/views/portlet.old/image_contents/_form.html.haml
new file mode 100644
index 0000000..7056bf1
--- /dev/null
+++ b/app/views/portlet.old/image_contents/_form.html.haml
@@ -0,0 +1,32 @@
+
+
+= semantic_form_for [:portlet, @image_content], :remote => true do |form|
+
+ = form.inputs do
+ = form.input :image_file_id, :label => "Image :" , :as => :qi_image_select
+
+
+ = form.input :alt, :label => "Texte alternatif :"
+
+ = form.input :alignement, :label => "Alignement :", :as => :select, :collection => ImageContent::ALIGNS, :include_blank => false
+ = form.input :style, :label => "Style :", :as => :select, :collection => ImageContent::STYLES, :include_blank => false
+ = form.input :width, :label => "Largeur :"
+ = form.input :height, :label => "Hauteur :"
+
+
+ = form.input :with_cible, :as => :boolean, :label => "Avec lien ?", :input_html => { :onchange => "if ($('#with_cible').is(':checked')) { $('#with_cible').closest('form').find('.cible_space').show();$('#with_cible').closest('form').find('.expandable').hide(); }else{ $('#with_cible').closest('form').find('.cible_space').hide();$('#with_cible').closest('form').find('.expandable').show(); }", :id => "with_cible" }, :label_html => {:onchange => ""}
+
+ .expandable{:style => ((!@image_content.cible and !@image_content.with_cible) ? "display:block;" : "display:none;" )}
+ = form.inputs do
+ = form.input :expandable,:as => :boolean , :label => "L'image peut être agrandie ? :"
+
+
+ .cible_space{:style => ((!@image_content.cible and !@image_content.with_cible) ? "display:none;" : "display:block;" )}
+ = form.inputs do
+ = form.input :cible, :label => "Cible :" , :as => :qi_cible_select
+ = form.input :popup, :label => "Ouvrir dans une popup ?", :as => :boolean
+
+
+ = form.submit "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/portlet.old/image_contents/_image_content.html.haml b/app/views/portlet.old/image_contents/_image_content.html.haml
new file mode 100644
index 0000000..4d10c9a
--- /dev/null
+++ b/app/views/portlet.old/image_contents/_image_content.html.haml
@@ -0,0 +1,42 @@
+
+-if image_content.image_file
+
+ -if image_content.style== "1"
+ -url =image_content.image_file.file.large.medium.url
+
+ -elsif image_content.style== "2"
+ -url =image_content.image_file.file.large.medium.small.url
+
+ -elsif image_content.style== "3"
+ -url =image_content.image_file.file.square.url
+
+ -elsif image_content.style== "4"
+ -url =image_content.image_file.file.large.medium.small.thumb.url
+ -elsif image_content.style== "5"
+ -url =image_content.image_file.file.large.url
+
+
+ =image_content.style
+
+-else
+ -url ="admin/default_image.png"
+-style = ""
+-style = "text-align:center;" if image_content.alignement == "center"
+
+
+-style = "text-align:right;" if image_content.alignement == "right"
+
+
+-style = "text-align:left;" if image_content.alignement == "left"
+
+-styleimg=""
+-styleimg += "width:"+image_content.width.to_s+"px;" if image_content.width?
+-styleimg += "height:"+image_content.height.to_s+"px;" if image_content.height?
+
+
+
+%p.img{:style =>style}
+ =image_tag(url, :alt => image_content.alt.to_s, :style => styleimg)
+
+
+="L'image peut être agrandie si l'on clique dessus" if image_content.expandable
\ No newline at end of file
diff --git a/app/views/portlet.old/img_link_contents/_form.html.haml b/app/views/portlet.old/img_link_contents/_form.html.haml
new file mode 100644
index 0000000..0375fad
--- /dev/null
+++ b/app/views/portlet.old/img_link_contents/_form.html.haml
@@ -0,0 +1,20 @@
+= semantic_form_for [:portlet, @img_link_content], :remote => true do |form|
+
+ .form1
+ = form.inputs do
+
+ = form.input :image_file_id, :label => "Image :" , :as => :qi_image_select
+ = form.input :title, :label => "Title :" , :as => :string
+ = form.input :description, :label => "Description :", :as => :text, :input_html => {:class => "text_editor"}
+
+
+
+ = form.input :with_cible, :as => :boolean, :label => "Avec lien ?", :input_html => {:id => "with_cible", :onchange => "if ($(this).attr('checked') == 'checked') { $(this).closest('form').find('.cible_space').show(); }else{ $(this).closest('form').find('.cible_space').hide(); }" }
+
+ .cible_space{:style => ("display:none;" if !@img_link_content.cible and !@img_link_content.with_cible )}
+ = form.inputs do
+ = form.input :cible, :label => "Cible :" , :as => :qi_cible_select
+
+ = form.commit_button "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/portlet.old/img_link_contents/_img_link_content.html.haml b/app/views/portlet.old/img_link_contents/_img_link_content.html.haml
new file mode 100644
index 0000000..ed06422
--- /dev/null
+++ b/app/views/portlet.old/img_link_contents/_img_link_content.html.haml
@@ -0,0 +1,16 @@
+
+
+.img_link_portlet
+ .image_file
+ =image_tag(img_link_content.image_file.file.square.url) if img_link_content.image_file
+
+ .title
+ %h3=img_link_content.title
+ .description
+ = simple_format(img_link_content.description)
+ .clear
+
+- if img_link_content.cible
+ %strong
+ Liens vers
+ = img_link_content.cible.cible_name
\ No newline at end of file
diff --git a/app/views/portlet.old/link_contents/_form.html.haml b/app/views/portlet.old/link_contents/_form.html.haml
new file mode 100644
index 0000000..d6e906f
--- /dev/null
+++ b/app/views/portlet.old/link_contents/_form.html.haml
@@ -0,0 +1,14 @@
+= semantic_form_for [:portlet, @link_content], :remote => true do |form|
+
+ .form1
+ = form.inputs do
+ = form.input :name, :label => "Texte à afficher :"
+ =# form.input :title, :label => "Title :"
+ = form.input :popup,:as => :boolean , :label => "Ouvrir dans une nouvelle fenêtre ?"
+
+ = form.input :cible, :label => "Cible :" , :as => :qi_cible_select
+
+
+ = form.submit "Sauvegarder", :class => "btn btn-primary"
+
+
diff --git a/app/views/portlet.old/link_contents/_link_content.html.haml b/app/views/portlet.old/link_contents/_link_content.html.haml
new file mode 100644
index 0000000..20387b2
--- /dev/null
+++ b/app/views/portlet.old/link_contents/_link_content.html.haml
@@ -0,0 +1,10 @@
+
+Texte affiché :
+%strong=link_content.name.to_s
+%br
+="s'ouvre dans une nouvelle page" if link_content.popup
+
+- if link_content.cible
+ %strong
+ Liens vers
+ = link_content.cible.cible_name
\ No newline at end of file
diff --git a/app/views/portlet.old/map_contents/_form.html.haml b/app/views/portlet.old/map_contents/_form.html.haml
new file mode 100644
index 0000000..3298e04
--- /dev/null
+++ b/app/views/portlet.old/map_contents/_form.html.haml
@@ -0,0 +1,26 @@
+=semantic_form_for( [:portlet, @map_content], :remote => true) do |f|
+
+ %p
+ Adresse :
+ =f.text_field :address, :style => "width:98%;", :class => "inputText"
+
+ %p
+ Nom du lieu :
+ =f.text_field :name, :style => "width:98%;", :class => "inputText"
+
+ %p
+ Infobule
+ =f.check_box :info_bule
+
+ %p
+ Vue
+ = f.select :view, MapContent::VIEWS
+
+ %p
+ Zoom
+ = f.select :zoom, MapContent::ZOOMS
+ %br
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
diff --git a/app/views/portlet.old/map_contents/_map_content.html.haml b/app/views/portlet.old/map_contents/_map_content.html.haml
new file mode 100644
index 0000000..54e9ac9
--- /dev/null
+++ b/app/views/portlet.old/map_contents/_map_content.html.haml
@@ -0,0 +1,64 @@
+#map_content_map.map_content_map{:id => map_content.id, :style => "width:400px; height:300px;margin:auto;"}
+
+
+
+
\ No newline at end of file
diff --git a/app/views/portlet.old/portlets/_portlet.html.haml b/app/views/portlet.old/portlets/_portlet.html.haml
new file mode 100644
index 0000000..54c8dc6
--- /dev/null
+++ b/app/views/portlet.old/portlets/_portlet.html.haml
@@ -0,0 +1,34 @@
+
+
+
+#portlet.portlet{:id => portlet.id,:"data-portlet_id" => portlet.id, :class => "portlet_"+portlet.content_type.tableize.singularize+(" " if portlet.content_type == "BlockContent").to_s}
+
+
+ -if portlet.content_type == "BlockContent"
+ .btn-toolbar{:style => "position:absolute;margin-left:10px;margin-top:-3em;"}
+ .btn-group
+ %a.btn.handle{:href => "#"}=i :move, :icon => false
+ =link_to i(:pencil, :icon => false), eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :remote => true, :class => "btn"
+ =link_to i(:trash, :icon => false), eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn"
+
+
+
+
+
+ -else
+ .btn-toolbar{:style => "position:absolute;margin-left:10px;z-index:1;"}
+ .btn-group
+ %a.btn.handle{:href => "#"}=i :move, :icon => false
+ =link_to i(:pencil, :icon => false), eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :remote => true, :class => "btn"
+ =link_to i(:trash, :icon => false), eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn"
+
+
+
+
+
+
+
+ =render :partial => "portlets/render_public/"+portlet.content_type.to_s.downcase, :locals => {:input => portlet.content, :admin => true}
+
+
+
\ No newline at end of file
diff --git a/app/views/portlet.old/portlets/new.html.haml b/app/views/portlet.old/portlets/new.html.haml
new file mode 100644
index 0000000..80d216a
--- /dev/null
+++ b/app/views/portlet.old/portlets/new.html.haml
@@ -0,0 +1,7 @@
+.portlet_types
+ -ContentType.all.each do |content_type|
+ =link_to content_type.name, eval("new_portlet_"+content_type.slug.tableize.singularize+"_path(:block_id => @portlet.block_id, :position => params[:position])"), :remote => true
+
+%br
+%br
+#new_portlet_content_form
\ No newline at end of file
diff --git a/app/views/portlet.old/portlets/new.js.erb b/app/views/portlet.old/portlets/new.js.erb
new file mode 100644
index 0000000..09bde8f
--- /dev/null
+++ b/app/views/portlet.old/portlets/new.js.erb
@@ -0,0 +1,12 @@
+$.ajax({
+ url:"<%= eval("new_portlet_"+params[:content_type].tableize.singularize+"_path(:format => 'js')") %>",
+ type: "GET",
+ data: {
+ block_id : "<%= params[:block_id] %>",
+ position : "<%= params[:position] %>"
+ } ,
+ success : function (){
+
+ }
+});
+
diff --git a/app/views/portlet.old/portlets/update.js.erb b/app/views/portlet.old/portlets/update.js.erb
new file mode 100644
index 0000000..3438a65
--- /dev/null
+++ b/app/views/portlet.old/portlets/update.js.erb
@@ -0,0 +1,8 @@
+
+
+
+$("#block_portlets_<%= @portlet.block.id %>").replaceWith("<%= escape_javascript(render(:partial => 'admin/blocks/block', :locals => {:block => @portlet.block})) %>");
+$("#portlet_<%= @portlet.id %>").effect("highlight", {}, 3000);
+block_js_initialize();
+
+<%= flash_notice() %>
\ No newline at end of file
diff --git a/app/views/portlet.old/shared/_new.html.haml b/app/views/portlet.old/shared/_new.html.haml
new file mode 100644
index 0000000..3f49e23
--- /dev/null
+++ b/app/views/portlet.old/shared/_new.html.haml
@@ -0,0 +1,6 @@
+=render :partial => "form"
+
+-cancel_button = escape_javascript(link_to("annuler", "#", :class => "button cancel", :onclick => "$('#new_portlet_form_inline').remove();block_js_initialize();return false;"));
+:javascript
+ $('#new_portlet_form_inline').find('.buttons ol').prepend('#{cancel_button}');
+
\ No newline at end of file
diff --git a/app/views/portlet.old/shared/create.js.erb b/app/views/portlet.old/shared/create.js.erb
new file mode 100644
index 0000000..ec20433
--- /dev/null
+++ b/app/views/portlet.old/shared/create.js.erb
@@ -0,0 +1,13 @@
+block_portlet_id = $("#new_portlet_form_inline").closest(".block_portlets").data('block_id');
+
+$("#new_portlet_form_inline").replaceWith("<%= escape_javascript(render(@portlet)) %>");
+
+
+
+
+update_block_portlet_order(block_portlet_id);
+
+
+$(".block_portlets").sortable("enable");
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/shared/destroy.js.erb b/app/views/portlet.old/shared/destroy.js.erb
new file mode 100644
index 0000000..64fd98f
--- /dev/null
+++ b/app/views/portlet.old/shared/destroy.js.erb
@@ -0,0 +1,4 @@
+$("#portlet_<%= @portlet.id %>").remove();
+<%= flash_js %>
+block_js_initialize();
+update_portlet_order();
\ No newline at end of file
diff --git a/app/views/portlet.old/shared/edit.js.erb b/app/views/portlet.old/shared/edit.js.erb
new file mode 100644
index 0000000..6e09501
--- /dev/null
+++ b/app/views/portlet.old/shared/edit.js.erb
@@ -0,0 +1,18 @@
+$("#portlet_<%= @portlet.id %>").html("
");
+
+$("#edit_portlet_content_form").html("<%= escape_javascript(render( :partial => "form")) %>");
+
+$(".block_portlets").sortable("disable");
+
+
+$("#edit_portlet_content_form .text_editor").each(function() {
+
+
+ auto_tiny_mce($(this));
+});
+
+<%- cancel_button = escape_javascript(link_to("annuler", portlet_portlet_path(@portlet), :class => "button cancel", :remote => true)); %>
+$("#portlet_<%= @portlet.id %>").find('.buttons ol').prepend('<%= cancel_button %>');
+
+
+
diff --git a/app/views/portlet.old/shared/new.js.erb b/app/views/portlet.old/shared/new.js.erb
new file mode 100644
index 0000000..d8a994a
--- /dev/null
+++ b/app/views/portlet.old/shared/new.js.erb
@@ -0,0 +1,21 @@
+$("#new_portlet_content_form").html("<%= escape_javascript(render( :partial => "portlet/shared/new")) %>");
+
+$(".block_portlets").sortable("disable");
+
+
+
+var first_form_element = $("#new_portlet_content_form input:text:visible:first")
+if(first_form_element.length == 0){
+ first_form_element = $("#new_portlet_content_form .text_editor:first")
+
+ //first_form_element.tinymce().focus();
+}
+
+if(first_form_element.length == 0){
+ first_form_element = $("#new_portlet_content_form textarea:first")
+}
+
+
+first_form_element.focus();
+
+uninitialize_block_js();
diff --git a/app/views/portlet.old/shared/update.js.erb b/app/views/portlet.old/shared/update.js.erb
new file mode 100644
index 0000000..d47c241
--- /dev/null
+++ b/app/views/portlet.old/shared/update.js.erb
@@ -0,0 +1,7 @@
+
+$("#portlet_<%= @portlet.id %>").replaceWith("<%= escape_javascript(render(@portlet)) %>");
+
+
+$(".block_portlets").sortable("enable");
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/table_cols/create.js.erb b/app/views/portlet.old/table_cols/create.js.erb
new file mode 100644
index 0000000..2db2ece
--- /dev/null
+++ b/app/views/portlet.old/table_cols/create.js.erb
@@ -0,0 +1,4 @@
+
+$("#portlet_<%= @table_content.portlet.id %>").replaceWith("<%= escape_javascript(render(@table_content.portlet)) %>");
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/table_cols/destroy.js.erb b/app/views/portlet.old/table_cols/destroy.js.erb
new file mode 100644
index 0000000..2db2ece
--- /dev/null
+++ b/app/views/portlet.old/table_cols/destroy.js.erb
@@ -0,0 +1,4 @@
+
+$("#portlet_<%= @table_content.portlet.id %>").replaceWith("<%= escape_javascript(render(@table_content.portlet)) %>");
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/table_contents/_form.html.haml b/app/views/portlet.old/table_contents/_form.html.haml
new file mode 100644
index 0000000..d194428
--- /dev/null
+++ b/app/views/portlet.old/table_contents/_form.html.haml
@@ -0,0 +1,22 @@
+
+=semantic_form_for( [:portlet, @table_content], :remote => true) do |f|
+
+
+ -if !@table_content.id
+ %table
+ %tr
+ %td Nombre de lignes :
+ %td=f.text_field :nbr_rows
+ %tr
+ %td Nombre de colonnes :
+ %td=f.text_field :nbr_cols
+
+ -if BlockContent::STYLES.size > 0
+ Style :
+ = f.select :style, TableContent::STYLES
+
+ %br
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
diff --git a/app/views/portlet.old/table_contents/_table_content.html.haml b/app/views/portlet.old/table_contents/_table_content.html.haml
new file mode 100644
index 0000000..bf948ab
--- /dev/null
+++ b/app/views/portlet.old/table_contents/_table_content.html.haml
@@ -0,0 +1,46 @@
+
+
+
+%table.table_content
+ -table_rows = table_content.table_rows
+ %tr
+ -i = 0
+ -table_content.nbr_cols.times do
+ -i += 1
+ %td.add_col
+ %span.innerWrapper
+ .col_menu
+ =link_to "Ajouter une colonne avant", portlet_table_cols_path(:position => i, :table_content_id =>table_content.id ), :method => :post, :remote => true
+
+ =link_to "Ajouter une colonne après", portlet_table_cols_path(:position => i+1, :table_content_id =>table_content.id ), :method => :post, :remote => true
+
+ -if table_content.nbr_cols > 1
+ =link_to "Supprimer cette colonne", portlet_table_col_path(:id => i, :table_content_id =>table_content.id ), :method => :delete, :remote => true, :confirm => "Voulez-vous vraiment supprimer cette colonne ?"
+ = i(:cog_alt, :gray_light, 12)
+
+ %td
+
+ -table_rows.each do |table_row|
+ %tr{:id => table_row.id}
+
+
+ -CelTable.where(:table_row_id => table_row.id).order("position ASC").each do |cel_table|
+
+ %td.table_content_cel{:id => cel_table.id}
+
+ =render :partial => "admin/blocks/block", :locals => {:block => cel_table.block}
+
+ %td.add_cel
+
+ .innerWrapper
+ .row_menu
+ =link_to "Ajouter un rang avant", portlet_table_rows_path(:table_row => {:table_content_id => table_content.id, :position => (table_row.position)}), :method => :post, :remote => true
+
+ =link_to "Ajouter un rang après", portlet_table_rows_path(:table_row => {:table_content_id => table_content.id, :position => (table_row.position+1)}), :method => :post, :remote => true
+ -if table_content.nbr_rows > 1
+ =link_to "Supprimer ce rang", portlet_table_row_path(table_row), :method => :delete, :remote => true, :confirm => "Voulez-vous vraiment supprimer ce rang ?"
+ = i(:cog_alt, :gray_light, 12)
+
+
+
+
\ No newline at end of file
diff --git a/app/views/portlet.old/table_contents/_table_content_edit_pane.html.haml b/app/views/portlet.old/table_contents/_table_content_edit_pane.html.haml
new file mode 100644
index 0000000..7d42a41
--- /dev/null
+++ b/app/views/portlet.old/table_contents/_table_content_edit_pane.html.haml
@@ -0,0 +1,33 @@
+%table.table_content
+ -table_rows = @table_content.table_rows
+ %tr
+
+
+
+
+ -table_rows.each do |table_row|
+ %tr
+ %td.row_left
+ .crl
+ %a{:href => "#", :onclick => "$('.table_row_menu').hide();$('#table_row_menu_"+table_row.id.to_s+"').toggle();return false;"}+
+
+
+
+
+ .table_row_menu#table_row_menu{:id => table_row.id}
+ =link_to "ajouter un rang avant", portlet_table_rows_path(:table_row => {:table_content_id => @table_content.id, :position => (table_row.position)}), :method => :post
+ %br
+ =link_to "ajouter un rang après", portlet_table_rows_path(:table_row => {:table_content_id => @table_content.id, :position => (table_row.position+1)}), :method => :post
+ %br
+ =link_to "supprimer ce rang", [:portlet, table_row], :method => :delete, :confirm => "Voulez-vous vraiment supprimer ce rang ainsi que son contenu ?", :remote => true
+
+ -table_row.cel_tables.each do |cel_table|
+
+ %td.table_content_cel
+ =auto_load_div(admin_block_path(cel_table.block),"Page_"+"@page.id.to_s"+"_blocks_part")
+
+ %td.add_col
+ %span +
+ -@table_content.nbr_cols.times do
+ %td.add_col
+ %span +f
diff --git a/app/views/portlet.old/table_contents/destroy_row.js.erb b/app/views/portlet.old/table_contents/destroy_row.js.erb
new file mode 100644
index 0000000..8fd1b2d
--- /dev/null
+++ b/app/views/portlet.old/table_contents/destroy_row.js.erb
@@ -0,0 +1,6 @@
+
+
+
+
+$("#table_content_edit_pane_<%= @table_content.id %>").html("<%= escape_javascript(render(:partial => "portlet/table_contents/table_content_edit_pane")) %>");
+<%= flash_notice() %>
\ No newline at end of file
diff --git a/app/views/portlet.old/table_rows/create.js.erb b/app/views/portlet.old/table_rows/create.js.erb
new file mode 100644
index 0000000..928d700
--- /dev/null
+++ b/app/views/portlet.old/table_rows/create.js.erb
@@ -0,0 +1,4 @@
+
+$("#portlet_<%= @portlet.id %>").replaceWith("<%= escape_javascript(render(@portlet)) %>");
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/table_rows/destroy.js.erb b/app/views/portlet.old/table_rows/destroy.js.erb
new file mode 100644
index 0000000..687bbba
--- /dev/null
+++ b/app/views/portlet.old/table_rows/destroy.js.erb
@@ -0,0 +1,4 @@
+
+$("#portlet_<%= @table_row.table_content.portlet.id %>").replaceWith("<%= escape_javascript(render(@table_row.table_content.portlet)) %>");
+
+<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet.old/text_contents/_form.html.haml b/app/views/portlet.old/text_contents/_form.html.haml
new file mode 100644
index 0000000..0a3cd7d
--- /dev/null
+++ b/app/views/portlet.old/text_contents/_form.html.haml
@@ -0,0 +1,35 @@
+=semantic_form_for( [:portlet, @text_content], :remote => true) do |f|
+
+ %p{:style => "text-align:center;"}= f.submit "Sauvegarder", :class => "btn btn-primary"
+
+ =f.text_area :content, :style => "width:98%;height:600px;", :class => "redactor_content"
+
+ #toolbar-text
+
+
+ -if TextContent::STYLES.size > 0
+ Style :
+ = f.select :style, TextContent::STYLES
+
+
+
+
+
+ :javascript
+
+ $('.redactor_content').redactor({
+ toolbarExternal: '#toolbar-text',
+
+ lang: 'fr',
+ buttons : ['html', '|', 'formatting', '|', 'bold', 'italic', 'deleted','underline','|', 'alignleft', 'aligncenter', 'alignright', 'justify', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'table', 'link', '|','fontcolor', 'backcolor','|', 'horizontalrule']
+
+
+ });
+
+
+
+
+
+
+
+
diff --git a/app/views/portlet.old/text_contents/_text_content.html.haml b/app/views/portlet.old/text_contents/_text_content.html.haml
new file mode 100644
index 0000000..afdbae0
--- /dev/null
+++ b/app/views/portlet.old/text_contents/_text_content.html.haml
@@ -0,0 +1 @@
+%p=raw text_content.content
\ No newline at end of file
diff --git a/app/views/portlet.old/title_contents/_form.html.haml b/app/views/portlet.old/title_contents/_form.html.haml
new file mode 100644
index 0000000..c0c9db3
--- /dev/null
+++ b/app/views/portlet.old/title_contents/_form.html.haml
@@ -0,0 +1,15 @@
+=semantic_form_for( [:portlet, @title_content], :remote => true) do |f|
+
+ =f.text_field :content, :style => "width:98%;", :class => "inputText"
+
+ Importance :
+ = f.select :level, TitleContent::LEVELS
+ -if TitleContent::STYLES.size > 0
+ Style :
+ = f.select :style, TitleContent::STYLES
+ %br
+
+ = f.submit "Sauvegarder", :class => "btn btn-primary"
+
+
+
diff --git a/app/views/portlet.old/title_contents/_title_content.html.haml b/app/views/portlet.old/title_contents/_title_content.html.haml
new file mode 100644
index 0000000..c394932
--- /dev/null
+++ b/app/views/portlet.old/title_contents/_title_content.html.haml
@@ -0,0 +1,4 @@
+=raw '"
+=title_content.content
+=raw " "
+
diff --git a/app/views/portlet/gallery_images/_gallery_image.html.haml b/app/views/portlet/gallery_images/_gallery_image.html.haml
index 39ec3d5..46def24 100644
--- a/app/views/portlet/gallery_images/_gallery_image.html.haml
+++ b/app/views/portlet/gallery_images/_gallery_image.html.haml
@@ -3,7 +3,7 @@
.img{:style => "background-image : url('#{gallery_image.image_file.file.large.medium.small.thumb.url}');"}
.actions
- =link_to i(:trash), [:portlet, gallery_image], :confirm => 'Voulez-vous vraiment supprimer cette image ?', :method => :delete, :remote => true
+ =link_to i(:"trash-o"), [:portlet, gallery_image], :confirm => 'Voulez-vous vraiment supprimer cette image ?', :method => :delete, :remote => true
=link_to i(:pencil), edit_portlet_gallery_image_path(gallery_image), :remote => true
\ No newline at end of file
diff --git a/app/views/portlet/portlets/_portlet.html.haml b/app/views/portlet/portlets/_portlet.html.haml
index 54c8dc6..03542d8 100644
--- a/app/views/portlet/portlets/_portlet.html.haml
+++ b/app/views/portlet/portlets/_portlet.html.haml
@@ -1,15 +1,12 @@
-
-
-
-#portlet.portlet{:id => portlet.id,:"data-portlet_id" => portlet.id, :class => "portlet_"+portlet.content_type.tableize.singularize+(" " if portlet.content_type == "BlockContent").to_s}
+#portlet.portlet{:"data-show-link" => eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id, :format => :js)"), :"data-edit-link" => eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id, :format => :js)"), :id => portlet.id,:"data-portlet_id" => portlet.id, :class => "portlet_"+portlet.content_type.tableize.singularize+(" " if portlet.content_type == "BlockContent").to_s}
-if portlet.content_type == "BlockContent"
- .btn-toolbar{:style => "position:absolute;margin-left:10px;margin-top:-3em;"}
+ .btn-toolbar{:style => "position:absolute;margin-left:150px;margin-top:5px;"}
.btn-group
- %a.btn.handle{:href => "#"}=i :move, :icon => false
- =link_to i(:pencil, :icon => false), eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :remote => true, :class => "btn"
- =link_to i(:trash, :icon => false), eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn"
+ %a.btn.handle{:href => "#"}=ic :arrows
+ =link_to ic(:pencil), eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :remote => true, :class => "btn"
+ =link_to ic(:"trash-o"), eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn"
@@ -18,9 +15,9 @@
-else
.btn-toolbar{:style => "position:absolute;margin-left:10px;z-index:1;"}
.btn-group
- %a.btn.handle{:href => "#"}=i :move, :icon => false
- =link_to i(:pencil, :icon => false), eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :remote => true, :class => "btn"
- =link_to i(:trash, :icon => false), eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn"
+ %a.btn.btn-default.portlet_handle{:href => "#", :data => {:portlet_id => portlet.id}}=ic :arrows
+ =link_to ic(:pencil), eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :remote => true, :class => "btn btn-default"
+ =link_to ic(:"trash-o"), eval("portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)"), :method => :delete, :data => { :confirm => "Etes-vous sûr ?"}, :remote => true, :class => "btn btn-default"
@@ -28,7 +25,4 @@
- =render :partial => "portlets/render_public/"+portlet.content_type.to_s.downcase, :locals => {:input => portlet.content, :admin => true}
-
-
-
\ No newline at end of file
+ =render :partial => "portlets/render_public/"+portlet.content_type.to_s.downcase, :locals => {:input => portlet.content, :admin => true, :edit_link => eval("edit_portlet_"+portlet.content_type.tableize.singularize+"_path(portlet.content, :portlet_id => portlet.id)") }
\ No newline at end of file
diff --git a/app/views/portlet/shared/edit.js.erb b/app/views/portlet/shared/edit.js.erb
index 6e09501..c424788 100644
--- a/app/views/portlet/shared/edit.js.erb
+++ b/app/views/portlet/shared/edit.js.erb
@@ -1,18 +1,22 @@
-$("#portlet_<%= @portlet.id %>").html("
");
+//$("#portlet_<%= @portlet.id %>").html("
");
-$("#edit_portlet_content_form").html("<%= escape_javascript(render( :partial => "form")) %>");
+//$("#edit_portlet_content_form").html("<%= escape_javascript(render( :partial => "form")) %>");
-$(".block_portlets").sortable("disable");
+$("#element_form").html("<%= escape_javascript(render( :partial => "form")) %>");
-$("#edit_portlet_content_form .text_editor").each(function() {
+$("#collapse2").collapse('hide');
+$("#collapse3").collapse('show');
+//$(".block_portlets").sortable("disable");
+
- auto_tiny_mce($(this));
-});
<%- cancel_button = escape_javascript(link_to("annuler", portlet_portlet_path(@portlet), :class => "button cancel", :remote => true)); %>
$("#portlet_<%= @portlet.id %>").find('.buttons ol').prepend('<%= cancel_button %>');
+$("#collapse3 .portlet_handle").data("portlet-id", <%= @portlet.id %>);
+
+
diff --git a/app/views/portlet/shared/update.js.erb b/app/views/portlet/shared/update.js.erb
index d47c241..848bb04 100644
--- a/app/views/portlet/shared/update.js.erb
+++ b/app/views/portlet/shared/update.js.erb
@@ -1,7 +1,7 @@
$("#portlet_<%= @portlet.id %>").replaceWith("<%= escape_javascript(render(@portlet)) %>");
-
-
-$(".block_portlets").sortable("enable");
+$("#portlet_<%= @portlet.id %>").addClass("active")
+//$("#element_form").html("")
+//$(".block_portlets").sortable("enable");
<%= flash_js %>
\ No newline at end of file
diff --git a/app/views/portlet/text_contents/_form.html.haml b/app/views/portlet/text_contents/_form.html.haml
index 0a3cd7d..59bc289 100644
--- a/app/views/portlet/text_contents/_form.html.haml
+++ b/app/views/portlet/text_contents/_form.html.haml
@@ -1,35 +1,70 @@
-=semantic_form_for( [:portlet, @text_content], :remote => true) do |f|
-
- %p{:style => "text-align:center;"}= f.submit "Sauvegarder", :class => "btn btn-primary"
-
- =f.text_area :content, :style => "width:98%;height:600px;", :class => "redactor_content"
+-if @text_content.id
+ =semantic_form_for( [:portlet, @text_content], :remote => true, :html => {:"data-portlet-id" => @text_content.portlet.id}) do |f|
+
+ %p{:style => "text-align:center;"}= f.submit "Sauvegarder", :class => "btn btn-primary"
+
+ =f.text_area :content, :style => "width:98%;height:600px;", :class => "redactor_content", :style => "display:none;"
- #toolbar-text
-
-
- -if TextContent::STYLES.size > 0
- Style :
- = f.select :style, TextContent::STYLES
+
+
+
+ -if TextContent::STYLES.size > 0
+ Style :
+ = f.select :style, TextContent::STYLES
-
-
-
- :javascript
-
- $('.redactor_content').redactor({
- toolbarExternal: '#toolbar-text',
-
- lang: 'fr',
- buttons : ['html', '|', 'formatting', '|', 'bold', 'italic', 'deleted','underline','|', 'alignleft', 'aligncenter', 'alignright', 'justify', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'table', 'link', '|','fontcolor', 'backcolor','|', 'horizontalrule']
-
-
- });
-
-
+
+ :javascript
+ $("#element_form form").submit(function (e){
+
+ $("textarea").val($('#portlet_'+$("#element_form form").data("portlet-id")+' .content').html());
+ $("#toolbar-text").html("");
+
+ });
+
+ $('#portlet_'+$("#element_form form").data("portlet-id")+' .content').redactor({
+ toolbarExternal: '#toolbar-text',
+ buttons : ['undo','redo','|', 'formatting', '|', 'bold', 'italic', 'deleted','underline','|', 'alignleft', 'aligncenter', 'alignright', 'justify', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'table', 'link', '|','fontcolor', 'backcolor','|', 'horizontalrule', '|','html']
+
+
+
+ });
+
+
-
-
-
+
+
+
+-else
+ =semantic_form_for( [:portlet, @text_content], :remote => true) do |f|
+
+ %p{:style => "text-align:center;"}= f.submit "Sauvegarder", :class => "btn btn-primary"
+
+ =f.text_area :content, :style => "width:98%;height:600px;", :class => "redactor_content"
+
+
+
+
+ -if TextContent::STYLES.size > 0
+ Style :
+ = f.select :style, TextContent::STYLES
+
+
+
+
+
+ :javascript
+
+ $('.redactor_content').redactor({
+ toolbarExternal: '#toolbar-text',
+
+
+
+ });
+
+
+
+
+
diff --git a/app/views/portlet/text_contents/_text_content.html.haml b/app/views/portlet/text_contents/_text_content.html.haml
index afdbae0..f36ab60 100644
--- a/app/views/portlet/text_contents/_text_content.html.haml
+++ b/app/views/portlet/text_contents/_text_content.html.haml
@@ -1 +1,2 @@
-%p=raw text_content.content
\ No newline at end of file
+
+.content=raw text_content.content
\ No newline at end of file
diff --git a/app/views/portlet/title_contents/_form.html.haml b/app/views/portlet/title_contents/_form.html.haml
index c0c9db3..b084cfd 100644
--- a/app/views/portlet/title_contents/_form.html.haml
+++ b/app/views/portlet/title_contents/_form.html.haml
@@ -1,6 +1,6 @@
=semantic_form_for( [:portlet, @title_content], :remote => true) do |f|
- =f.text_field :content, :style => "width:98%;", :class => "inputText"
+ =f.text_field :content, :style => "width:98%;", :class => "inputText" if !@title_content.id
Importance :
= f.select :level, TitleContent::LEVELS
diff --git a/app/views/portlets.old/render_public/_blockcontent.html.haml b/app/views/portlets.old/render_public/_blockcontent.html.haml
new file mode 100644
index 0000000..220b93d
--- /dev/null
+++ b/app/views/portlets.old/render_public/_blockcontent.html.haml
@@ -0,0 +1,30 @@
+
+-if input.nbr_columns == 1 and admin == "dd"
+ -input.blocks.each do |block|
+ .block
+ =render :partial => "admin/blocks/block", :locals => {:block => block, :sortable => false}
+ .clear
+
+-else
+ =raw '' if !admin
+
+ - css_class = ""
+ - css_class = "fond-gris" if input.style == 2
+ - css_class = "fond-bleu" if input.style == 3
+
+ =raw "" if !admin
+
+ %div{:class => css_class}
+ .row-fluid
+ -for i in 1..input.nbr_columns.to_i
+ %div{:class => "span"+eval("input.row#{i}").to_s}
+ -if admin
+ =render :partial => "admin/blocks/block", :locals => {:admin => false,:block => input.blocks[i-1], :sortable => false}
+ -else
+ =render :partial => "public/blocks/block", :locals => {:admin => false, :block => input.blocks[i-1], :sortable => false}
+
+
+ =raw "
" if !admin
+ =raw '' if !admin
+
+
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_breakcontent.html.haml b/app/views/portlets.old/render_public/_breakcontent.html.haml
new file mode 100644
index 0000000..a287381
--- /dev/null
+++ b/app/views/portlets.old/render_public/_breakcontent.html.haml
@@ -0,0 +1 @@
+%hr
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_downloadcontent.html.haml b/app/views/portlets.old/render_public/_downloadcontent.html.haml
new file mode 100644
index 0000000..8165052
--- /dev/null
+++ b/app/views/portlets.old/render_public/_downloadcontent.html.haml
@@ -0,0 +1,11 @@
+-if input.data_file
+
+
+
+ .portlet.download_content
+ =link_to input.title.to_s, input.data_file.file.url
+
+-else
+
+ .portlet.download_content
+ =link_to input.title.to_s, ""
diff --git a/app/views/portlets.old/render_public/_dynamiccontent.html.haml b/app/views/portlets.old/render_public/_dynamiccontent.html.haml
new file mode 100644
index 0000000..7b58256
--- /dev/null
+++ b/app/views/portlets.old/render_public/_dynamiccontent.html.haml
@@ -0,0 +1,3 @@
+
+
+=render :partial => "portlets/dynamic_contents/"+input.name.to_s.downcase if input.name
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_eventcontent.html.haml b/app/views/portlets.old/render_public/_eventcontent.html.haml
new file mode 100644
index 0000000..c312515
--- /dev/null
+++ b/app/views/portlets.old/render_public/_eventcontent.html.haml
@@ -0,0 +1,106 @@
+.event{:class => input.event_type.to_i}
+ %a{:id => "event_#{input.id}"}
+ -if input.image_file
+
+ %p.img{:style =>"float:left;"}
+ =image_tag(input.image_file.file.large.medium.small.thumb)
+
+
+
+
+
+
+
+
+
+
+
+
+ %h2=input.title
+ %h3= input.artist
+ %h4
+ ="Rencontre avec l'artiste" if input.event_type.to_i == 1
+ = l input.start_at, :format => :human
+ %p{:style => "clear:both;margin-top:20px;"}
+
+ #map.map{:id => input.id, :style => "width:400px; height:200px;"}
+
+
+
+
+
+
+
+
+ %p
+ %strong=input.place
+ %br
+ =simple_format input.address
+
+
+
+ =simple_format input.description
+ %p=link_to "voir la carte en grand", "http://maps.google.com/maps?q="+u(input.address), :target => "blank"
+
+ -if input.with_cible?
+
+
+ - if input.cible
+ =link_to "site de l'artiste", input.cible.cible_url, :target => ("_blank" if input.popup).to_s
+
+ %p{:style => "clear:both;margin-top:10px;"}
+
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_gallerycontent.html.haml b/app/views/portlets.old/render_public/_gallerycontent.html.haml
new file mode 100644
index 0000000..a9a2a60
--- /dev/null
+++ b/app/views/portlets.old/render_public/_gallerycontent.html.haml
@@ -0,0 +1,136 @@
+
+-if admin
+
+ %h2=input.name
+ .description
+ =raw input.description
+
+ %p{:style => "text-align:center;"}=link_to "Ajouter des images", "#", :onclick => "select_gallery_images_from_manager('"+input.id.to_s+"');return false;", :class => "btn"
+
+ .gallery_images
+ =render :collection => input.gallery_images, :partial => "portlet/gallery_images/gallery_image"
+ %p{:style => "clear:both;"}
+
+ :coffeescript
+
+ adjustment = ""
+
+ $('.gallery_images').sortable({
+ itemSelector:".gallery_image",
+ containerSelector :".gallery_images",
+ nested:true,
+ placeholder:"
",
+ onDragStart: ($item, container, _super) ->
+ $("body").addClass("dragging")
+
+ offset = $item.offset()
+ pointer = container.rootGroup.pointer
+ adjustment = {
+ left: pointer.left - offset.left,
+ top: pointer.top - offset.top
+ }
+ onDrag: ($item, position, _super) ->
+
+ $item.css({
+
+ left: position.left - adjustment.left,
+ top: position.top - adjustment.top - $(window).scrollTop()
+
+ })
+
+ onDrop: ($item, container, _super) ->
+
+ $item.removeClass("dragged").removeAttr("style")
+ $("body").removeClass("dragging")
+
+ result = []
+ container.el.find(".gallery_image").each ->
+ result.push $(this).data("id")
+
+
+
+
+ $.ajax({
+ url:"/portlet/gallery_images/reorder.js",
+ type: "GET",
+ data: {
+ order : result
+ }
+
+ })
+ });
+
+
+
+
+-else
+ -if input.style == 4
+ %ul#portfolio-filter
+
+ %li
+ %a.current{:href => "#all"} Tous
+
+ -input.tags.each do |tag|
+ %li
+ %a{:href => "##{tag.to_slug}"}= tag
+
+
+
+ %ul#portfolio-list
+ -input.gallery_images.each do |gallery_images|
+ %li{:class => gallery_images.tags_class}=link_to image_tag(gallery_images.image_file.file.square.url),gallery_images.image_file.file.large.url, :title => "#{gallery_images.title}", :rel => "prettyPhoto"
+
+
+ :coffeescript
+ $('#portfolio-list').filterable({
+ animationSpeed: 300,
+ show: { height: 'show',width: 'show' },
+ hide: { height: 'hide' ,width: 'hide'}
+ })
+
+
+
+ -if input.style == 3
+ .portlet.input
+ .gallery_images
+ -input.gallery_images.each do |gallery_images|
+ =link_to image_tag(gallery_images.image_file.file.square.url, :alt => "#{gallery_images.title}"), gallery_images.image_file.file.large.url, :rel => "prettyPhoto"
+ %p{:style => "clear:both;"}
+
+
+ -elsif input.style==2
+
+
+ #slider
+
+
+
+
+ -input.gallery_images.each do |gallery_images|
+ =image_tag gallery_images.image_file.file.large.medium.url
+
+
+
+
+
+
+
+
+
+ -elsif input.style==1
+ .portlet.input
+ %table.gallery_images
+ =raw "
"
+
+ - i = 0
+ -input.gallery_images.each do |gallery_images|
+ - i = i+1
+
+ %td=link_to image_tag(gallery_images.image_file.file.large.medium.small.thumb.url, :alt => "#{gallery_images.title}"), gallery_images.image_file.file.large.url, :rel => "prettyPhoto"
+
+ -if i % 4 == 0
+ =raw " "
+
+
+ =raw " "
+
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_htmlcontent.html.haml b/app/views/portlets.old/render_public/_htmlcontent.html.haml
new file mode 100644
index 0000000..edf5dc6
--- /dev/null
+++ b/app/views/portlets.old/render_public/_htmlcontent.html.haml
@@ -0,0 +1,5 @@
+
+-begin
+ =render :inline => input.content, :type => input.content_type
+-rescue Exception=>e
+ =raw "
"
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_imagecontent.html.haml b/app/views/portlets.old/render_public/_imagecontent.html.haml
new file mode 100644
index 0000000..57f456a
--- /dev/null
+++ b/app/views/portlets.old/render_public/_imagecontent.html.haml
@@ -0,0 +1,51 @@
+
+-if input.image_file
+
+ -if input.style== "1"
+ -url =input.image_file.file.large.medium.url
+
+ -elsif input.style== "2"
+ -url =input.image_file.file.large.medium.small.url
+
+ -elsif input.style== "3"
+ -url =input.image_file.file.square.url
+
+ -elsif input.style== "4"
+ -url =input.image_file.file.large.medium.small.thumb.url
+
+ -elsif input.style== "5"
+ -url =input.image_file.file.large.url
+
+
+
+-else
+ -url =""
+
+-url = "http://"+request.host_with_port+url
+-style = ""
+-style = "text-align:center;" if input.alignement == "center"
+
+
+-style = "float:right;" if input.alignement == "right"
+
+
+-style = "float:left;" if input.alignement == "left"
+
+- if input.cible
+ -link = input.cible.cible_url
+
+-styleimg=""
+-styleimg += "width:"+input.width.to_s+"px;" if input.width?
+-styleimg += "height:"+input.height.to_s+"px;" if input.height?
+
+%p.img{:style =>style}
+ -if link
+
+ =link_to image_tag(url, :alt => input.alt.to_s, :style => styleimg ), link, :title => input.alt.to_s, :target => (input.popup ? "_blank" : "")
+
+
+ -elsif input.expandable
+ =link_to image_tag(url, :alt => input.alt.to_s, :style => styleimg ), (input.image_file ? input.image_file.file.large.url : ""), :rel => "prettyPhoto", :title => input.alt.to_s
+
+ -else
+ =image_tag(url, :alt => input.alt.to_s, :style => styleimg )
diff --git a/app/views/portlets.old/render_public/_imglinkcontent.html.haml b/app/views/portlets.old/render_public/_imglinkcontent.html.haml
new file mode 100644
index 0000000..673a185
--- /dev/null
+++ b/app/views/portlets.old/render_public/_imglinkcontent.html.haml
@@ -0,0 +1,27 @@
+.img_link_portlet
+
+ - if input.cible
+ -url = input.cible.cible_url
+
+ .image_file
+ =link_to image_tag(input.image_file.file.square.url), url if input.image_file
+
+ .title
+ %h3=link_to input.title, url
+ .description
+ = link_to simple_format(input.description), url
+ .clear
+
+
+ -else
+
+
+ .image_file
+ =image_tag(input.image_file.file.square.url) if input.image_file
+
+ .title
+ %h3=input.title
+ .description
+ = simple_format(input.description)
+ .clear
+
diff --git a/app/views/portlets.old/render_public/_linkcontent.html.haml b/app/views/portlets.old/render_public/_linkcontent.html.haml
new file mode 100644
index 0000000..6cf9229
--- /dev/null
+++ b/app/views/portlets.old/render_public/_linkcontent.html.haml
@@ -0,0 +1,6 @@
+.portlet.link_content
+ - if input.cible
+ -url = input.cible.cible_url
+ -else
+ -url = ""
+ =link_to input.name.to_s, url.to_s, :class => "external_link", :target => ("_blank" if input.popup).to_s
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_mapcontent.html.haml b/app/views/portlets.old/render_public/_mapcontent.html.haml
new file mode 100644
index 0000000..7fd76a6
--- /dev/null
+++ b/app/views/portlets.old/render_public/_mapcontent.html.haml
@@ -0,0 +1,64 @@
+#map_content_map.map_content_map{:id => input.id, :style => "width:100%; height:400px;margin:auto;"}
+
+
+
+
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_tablecontent.html.haml b/app/views/portlets.old/render_public/_tablecontent.html.haml
new file mode 100644
index 0000000..bed8375
--- /dev/null
+++ b/app/views/portlets.old/render_public/_tablecontent.html.haml
@@ -0,0 +1,74 @@
+-if admin
+
+
+
+
+
+ %table
+ -table_rows = input.table_rows
+ %tr
+ -i = 0
+ -input.nbr_cols.times do
+ -i += 1
+ %td.add_col{:style => "text-align:center;"}
+
+ .btn-group
+ %a.btn.dropdown-toggle{:href => "#", :data => {:toggle => "dropdown"}}
+ = i(:cog)
+
+ %ul.dropdown-menu
+ %li=link_to "Ajouter une colonne avant", portlet_table_cols_path(:position => i, :table_content_id =>input.id ), :method => :post, :remote => true
+
+ %li=link_to "Ajouter une colonne après", portlet_table_cols_path(:position => i+1, :table_content_id =>input.id ), :method => :post, :remote => true
+
+ -if input.nbr_cols > 1
+ %li=link_to "Supprimer cette colonne", portlet_table_col_path(:id => i, :table_content_id =>input.id ), :method => :delete, :remote => true, :confirm => "Voulez-vous vraiment supprimer cette colonne ?"
+
+
+ %td
+
+ -table_rows.each do |table_row|
+ %tr{:id => table_row.id}
+
+
+ -CelTable.where(:table_row_id => table_row.id).order("position ASC").each do |cel_table|
+
+ %td.input_cel{:id => cel_table.id, :style => "border:1px solid black;"}
+
+ =render :partial => "admin/blocks/block", :locals => {:block => cel_table.block, :sortable => false}
+
+ %td.add_cel
+
+ .btn-group{:style => "position:relative;"}
+ %a.btn.dropdown-toggle{:href => "#", :data => {:toggle => "dropdown"}}
+ = i(:cog)
+
+ %ul.dropdown-menu{:style => "position:absolute;right:40px !important;left:auto !important;top:-2px !important;"}
+ %li=link_to "Ajouter un rang avant", portlet_table_rows_path(:table_row => {:table_content_id => input.id, :position => (table_row.position)}), :method => :post, :remote => true
+
+ %li=link_to "Ajouter un rang après", portlet_table_rows_path(:table_row => {:table_content_id => input.id, :position => (table_row.position+1)}), :method => :post, :remote => true
+ -if input.nbr_rows > 1
+ %li=link_to "Supprimer ce rang", portlet_table_row_path(table_row), :method => :delete, :remote => true, :confirm => "Voulez-vous vraiment supprimer ce rang ?"
+
+
+
+
+
+-else
+
+ %table
+ -table_rows = input.table_rows
+
+
+ -table_rows.each do |table_row|
+ %tr
+
+ -table_row.cel_tables.each do |cel_table|
+
+ %td
+
+ =render cel_table.block
+
+
+
+
diff --git a/app/views/portlets.old/render_public/_textcontent.html.haml b/app/views/portlets.old/render_public/_textcontent.html.haml
new file mode 100644
index 0000000..81883ed
--- /dev/null
+++ b/app/views/portlets.old/render_public/_textcontent.html.haml
@@ -0,0 +1 @@
+=raw(input.content)
\ No newline at end of file
diff --git a/app/views/portlets.old/render_public/_titlecontent.html.haml b/app/views/portlets.old/render_public/_titlecontent.html.haml
new file mode 100644
index 0000000..72e2a08
--- /dev/null
+++ b/app/views/portlets.old/render_public/_titlecontent.html.haml
@@ -0,0 +1,5 @@
+-level = (input.level || "1").to_s
+
+=raw '
"
+=input.content
+=raw ' "
diff --git a/app/views/portlets/render_public/_blockcontent.html.haml b/app/views/portlets/render_public/_blockcontent.html.haml
index 220b93d..af95aac 100644
--- a/app/views/portlets/render_public/_blockcontent.html.haml
+++ b/app/views/portlets/render_public/_blockcontent.html.haml
@@ -14,17 +14,17 @@
=raw "
" if !admin
- %div{:class => css_class}
- .row-fluid
- -for i in 1..input.nbr_columns.to_i
- %div{:class => "span"+eval("input.row#{i}").to_s}
- -if admin
- =render :partial => "admin/blocks/block", :locals => {:admin => false,:block => input.blocks[i-1], :sortable => false}
- -else
- =render :partial => "public/blocks/block", :locals => {:admin => false, :block => input.blocks[i-1], :sortable => false}
+
+ .row
+ -for i in 1..input.nbr_columns.to_i
+ %div{:class => "col-xs-"+eval("input.row#{i}").to_s}
+ -if admin
+ =render :partial => "admin/blocks/block", :locals => {:admin => false,:block => input.blocks[i-1], :sortable => false}
+ -else
+ =render :partial => "public/blocks/block", :locals => {:admin => false, :block => input.blocks[i-1], :sortable => false}
=raw "
" if !admin
- =raw '
' if !admin
+ =raw '
' if !admin
\ No newline at end of file
diff --git a/app/views/portlets/render_public/_gallerycontent.html.haml b/app/views/portlets/render_public/_gallerycontent.html.haml
index a9a2a60..8792e17 100644
--- a/app/views/portlets/render_public/_gallerycontent.html.haml
+++ b/app/views/portlets/render_public/_gallerycontent.html.haml
@@ -124,13 +124,15 @@
- i = 0
-input.gallery_images.each do |gallery_images|
- - i = i+1
+ -if gallery_images.image_file
+ - i = i+1
- %td=link_to image_tag(gallery_images.image_file.file.large.medium.small.thumb.url, :alt => "#{gallery_images.title}"), gallery_images.image_file.file.large.url, :rel => "prettyPhoto"
+ %td=link_to image_tag(gallery_images.image_file.file.large.medium.small.thumb.url, :alt => "#{gallery_images.title}"), gallery_images.image_file.file.large.url, :rel => "prettyPhoto"
- -if i % 4 == 0
- =raw "
"
+ -if i % 4 == 0
+ =raw " "
=raw " "
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/app/views/portlets/render_public/_imagecontent.html.haml b/app/views/portlets/render_public/_imagecontent.html.haml
index 57f456a..942e194 100644
--- a/app/views/portlets/render_public/_imagecontent.html.haml
+++ b/app/views/portlets/render_public/_imagecontent.html.haml
@@ -1,25 +1,25 @@
-
+
-if input.image_file
- -if input.style== "1"
- -url =input.image_file.file.large.medium.url
+ -if input.style== "1"
+ -url =input.image_file.file.large.medium.url
- -elsif input.style== "2"
- -url =input.image_file.file.large.medium.small.url
+ -elsif input.style== "2"
+ -url =input.image_file.file.large.medium.small.url
- -elsif input.style== "3"
- -url =input.image_file.file.square.url
+ -elsif input.style== "3"
+ -url =input.image_file.file.square.url
- -elsif input.style== "4"
- -url =input.image_file.file.large.medium.small.thumb.url
-
- -elsif input.style== "5"
- -url =input.image_file.file.large.url
-
-
+ -elsif input.style== "4"
+ -url =input.image_file.file.large.medium.small.thumb.url
+
+ -elsif input.style== "5"
+ -url =input.image_file.file.large.url
+
+
-else
- -url =""
+ -url =""
-url = "http://"+request.host_with_port+url
-style = ""
@@ -27,25 +27,29 @@
-style = "float:right;" if input.alignement == "right"
-
+
-style = "float:left;" if input.alignement == "left"
- if input.cible
- -link = input.cible.cible_url
+ -link = input.cible.cible_url
-styleimg=""
-styleimg += "width:"+input.width.to_s+"px;" if input.width?
-styleimg += "height:"+input.height.to_s+"px;" if input.height?
-%p.img{:style =>style}
- -if link
-
- =link_to image_tag(url, :alt => input.alt.to_s, :style => styleimg ), link, :title => input.alt.to_s, :target => (input.popup ? "_blank" : "")
+.img{:style =>style}
+ -if admin
+ = image_tag(url, :alt => input.alt.to_s, :style => styleimg )
+ -else
+
+ -if link
+
+ =link_to image_tag(url, :alt => input.alt.to_s, :style => styleimg ), link, :title => input.alt.to_s, :target => (input.popup ? "_blank" : "")
-
- -elsif input.expandable
- =link_to image_tag(url, :alt => input.alt.to_s, :style => styleimg ), (input.image_file ? input.image_file.file.large.url : ""), :rel => "prettyPhoto", :title => input.alt.to_s
+
+ -elsif input.expandable
+ =link_to image_tag(url, :alt => input.alt.to_s, :style => styleimg ), (input.image_file ? input.image_file.file.large.url : ""), :rel => "prettyPhoto", :title => input.alt.to_s
- -else
- =image_tag(url, :alt => input.alt.to_s, :style => styleimg )
+ -else
+ =image_tag(url, :alt => input.alt.to_s, :style => styleimg )
diff --git a/app/views/portlets/render_public/_textcontent.html.haml b/app/views/portlets/render_public/_textcontent.html.haml
index 81883ed..3208fe0 100644
--- a/app/views/portlets/render_public/_textcontent.html.haml
+++ b/app/views/portlets/render_public/_textcontent.html.haml
@@ -1 +1,4 @@
-=raw(input.content)
\ No newline at end of file
+-if admin
+ .content=raw(input.content)
+-else
+ =raw(input.content)
\ No newline at end of file
diff --git a/app/views/portlets/render_public/_titlecontent.html.haml b/app/views/portlets/render_public/_titlecontent.html.haml
index 72e2a08..364280d 100644
--- a/app/views/portlets/render_public/_titlecontent.html.haml
+++ b/app/views/portlets/render_public/_titlecontent.html.haml
@@ -1,5 +1,8 @@
-level = (input.level || "1").to_s
-=raw '"
+-if admin
+ =raw '"
+-else
+ =raw '"
=input.content
=raw ' "
diff --git a/app/views/public/menu_items/show.html.haml b/app/views/public/menu_items/show.html.haml
index 0039dab..e6b3014 100644
--- a/app/views/public/menu_items/show.html.haml
+++ b/app/views/public/menu_items/show.html.haml
@@ -8,7 +8,8 @@
-first_level_menu = @menu_item
- -if first_level_menu.children.size > 0
+ -#if first_level_menu.children.size > 0
+ -if first_level_menu.children.count > 0
.square.green
%h3=menu_item_link(first_level_menu)
%ul
diff --git a/config/database.yml b/config/database.yml
index 8b007ef..783bd3c 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -5,8 +5,8 @@
# gem 'sqlite3'
development:
adapter: mysql2
- encoding: utf8
- database: ecoleeft_app
+ encoding: utf8mb4
+ database: ecole_eft_app
pool: 5
username: root
socket: /tmp/mysql.sock
diff --git a/config/initializers/formtastic.rb b/config/initializers/formtastic.rb
index 262f893..94a11ab 100644
--- a/config/initializers/formtastic.rb
+++ b/config/initializers/formtastic.rb
@@ -1,94 +1,5 @@
# -*- encoding : utf-8 -*-
+Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
+
Date::DATE_FORMATS[:default] = '%d/%m/%Y'
Time::DATE_FORMATS[:default]= '%d/%m/%Y %H:%M:%S'
-module Formtastic
-
-
- module Inputs
-
- class QiCibleSelectInput
- include Base
-
- def to_html
- r = rand(1000000000000000000000000000)
-
-
- input_wrapping do
- label_html +
- template.content_tag(:fieldset, template.text_field_tag("cible_name", (object.cible ? object.cible.cible_name : "aucuns élément séléctionné"), :id =>"name_#{r}" ) +
- self.manager_select_cible_link(method, options, r) + builder.hidden_field(method.to_s+"_id", input_html_options.merge!(:id => "input_id_"+r.to_s)) +
- builder.hidden_field(method.to_s+"_type", input_html_options.merge!(:id => "input_type_"+r.to_s)) )
- end
-
- end
-
-
- def manager_select_cible_link(method, options, r)
-
- template.content_tag(:a, "Modifier ce lien", :href => "#", :onclick => "select_cible_from_manager('"+r.to_s+"');return false;")
-
- end
- end
-
- class QiImageSelectInput
- include Base
-
- def to_html
- r = rand(1000000000000000000000000000)
-
-
- input_wrapping do
- label_html +
- template.content_tag(:fieldset, manager_select_link(method, options, r) + template.tag(:br) + image_preview(method, options, r) + builder.hidden_field(method.to_s, input_html_options.merge!(:id => "input_"+r.to_s)) )
- end
-
- end
-
-
- def manager_select_link(method, options, r)
- template.content_tag(:a, "Modifier cette image", :href => "#", :onclick => "select_image_from_manager('"+r.to_s+"');return false;")
- end
-
- def image_preview(method, options,r)
- if object.send("#{method}?") and ImageFile.exists?(object.send("#{method}"))
- template.content_tag(:span, template.image_tag(object.image_file.file.large.medium.small.thumb.url, :id => "img_"+r.to_s, :onclick => "select_image_from_manager('"+r.to_s+"');return false;"), :class => "preview ")
- else
- template.content_tag(:span, template.image_tag("admin/default_image.png", :id => "img_"+r.to_s, :onclick => "select_image_from_manager('"+r.to_s+"');return false;"), :class => "preview ")
- end
- end
-
- end
-
- class QiDatePickerInput
- include Base
-
- def to_html
- r = rand(1000000000000000000000000000)
-
-
- input_wrapping do
- label_html +
- builder.text_field(method.to_s, input_html_options.merge!(:class => "datepicker"))
- #template.content_tag(:fieldset, manager_select_link(method, options, r) + template.tag(:br) + image_preview(method, options, r) + builder.hidden_field(method.to_s, input_html_options.merge!(:id => "input_"+r.to_s)) )
- end
-
- end
-
-
-
- end
-
-
-
-
-
-
-
-
-
-
-
-
-
- end
-end