spec/dummy/tmp/cache/assets/D0E/2E0/sprockets%2F4a4bfb6542664b7912f800e18ce7e4c2 in locomotivecms-search-0.2.8 vs spec/dummy/tmp/cache/assets/D0E/2E0/sprockets%2F4a4bfb6542664b7912f800e18ce7e4c2 in locomotivecms-search-0.3.0

- old
+ new

@@ -1,8 +1,8 @@ -o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1384093249.403806: @value"Ö•{I" +o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1396022042.161833: @value"{I" class:ETI"BundledAsset;FI"logical_path;TI"locomotive.js;TI" pathname;TI"V/Users/didier/Documents/LocomotiveCMS/engine/app/assets/javascripts/locomotive.js;FI"content_type;TI"application/javascript;TI" -mtime;TI"2013-11-09T00:10:51+01:00;TI" length;Tiñ“I" digest;TI"%d158eb94073c745799928c8d2623a160;FI" source;TI"ñ“/*! +mtime;TI"2014-03-20T10:46:19+01:00;TI" length;Ti3I" digest;TI"%2f328578df55c9afe9bb5173af68e1cf;FI" source;TI"3/*! * jQuery JavaScript Library v1.8.3 * http://jquery.com/ * * Includes Sizzle.js * http://sizzlejs.com/ @@ -27303,24 +27303,30 @@ var urlError = function() { throw new Error('A "url" property or function must be specified'); }; }).call(this); -// CodeMirror version 3.16 +// CodeMirror version 3.22 // // CodeMirror is the only global var we claim window.CodeMirror = (function() { "use strict"; // BROWSER SNIFFING // Crude, but necessary to handle a number of hard-to-feature-detect // bugs and behavior differences. var gecko = /gecko\/\d/i.test(navigator.userAgent); - var ie = /MSIE \d/.test(navigator.userAgent); - var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8); - var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); + // IE11 currently doesn't count as 'ie', since it has almost none of + // the same bugs as earlier versions. Use ie_gt10 to handle + // incompatibilities in that version. + var old_ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt8 = old_ie && (document.documentMode == null || document.documentMode < 8); + var ie_lt9 = old_ie && (document.documentMode == null || document.documentMode < 9); + var ie_lt10 = old_ie && (document.documentMode == null || document.documentMode < 10); + var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent); + var ie = old_ie || ie_gt10; var webkit = /WebKit\//.test(navigator.userAgent); var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); var chrome = /Chrome\//.test(navigator.userAgent); var opera = /Opera\//.test(navigator.userAgent); var safari = /Apple Computer/.test(navigator.vendor); @@ -27364,11 +27370,12 @@ this.state = {keyMaps: [], overlays: [], modeGen: 0, overwrite: false, focused: false, - suppressEdits: false, pasteIncoming: false, + suppressEdits: false, + pasteIncoming: false, cutIncoming: false, draggingText: false, highlight: new Delayed()}; themeChanged(this); if (options.lineWrapping) @@ -27378,11 +27385,11 @@ if (typeof doc == "string") doc = new Doc(options.value, options.mode); operation(this, attachDoc)(this, doc); // Override magic textarea content restore that IE sometimes does // on our hidden textarea on reload - if (ie) setTimeout(bind(resetInput, this, true), 20); + if (old_ie) setTimeout(bind(resetInput, this, true), 20); registerEventHandlers(this); // IE throws unspecified error in certain cases, when // trying to access activeElement before onload var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { } @@ -27400,11 +27407,11 @@ // DISPLAY CONSTRUCTOR function makeDisplay(place, docStart) { var d = {}; - var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;"); + var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none"); if (webkit) input.style.width = "1000px"; else input.setAttribute("wrap", "off"); // if border: 0; -- iOS fails to open keyboard (issue #1287) if (ios) input.style.border = "1px solid black"; input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false"); @@ -27472,11 +27479,11 @@ // intensively. d.pollingFast = false; // Self-resetting timeout for the poller d.poll = new Delayed(); - d.cachedCharWidth = d.cachedTextHeight = null; + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; d.measureLineCache = []; d.measureLineCachePos = 0; // Tracks when resetInput has punted to just putting a short // string instead of the (large) selection. @@ -27498,10 +27505,14 @@ // Used to get the editor into a consistent state again when options change. function loadMode(cm) { cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { cm.doc.iter(function(line) { if (line.stateAfter) line.stateAfter = null; if (line.styles) line.styles = null; }); cm.doc.frontier = cm.doc.first; @@ -27547,11 +27558,10 @@ function keyMapChanged(cm) { var map = keyMap[cm.options.keyMap], style = map.style; cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + (style ? " cm-keymap-" + style : ""); - cm.state.disableInput = map.disableInput; } function themeChanged(cm) { cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); @@ -27611,19 +27621,17 @@ } // Make sure the gutters options contains the element // "CodeMirror-linenumbers" when the lineNumbers option is true. function setGuttersForLineNumbers(options) { - var found = false; - for (var i = 0; i < options.gutters.length; ++i) { - if (options.gutters[i] == "CodeMirror-linenumbers") { - if (options.lineNumbers) found = true; - else options.gutters.splice(i--, 1); - } + var found = indexOf(options.gutters, "CodeMirror-linenumbers"); + if (found == -1 && options.lineNumbers) { + options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); + } else if (found > -1 && !options.lineNumbers) { + options.gutters = options.gutters.slice(0); + options.gutters.splice(found, 1); } - if (!found && options.lineNumbers) - options.gutters.push("CodeMirror-linenumbers"); } // SCROLLBARS // Re-synchronize the fake scrollbars with the actual size of the @@ -27637,12 +27645,13 @@ var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1); var needsV = scrollHeight > (d.scroller.clientHeight + 1); if (needsV) { d.scrollbarV.style.display = "block"; d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0"; + // A bug in IE8 can cause this value to be negative, so guard it. d.scrollbarV.firstChild.style.height = - (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px"; + Math.max(0, scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px"; } else { d.scrollbarV.style.display = ""; d.scrollbarV.firstChild.style.height = "0"; } if (needsH) { @@ -27662,12 +27671,14 @@ d.gutterFiller.style.display = "block"; d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px"; d.gutterFiller.style.width = d.gutters.offsetWidth + "px"; } else d.gutterFiller.style.display = ""; - if (mac_geLion && scrollbarWidth(d.measure) === 0) + if (mac_geLion && scrollbarWidth(d.measure) === 0) { d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; + d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = "none"; + } } function visibleLines(display, doc, viewPort) { var top = display.scroller.scrollTop, height = display.wrapper.clientHeight; if (typeof viewPort == "number") top = viewPort; @@ -27718,25 +27729,30 @@ // DISPLAY DRAWING function updateDisplay(cm, changes, viewPort, forced) { var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated; var visible = visibleLines(cm.display, cm.doc, viewPort); - for (;;) { + for (var first = true;; first = false) { + var oldWidth = cm.display.scroller.clientWidth; if (!updateDisplayInner(cm, changes, visible, forced)) break; - forced = false; updated = true; + changes = []; updateSelection(cm); updateScrollbars(cm); + if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) { + forced = true; + continue; + } + forced = false; // Clip forced viewport to actual scrollable area if (viewPort) viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, typeof viewPort == "number" ? viewPort : viewPort.top); visible = visibleLines(cm.display, cm.doc, viewPort); if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo) break; - changes = []; } if (updated) { signalLater(cm, "update", cm); if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo) @@ -27748,11 +27764,11 @@ // Uses a set of changes plus the current scroll position to // determine which DOM updates have to be made, and makes the // updates. function updateDisplayInner(cm, changes, visible, forced) { var display = cm.display, doc = cm.doc; - if (!display.wrapper.clientWidth) { + if (!display.wrapper.offsetWidth) { display.showingFrom = display.showingTo = doc.first; display.viewOffset = 0; return; } @@ -27833,10 +27849,11 @@ display.lastSizeC = display.wrapper.clientHeight; startWorker(cm, 400); } display.showingFrom = from; display.showingTo = to; + display.gutters.style.height = ""; updateHeightsInViewport(cm); updateViewOffset(cm); return true; } @@ -27970,14 +27987,15 @@ }); while (cur) cur = rm(cur); } function buildLineElement(cm, line, lineNo, dims, reuse) { - var lineElement = lineContent(cm, line); + var built = buildLineContent(cm, line), lineElement = built.pre; var markers = line.gutterMarkers, display = cm.display, wrap; - if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets) + var bgClass = built.bgClass ? built.bgClass + " " + (line.bgClass || "") : line.bgClass; + if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets) return lineElement; // Lines with gutter elements, widgets or a background class need // to be wrapped again, and have the extra elements added to the // wrapper div @@ -28011,16 +28029,16 @@ if (!wrap) { wrap = elt("div", null, line.wrapClass, "position: relative"); wrap.appendChild(lineElement); } // Kludge to make sure the styled element lies behind the selection (by z-index) - if (line.bgClass) - wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild); + if (bgClass) + wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild); if (cm.options.lineNumbers || markers) { - var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " + + var gutterWrap = wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"), - wrap.firstChild); + lineElement); if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap); if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) wrap.lineNumber = gutterWrap.appendChild( elt("div", lineNumberFor(cm.options, lineNo), "CodeMirror-linenumber CodeMirror-gutter-elt", @@ -28109,16 +28127,16 @@ // Highlight selection function updateSelectionRange(cm) { var display = cm.display, doc = cm.doc, sel = cm.doc.sel; var fragment = document.createDocumentFragment(); - var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display); + var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right; function add(left, top, width, bottom) { if (top < 0) top = 0; fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + - "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) + + "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px; height: " + (bottom - top) + "px")); } function drawForLine(line, fromArg, toArg) { var lineObj = getLine(doc, line); @@ -28137,22 +28155,22 @@ rightPos = coords(to - 1, "right"); if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } left = leftPos.left; right = rightPos.right; } - if (fromArg == null && from == 0) left = pl; + if (fromArg == null && from == 0) left = leftSide; if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part add(left, leftPos.top, null, leftPos.bottom); - left = pl; + left = leftSide; if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); } - if (toArg == null && to == lineLen) right = clientWidth; + if (toArg == null && to == lineLen) right = rightSide; if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) start = leftPos; if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) end = rightPos; - if (left < pl + 1) left = pl; + if (left < leftSide + 1) left = leftSide; add(left, rightPos.top, right - left, rightPos.bottom); }); return {start: start, end: end}; } @@ -28164,17 +28182,17 @@ var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end; var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start; if (singleVLine) { if (leftEnd.top < rightStart.top - 2) { add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); - add(pl, rightStart.top, rightStart.left, rightStart.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); } else { add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); } } if (leftEnd.bottom < rightStart.top) - add(pl, leftEnd.bottom, null, rightStart.top); + add(leftSide, leftEnd.bottom, null, rightStart.top); } removeChildrenAndAdd(display.selectionDiv, fragment); display.selectionDiv.style.display = ""; } @@ -28207,20 +28225,20 @@ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); var changed = [], prevChange; doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) { if (doc.frontier >= cm.display.showingFrom) { // Visible var oldStyles = line.styles; - line.styles = highlightLine(cm, line, state); + line.styles = highlightLine(cm, line, state, true); var ischange = !oldStyles || oldStyles.length != line.styles.length; for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; if (ischange) { if (prevChange && prevChange.end == doc.frontier) prevChange.end++; else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1}); } line.stateAfter = copyState(doc.mode, state); } else { - processLine(cm, line, state); + processLine(cm, line.text, state); line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; } ++doc.frontier; if (+new Date > end) { startWorker(cm, cm.options.workDelay); @@ -28238,12 +28256,13 @@ // find a line with a stateAfter, so that it can start with a // valid state. If that fails, it returns the line with the // smallest indentation, which tends to need the least context to // parse correctly. function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc, maxScan = cm.doc.mode.innerMode ? 1000 : 100; - for (var search = n, lim = n - maxScan; search > lim; --search) { + var minindent, minline, doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + for (var search = n; search > lim; --search) { if (search <= doc.first) return doc.first; var line = getLine(doc, search - 1); if (line.stateAfter && (!precise || search <= doc.frontier)) return search; var indented = countColumn(line.text, null, cm.options.tabSize); if (minline == null || minindent > indented) { @@ -28259,30 +28278,38 @@ if (!doc.mode.startState) return true; var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; if (!state) state = startState(doc.mode); else state = copyState(doc.mode, state); doc.iter(pos, n, function(line) { - processLine(cm, line, state); + processLine(cm, line.text, state); var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo; line.stateAfter = save ? copyState(doc.mode, state) : null; ++pos; }); + if (precise) doc.frontier = pos; return state; } // POSITION MEASUREMENT function paddingTop(display) {return display.lineSpace.offsetTop;} function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} - function paddingLeft(display) { - var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x")); - return e.offsetLeft; + function paddingH(display) { + if (display.cachedPaddingH) return display.cachedPaddingH; + var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + return display.cachedPaddingH = {left: parseInt(style.paddingLeft), + right: parseInt(style.paddingRight)}; } function measureChar(cm, line, ch, data, bias) { var dir = -1; data = data || measureLine(cm, line); + if (data.crude) { + var left = data.left + ch * data.width; + return {left: left, right: left + data.width, top: data.top, bottom: data.bottom}; + } for (var pos = ch;; pos += dir) { var r = data[pos]; if (r) break; if (dir < 0 && pos == 0) dir = 1; @@ -28300,11 +28327,11 @@ var cache = cm.display.measureLineCache; for (var i = 0; i < cache.length; ++i) { var memo = cache[i]; if (memo.text == line.text && memo.markedSpans == line.markedSpans && cm.display.scroller.clientWidth == memo.width && - memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass) + memo.classes == line.textClass + "|" + line.wrapClass) return memo; } } function clearCachedMeasurement(cm, line) { @@ -28320,19 +28347,22 @@ // Failing that, recompute and store result in cache var measure = measureLineInner(cm, line); var cache = cm.display.measureLineCache; var memo = {text: line.text, width: cm.display.scroller.clientWidth, markedSpans: line.markedSpans, measure: measure, - classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; + classes: line.textClass + "|" + line.wrapClass}; if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; else cache.push(memo); return measure; } function measureLineInner(cm, line) { + if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom) + return crudelyMeasureLine(cm, line); + var display = cm.display, measure = emptyArray(line.text.length); - var pre = lineContent(cm, line, measure, true); + var pre = buildLineContent(cm, line, measure, true).pre; // IE does not cache element positions of inline elements between // calls to getBoundingClientRect. This makes the loop below, // which gathers the positions of all the characters on the line, // do an amount of layout work quadratic to the number of @@ -28341,11 +28371,11 @@ // that IE can reuse most of the layout information from caches // for those blocks. This does interfere with line wrapping, so it // doesn't work when wrapping is on, but in that case the // situation is slightly better, since IE does cache line-wrapping // information and only recomputes per-line. - if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { + if (old_ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { var fragment = document.createDocumentFragment(); var chunk = 10, n = pre.childNodes.length; for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) { var wrap = elt("div", null, null, "display: inline-block"); for (var j = 0; j < chunk && n; ++j) { @@ -28401,11 +28431,11 @@ rect = data[i] = measureRect(rects[0]); rect.rightSide = measureRect(rects[rects.length - 1]); } } if (!rect) rect = data[i] = measureRect(getRect(node)); - if (cur.measureRight) rect.right = getRect(cur.measureRight).left; + if (cur.measureRight) rect.right = getRect(cur.measureRight).left - outer.left; if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide)); } removeChildren(cm.display.measure); for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) { finishRect(cur); @@ -28413,28 +28443,38 @@ if (cur.rightSide) finishRect(cur.rightSide); } return data; } + function crudelyMeasureLine(cm, line) { + var copy = new Line(line.text.slice(0, 100), null); + if (line.textClass) copy.textClass = line.textClass; + var measure = measureLineInner(cm, copy); + var left = measureChar(cm, copy, 0, measure, "left"); + var right = measureChar(cm, copy, 99, measure, "right"); + return {crude: true, top: left.top, left: left.left, bottom: left.bottom, width: (right.right - left.left) / 100}; + } + function measureLineWidth(cm, line) { var hasBadSpan = false; if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) { var sp = line.markedSpans[i]; if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true; } var cached = !hasBadSpan && findCachedMeasurement(cm, line); - if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right; + if (cached || line.text.length >= cm.options.crudeMeasuringFrom) + return measureChar(cm, line, line.text.length, cached && cached.measure, "right").right; - var pre = lineContent(cm, line, null, true); + var pre = buildLineContent(cm, line, null, true).pre; var end = pre.appendChild(zeroWidthElement(cm.display.measure)); removeChildrenAndAdd(cm.display.measure, pre); return getRect(end).right - getRect(cm.display.lineDiv).left; } function clearCaches(cm) { cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0; - cm.display.cachedCharWidth = cm.display.cachedTextHeight = null; + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; cm.display.lineNumChars = null; } function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } @@ -28567,11 +28607,11 @@ // Do a binary search between these bounds. for (;;) { if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { var ch = x < fromX || x - fromX <= toX - x ? from : to; var xDiff = x - (ch == from ? fromX : toX); - while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch; + while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside, xDiff < 0 ? -1 : xDiff ? 1 : 0); return pos; } var step = Math.ceil(dist / 2), middle = from + step; @@ -28646,11 +28686,11 @@ cm.curOp = null; if (op.updateMaxLine) computeMaxLength(cm); if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) { var width = measureLineWidth(cm, display.maxLine); - display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px"; + display.sizer.style.minWidth = Math.max(0, width + 3) + "px"; display.maxLineChanged = false; var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth); if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos) setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true); } @@ -28665,15 +28705,18 @@ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate); if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop; } if (!updated && op.selectionChanged) updateSelection(cm); if (op.updateScrollPos) { - display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop; - display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft; + var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, newScrollPos.scrollTop)); + var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, newScrollPos.scrollLeft)); + display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top; + display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left; alignHorizontally(cm); if (op.scrollToPos) - scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin); + scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from), + clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin); } else if (newScrollPos) { scrollCursorIntoView(cm); } if (op.selectionChanged) restartBlink(cm); @@ -28756,11 +28799,11 @@ // compared to the previous content instead. (Modern browsers have // events that indicate IME taking place, but these are not widely // supported or compatible enough yet to rely on.) function readInput(cm) { var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel; - if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false; + if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false; if (cm.state.pasteIncoming && cm.state.fakedLastChar) { input.value = input.value.substring(0, input.value.length - 1); cm.state.fakedLastChar = false; } var text = input.value; @@ -28774,26 +28817,36 @@ if (withOp) startOperation(cm); sel.shift = false; var same = 0, l = Math.min(prevInput.length, text.length); while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; var from = sel.from, to = sel.to; + var inserted = text.slice(same); if (same < prevInput.length) from = Pos(from.line, from.ch - (prevInput.length - same)); else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming) - to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same))); + to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + inserted.length)); var updateInput = cm.curOp.updateInput; - var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)), - origin: cm.state.pasteIncoming ? "paste" : "+input"}; + var changeEvent = {from: from, to: to, text: splitLines(inserted), + origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"}; makeChange(cm.doc, changeEvent, "end"); cm.curOp.updateInput = updateInput; signalLater(cm, "inputRead", cm, changeEvent); + if (inserted && !cm.state.pasteIncoming && cm.options.electricChars && + cm.options.smartIndent && sel.head.ch < 100) { + var electric = cm.getModeAt(sel.head).electricChars; + if (electric) for (var i = 0; i < electric.length; i++) + if (inserted.indexOf(electric.charAt(i)) > -1) { + indentLine(cm, sel.head.line, "smart"); + break; + } + } if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = ""; else cm.display.prevInput = text; if (withOp) endOperation(cm); - cm.state.pasteIncoming = false; + cm.state.pasteIncoming = cm.state.cutIncoming = false; return true; } function resetInput(cm, user) { var minimal, selected, doc = cm.doc; @@ -28815,20 +28868,24 @@ function focusInput(cm) { if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input)) cm.display.input.focus(); } + function ensureFocus(cm) { + if (!cm.state.focused) { focusInput(cm); onFocus(cm); } + } + function isReadOnly(cm) { return cm.options.readOnly || cm.doc.cantEdit; } // EVENT HANDLERS function registerEventHandlers(cm) { var d = cm.display; on(d.scroller, "mousedown", operation(cm, onMouseDown)); - if (ie) + if (old_ie) on(d.scroller, "dblclick", operation(cm, function(e) { if (signalDOMEvent(cm, e)) return; var pos = posFromMouse(cm, e); if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; e_preventDefault(e); @@ -28871,11 +28928,11 @@ var resizeTimer; function onResize() { if (resizeTimer == null) resizeTimer = setTimeout(function() { resizeTimer = null; // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null; + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null; clearCaches(cm); runInOp(cm, bind(regChange, cm)); }, 100); } on(window, "resize", onResize); @@ -28887,15 +28944,15 @@ if (p) setTimeout(unregister, 5000); else off(window, "resize", onResize); } setTimeout(unregister, 5000); - on(d.input, "keyup", operation(cm, function(e) { - if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; - if (e.keyCode == 16) cm.doc.sel.shift = false; - })); - on(d.input, "input", bind(fastPoll, cm)); + on(d.input, "keyup", operation(cm, onKeyUp)); + on(d.input, "input", function() { + if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null; + fastPoll(cm); + }); on(d.input, "keydown", operation(cm, onKeyDown)); on(d.input, "keypress", operation(cm, onKeyPress)); on(d.input, "focus", bind(onFocus, cm)); on(d.input, "blur", bind(onBlur, cm)); @@ -28927,25 +28984,26 @@ } cm.state.pasteIncoming = true; fastPoll(cm); }); - function prepareCopy() { + function prepareCopy(e) { if (d.inaccurateSelection) { d.prevInput = ""; d.inaccurateSelection = false; d.input.value = cm.getSelection(); selectInput(d.input); } + if (e.type == "cut") cm.state.cutIncoming = true; } on(d.input, "cut", prepareCopy); on(d.input, "copy", prepareCopy); // Needed to handle Tab key in KHTML if (khtml) on(d.sizer, "mouseup", function() { - if (document.activeElement == d.input) d.input.blur(); - focusInput(cm); + if (document.activeElement == d.input) d.input.blur(); + focusInput(cm); }); } function eventInWidget(display, e) { for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { @@ -28980,10 +29038,11 @@ } return; } if (clickInGutter(cm, e)) return; var start = posFromMouse(cm, e); + window.focus(); switch (e_button(e)) { case 3: if (captureMiddleClick) onContextMenu.call(cm, cm, e); return; @@ -28997,11 +29056,11 @@ // For button 1, if it was clicked inside the editor // (posFromMouse returning non-null), we have to adjust the // selection. if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;} - if (!cm.state.focused) onFocus(cm); + setTimeout(bind(ensureFocus, cm), 0); var now = +new Date, type = "single"; if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { type = "triple"; e_preventDefault(e); @@ -29025,10 +29084,13 @@ off(display.scroller, "drop", dragEnd); if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { e_preventDefault(e2); extendSelection(cm.doc, start); focusInput(cm); + // Work around unexplainable focus problem in IE9 (#2127) + if (old_ie && !ie_lt9) + setTimeout(function() {document.body.focus(); focusInput(cm);}, 20); } }); // Let the drag handler handle this. if (webkit) display.scroller.draggable = true; cm.state.draggingText = dragEnd; @@ -29074,11 +29136,11 @@ function extend(e) { var curCount = ++counter; var cur = posFromMouse(cm, e, true); if (!cur) return; if (!posEq(cur, last)) { - if (!cm.state.focused) onFocus(cm); + ensureFocus(cm); last = cur; doSelect(cur); var visible = visibleLines(display, doc); if (cur.line >= visible.to || cur.line < visible.from) setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); @@ -29099,43 +29161,50 @@ off(document, "mousemove", move); off(document, "mouseup", up); } var move = operation(cm, function(e) { - if (!ie && !e_button(e)) done(e); + if ((ie && !ie_lt10) ? !e.buttons : !e_button(e)) done(e); else extend(e); }); var up = operation(cm, done); on(document, "mousemove", move); on(document, "mouseup", up); } - function clickInGutter(cm, e) { - var display = cm.display; + function gutterEvent(cm, e, type, prevent, signalfn) { try { var mX = e.clientX, mY = e.clientY; } catch(e) { return false; } + if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false; + if (prevent) e_preventDefault(e); - if (mX >= Math.floor(getRect(display.gutters).right)) return false; - e_preventDefault(e); - if (!hasHandler(cm, "gutterClick")) return true; - + var display = cm.display; var lineBox = getRect(display.lineDiv); - if (mY > lineBox.bottom) return true; + + if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e); mY -= lineBox.top - display.viewOffset; for (var i = 0; i < cm.options.gutters.length; ++i) { var g = display.gutters.childNodes[i]; if (g && getRect(g).right >= mX) { var line = lineAtHeight(cm.doc, mY); var gutter = cm.options.gutters[i]; - signalLater(cm, "gutterClick", cm, line, gutter, e); - break; + signalfn(cm, type, cm, line, gutter, e); + return e_defaultPrevented(e); } } - return true; } + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) return false; + return gutterEvent(cm, e, "gutterContextMenu", false, signal); + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true, signalLater); + } + // Kludge to work around strange IE behavior where it'll sometimes // re-fire a series of drag-related events right after the drop (#1551) var lastDrop = 0; function onDrop(e) { @@ -29174,11 +29243,10 @@ var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to; setSelection(cm.doc, pos, pos); if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste"); cm.replaceSelection(text, null, "paste"); focusInput(cm); - onFocus(cm); } } catch(e){} } } @@ -29192,10 +29260,11 @@ // Use dummy image instead of default browsers image. // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. if (e.dataTransfer.setDragImage && !safari) { var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; if (opera) { img.width = img.height = 1; cm.display.wrapper.appendChild(img); // Force a relayout, or Opera won't use our image for some obscure reason img._top = img.offsetTop; @@ -29386,16 +29455,22 @@ signalLater(cm, "keyHandled", cm, "'" + ch + "'", e); } return handled; } + function onKeyUp(e) { + var cm = this; + if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + if (e.keyCode == 16) cm.doc.sel.shift = false; + } + var lastStoppedKey = null; function onKeyDown(e) { var cm = this; - if (!cm.state.focused) onFocus(cm); + ensureFocus(cm); if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; - if (ie && e.keyCode == 27) e.returnValue = false; + if (old_ie && e.keyCode == 27) e.returnValue = false; var code = e.keyCode; // IE does strange things with escape. cm.doc.sel.shift = code == 16 || e.shiftKey; // First give onKeyEvent option a chance to handle this. var handled = handleKeyBinding(cm, e); @@ -29412,14 +29487,10 @@ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; var keyCode = e.keyCode, charCode = e.charCode; if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - if (this.options.electricChars && this.doc.mode.electricChars && - this.options.smartIndent && !isReadOnly(this) && - this.doc.mode.electricChars.indexOf(ch) > -1) - setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75); if (handleCharBinding(cm, e, ch)) return; if (ie && !ie_lt9) cm.display.inputHasSelection = null; fastPoll(cm); } @@ -29450,31 +29521,35 @@ var detectingSelectAll; function onContextMenu(cm, e) { if (signalDOMEvent(cm, e, "contextmenu")) return; var display = cm.display, sel = cm.doc.sel; - if (eventInWidget(display, e)) return; + if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return; var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; if (!pos || opera) return; // Opera is difficult. - if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu; + if (reset && (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))) operation(cm, setSelection)(cm.doc, pos, pos); var oldCSS = display.input.style.cssText; display.inputDiv.style.position = "absolute"; display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + - "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" + + "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: transparent; outline: none;" + "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);"; focusInput(cm); resetInput(cm, true); // Adds "Select all" to context menu in FF if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " "; function prepareSelectAllHack() { if (display.input.selectionStart != null) { - var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value); - display.prevInput = " "; + var extval = display.input.value = "\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value); + display.prevInput = "\u200b"; display.input.selectionStart = 1; display.input.selectionEnd = extval.length; } } function rehide() { display.inputDiv.style.position = "relative"; @@ -29485,11 +29560,11 @@ // Try to detect the user choosing select-all if (display.input.selectionStart != null) { if (!ie || ie_lt9) prepareSelectAllHack(); clearTimeout(detectingSelectAll); var i = 0, poll = function(){ - if (display.prevInput == " " && display.input.selectionStart == 0) + if (display.prevInput == "\u200b" && display.input.selectionStart == 0) operation(cm, commands.selectAll)(cm); else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); else resetInput(cm); }; detectingSelectAll = setTimeout(poll, 200); @@ -29604,10 +29679,11 @@ makeChangeNoReadonly(doc, change, selUpdate); } } function makeChangeNoReadonly(doc, change, selUpdate) { + if (change.text.length == 1 && change.text[0] == "" && posEq(change.from, change.to)) return; var selAfter = computeSelAfterChange(doc, change, selUpdate); addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); var rebased = []; @@ -29766,10 +29842,11 @@ } CodeMirror.Pos = Pos; function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} + function cmp(a, b) {return a.line - b.line || a.ch - b.ch;} function copyPos(x) {return Pos(x.line, x.ch);} // SELECTION function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} @@ -29826,10 +29903,11 @@ anchor = filtered.anchor; } var sel = doc.sel; sel.goalColumn = null; + if (bias == null) bias = posLess(head, sel.head) ? -1 : 1; // Skip over atomic spans. if (checkAtomic || !posEq(anchor, sel.anchor)) anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push"); if (checkAtomic || !posEq(head, sel.head)) head = skipAtomic(doc, head, bias, checkAtomic != "push"); @@ -29903,32 +29981,35 @@ } // SCROLLING function scrollCursorIntoView(cm) { - var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin); + var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin); if (!cm.state.focused) return; var display = cm.display, box = getRect(display.sizer), doScroll = null; if (coords.top + box.top < 0) doScroll = true; else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; if (doScroll != null && !phantom) { - var hidden = display.cursor.style.display == "none"; - if (hidden) { - display.cursor.style.display = ""; - display.cursor.style.left = coords.left + "px"; - display.cursor.style.top = (coords.top - display.viewOffset) + "px"; - } - display.cursor.scrollIntoView(doScroll); - if (hidden) display.cursor.style.display = "none"; + var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " + + (coords.top - display.viewOffset) + "px; height: " + + (coords.bottom - coords.top + scrollerCutOff) + "px; left: " + + coords.left + "px; width: 2px;"); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); } } - function scrollPosIntoView(cm, pos, margin) { + function scrollPosIntoView(cm, pos, end, margin) { if (margin == null) margin = 0; for (;;) { var changed = false, coords = cursorCoords(cm, pos); - var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin); + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); + var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), + Math.min(coords.top, endCoords.top) - margin, + Math.max(coords.left, endCoords.left), + Math.max(coords.bottom, endCoords.bottom) + margin); var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop); if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; } @@ -29985,21 +30066,25 @@ } // API UTILITIES function indentLine(cm, n, how, aggressive) { - var doc = cm.doc; + var doc = cm.doc, state; if (how == null) how = "add"; if (how == "smart") { if (!cm.doc.mode.indent) how = "prev"; - else var state = getStateBefore(cm, n); + else state = getStateBefore(cm, n); } var tabSize = cm.options.tabSize; var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + if (line.stateAfter) line.stateAfter = null; var curSpaceString = line.text.match(/^\s*/)[0], indentation; - if (how == "smart") { + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); if (indentation == Pass) { if (!aggressive) return; how = "prev"; } @@ -30021,10 +30106,12 @@ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} if (pos < indentation) indentString += spaceStr(indentation - pos); if (indentString != curSpaceString) replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + else if (doc.sel.head.line == n && doc.sel.head.ch < curSpaceString.length) + setSelection(doc, Pos(n, curSpaceString.length), Pos(n, curSpaceString.length), 1); line.stateAfter = null; } function changeLine(cm, handle, op) { var no = handle, line = handle, doc = cm.doc; @@ -30063,17 +30150,19 @@ var sawType = null, group = unit == "group"; for (var first = true;; first = false) { if (dir < 0 && !moveOnce(!first)) break; var cur = lineObj.text.charAt(ch) || "\n"; var type = isWordChar(cur) ? "w" - : !group ? null - : /\s/.test(cur) ? null + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null : "p"; + if (group && !first && !type) type = "s"; if (sawType && sawType != type) { if (dir < 0) {dir = 1; moveOnce();} break; } + if (type) sawType = type; if (dir > 0 && !moveOnce(!first)) break; } } var result = skipAtomic(doc, Pos(line, ch), origDir, true); @@ -30121,11 +30210,11 @@ // The publicly visible API. Note that operation(null, f) means // 'wrap f in an operation, performed on its `this` parameter' CodeMirror.prototype = { constructor: CodeMirror, - focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);}, + focus: function(){window.focus(); focusInput(this); fastPoll(this);}, setOption: function(option, value) { var options = this.options, old = options[option]; if (options[option] == value && option != "mode") return; options[option] = value; @@ -30175,11 +30264,11 @@ } if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); }), indentSelection: operation(null, function(how) { var sel = this.doc.sel; - if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how); + if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how, true); var e = sel.to.line - (sel.to.ch ? 0 : 1); for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how); }), // Fetch the parser token for a given character. Useful for hacks @@ -30220,15 +30309,35 @@ if (!mode.innerMode) return mode; return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; }, getHelper: function(pos, type) { - if (!helpers.hasOwnProperty(type)) return; + return this.getHelpers(pos, type)[0]; + }, + + getHelpers: function(pos, type) { + var found = []; + if (!helpers.hasOwnProperty(type)) return helpers; var help = helpers[type], mode = this.getModeAt(pos); - return mode[type] && help[mode[type]] || - mode.helperType && help[mode.helperType] || - help[mode.name]; + if (typeof mode[type] == "string") { + if (help[mode[type]]) found.push(help[mode[type]]); + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) found.push(val); + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i = 0; i < help._global.length; i++) { + var cur = help._global[i]; + if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) + found.push(cur.val); + } + return found; }, getStateAfter: function(line, precise) { var doc = this.doc; line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); @@ -30370,12 +30479,17 @@ if (scroll) scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); }, triggerOnKeyDown: operation(null, onKeyDown), + triggerOnKeyPress: operation(null, onKeyPress), + triggerOnKeyUp: operation(null, onKeyUp), - execCommand: function(cmd) {return commands[cmd](this);}, + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + return commands[cmd](this); + }, findPosH: function(from, amount, unit, visually) { var dir = 1; if (amount < 0) { dir = -1; amount = -amount; } for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { @@ -30413,28 +30527,34 @@ } return cur; }, moveV: operation(null, function(dir, unit) { - var sel = this.doc.sel; - var pos = cursorCoords(this, sel.head, "div"); - if (sel.goalColumn != null) pos.left = sel.goalColumn; - var target = findPosV(this, pos, dir, unit); - - if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top); + var sel = this.doc.sel, target, goal; + if (sel.shift || sel.extend || posEq(sel.from, sel.to)) { + var pos = cursorCoords(this, sel.head, "div"); + if (sel.goalColumn != null) pos.left = sel.goalColumn; + target = findPosV(this, pos, dir, unit); + if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top); + goal = pos.left; + } else { + target = dir < 0 ? sel.from : sel.to; + } extendSelection(this.doc, target, target, dir); - sel.goalColumn = pos.left; + if (goal != null) sel.goalColumn = goal; }), toggleOverwrite: function(value) { if (value != null && value == this.state.overwrite) return; if (this.state.overwrite = !this.state.overwrite) this.display.cursor.className += " CodeMirror-overwrite"; else this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", ""); + + signal(this, "overwriteToggle", this, this.state.overwrite); }, - hasFocus: function() { return this.state.focused; }, + hasFocus: function() { return document.activeElement == this.display.input; }, scrollTo: operation(null, function(x, y) { updateScrollPos(this, x, y); }), getScrollInfo: function() { @@ -30442,21 +30562,27 @@ return {left: scroller.scrollLeft, top: scroller.scrollTop, height: scroller.scrollHeight - co, width: scroller.scrollWidth - co, clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co}; }, - scrollIntoView: operation(null, function(pos, margin) { - if (typeof pos == "number") pos = Pos(pos, 0); + scrollIntoView: operation(null, function(range, margin) { + if (range == null) range = {from: this.doc.sel.head, to: null}; + else if (typeof range == "number") range = {from: Pos(range, 0), to: null}; + else if (range.from == null) range = {from: range, to: null}; + if (!range.to) range.to = range.from; if (!margin) margin = 0; - var coords = pos; - if (!pos || pos.line != null) { - this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head; - this.curOp.scrollToPosMargin = margin; - coords = cursorCoords(this, this.curOp.scrollToPos); + var coords = range; + if (range.from.line != null) { + this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin}; + coords = {from: cursorCoords(this, range.from), + to: cursorCoords(this, range.to)}; } - var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin); + var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left), + Math.min(coords.from.top, coords.to.top) - margin, + Math.max(coords.from.right, coords.to.right), + Math.max(coords.from.bottom, coords.to.bottom) + margin); updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop); }), setSize: operation(null, function(width, height) { function interpret(val) { @@ -30465,27 +30591,33 @@ if (width != null) this.display.wrapper.style.width = interpret(width); if (height != null) this.display.wrapper.style.height = interpret(height); if (this.options.lineWrapping) this.display.measureLineCache.length = this.display.measureLineCachePos = 0; this.curOp.forceUpdate = true; + signal(this, "refresh", this); }), operation: function(f){return runInOp(this, f);}, refresh: operation(null, function() { + var oldHeight = this.display.cachedTextHeight; clearCaches(this); updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop); regChange(this); + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) + estimateLineHeights(this); + signal(this, "refresh", this); }), swapDoc: operation(null, function(doc) { var old = this.doc; old.cm = null; attachDoc(this, doc); clearCaches(this); resetInput(this, true); updateScrollPos(this, doc.scrollLeft, doc.scrollTop); + signalLater(this, "swapDoc", this, old); return old; }), getInputField: function(){return this.display.input;}, getWrapperElement: function(){return this.display.wrapper;}, @@ -30521,16 +30653,22 @@ option("indentUnit", 2, loadMode, true); option("indentWithTabs", false); option("smartIndent", true); option("tabSize", 4, function(cm) { - loadMode(cm); + resetModeState(cm); clearCaches(cm); regChange(cm); }, true); + option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) { + cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + cm.refresh(); + }, true); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); option("electricChars", true); option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); option("theme", "default", function(cm) { themeChanged(cm); guttersChanged(cm); }, true); @@ -30556,27 +30694,38 @@ }, true); option("firstLineNumber", 1, guttersChanged, true); option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); option("showCursorWhenSelecting", false, updateSelection, true); + option("resetSelectionOnContextMenu", true); + option("readOnly", false, function(cm, val) { - if (val == "nocursor") {onBlur(cm); cm.display.input.blur();} - else if (!val) resetInput(cm, true); + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + cm.display.disabled = true; + } else { + cm.display.disabled = false; + if (!val) resetInput(cm, true); + } }); + option("disableInput", false, function(cm, val) {if (!val) resetInput(cm, true);}, true); option("dragDrop", true); option("cursorBlinkRate", 530); option("cursorScrollMargin", 0); option("cursorHeight", 1); option("workTime", 100); option("workDelay", 100); - option("flattenSpans", true); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); option("pollInterval", 100); option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;}); option("historyEventDelay", 500); option("viewportMargin", 10, function(cm){cm.refresh();}, true); - option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("crudeMeasuringFrom", 10000); option("moveInputWithCursor", true, function(cm, val) { if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0; }); option("tabindex", null, function(cm, val) { @@ -30605,10 +30754,11 @@ CodeMirror.resolveMode = function(spec) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { var found = mimeModes[spec.name]; + if (typeof found == "string") found = {name: found}; spec = createObj(found, spec); spec.name = found.name; } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { return CodeMirror.resolveMode("application/xml"); } @@ -30628,10 +30778,13 @@ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; modeObj[prop] = exts[prop]; } } modeObj.name = spec.name; + if (spec.helperType) modeObj.helperType = spec.helperType; + if (spec.modeProps) for (var prop in spec.modeProps) + modeObj[prop] = spec.modeProps[prop]; return modeObj; }; CodeMirror.defineMode("null", function() { @@ -30658,13 +30811,17 @@ var initHooks = []; CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; var helpers = CodeMirror.helpers = {}; CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {}; + if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; helpers[type][name] = value; }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; // UTILITIES CodeMirror.isWordChar = isWordChar; @@ -30710,11 +30867,11 @@ cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete"); else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete"); }, deleteLine: function(cm) { var l = cm.getCursor().line; - cm.replaceRange("", Pos(l, 0), Pos(l), "+delete"); + cm.replaceRange("", Pos(l, 0), Pos(l + 1, 0), "+delete"); }, delLineLeft: function(cm) { var cur = cm.getCursor(); cm.replaceRange("", Pos(cur.line, 0), cur, "+delete"); }, @@ -30765,11 +30922,13 @@ delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, delGroupAfter: function(cm) {cm.deleteH(1, "group");}, indentAuto: function(cm) {cm.indentSelection("smart");}, indentMore: function(cm) {cm.indentSelection("add");}, indentLess: function(cm) {cm.indentSelection("subtract");}, - insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");}, + insertTab: function(cm) { + cm.replaceSelection("\t", "end", "+input"); + }, defaultTab: function(cm) { if (cm.somethingSelected()) cm.indentSelection("add"); else cm.replaceSelection("\t", "end", "+input"); }, transposeChars: function(cm) { @@ -30791,18 +30950,19 @@ var keyMap = CodeMirror.keyMap = {}; keyMap.basic = { "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" }; // Note that the save and find-related commands aren't defined by // default. Unknown commands are simply ignored. keyMap.pcDefault = { "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", + "Ctrl-Home": "goDocStart", "Ctrl-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", fallthrough: "basic" @@ -30937,15 +31097,16 @@ function StringStream(string, tabSize) { this.pos = this.start = 0; this.string = string; this.tabSize = tabSize || 8; this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; } StringStream.prototype = { eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == 0;}, + sol: function() {return this.pos == this.lineStart;}, peek: function() {return this.string.charAt(this.pos) || undefined;}, next: function() { if (this.pos < this.string.length) return this.string.charAt(this.pos++); }, @@ -30974,13 +31135,16 @@ column: function() { if (this.lastColumnPos < this.start) { this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); this.lastColumnPos = this.start; } - return this.lastColumnValue; + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); }, - indentation: function() {return countColumn(this.string, null, this.tabSize);}, + indentation: function() { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }, match: function(pattern, consume, caseInsensitive) { if (typeof pattern == "string") { var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; var substr = this.string.substr(this.pos, pattern.length); if (cased(substr) == cased(pattern)) { @@ -30992,11 +31156,16 @@ if (match && match.index > 0) return null; if (match && consume !== false) this.pos += match[0].length; return match; } }, - current: function(){return this.string.slice(this.start, this.pos);} + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } }; CodeMirror.StringStream = StringStream; // TEXTMARKERS @@ -31044,22 +31213,22 @@ if (cm) reCheckSelection(cm); } if (withOp) endOperation(cm); }; - TextMarker.prototype.find = function() { + TextMarker.prototype.find = function(bothSides) { var from, to; for (var i = 0; i < this.lines.length; ++i) { var line = this.lines[i]; var span = getMarkedSpanFor(line.markedSpans, this); if (span.from != null || span.to != null) { var found = lineNo(line); if (span.from != null) from = Pos(found, span.from); if (span.to != null) to = Pos(found, span.to); } } - if (this.type == "bookmark") return from; + if (this.type == "bookmark" && !bothSides) return from; return from && {from: from, to: to}; }; TextMarker.prototype.changed = function() { var pos = this.find(), cm = this.doc.cm; @@ -31092,41 +31261,44 @@ var op = this.doc.cm.curOp; (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); } }; + var nextMarkerId = 0; + function markText(doc, from, to, options, type) { if (options && options.shared) return markTextShared(doc, from, to, options, type); if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); var marker = new TextMarker(doc, type); - if (type == "range" && !posLess(from, to)) return marker; if (options) copyObj(options, marker); + if (posLess(to, from) || posEq(from, to) && marker.clearWhenEmpty !== false) + return marker; if (marker.replacedWith) { marker.collapsed = true; marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget"); if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true; } - if (marker.collapsed) sawCollapsedSpans = true; + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + throw new Error("Inserting collapsed marker partially overlapping an existing one"); + sawCollapsedSpans = true; + } if (marker.addToHistory) addToHistory(doc, {from: from, to: to, origin: "markText"}, {head: doc.sel.head, anchor: doc.sel.anchor}, NaN); - var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine; + var curLine = from.line, cm = doc.cm, updateMaxLine; doc.iter(curLine, to.line + 1, function(line) { if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine) updateMaxLine = true; var span = {from: null, to: null, marker: marker}; - size += line.text.length; - if (curLine == from.line) {span.from = from.ch; size -= from.ch;} - if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;} - if (marker.collapsed) { - if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch); - if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch); - else updateLineHeight(line, 0); - } + if (curLine == from.line) span.from = from.ch; + if (curLine == to.line) span.to = to.ch; + if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); addMarkedSpan(line, span); ++curLine; }); if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { if (lineIsHidden(doc, line)) updateLineHeight(line, 0); @@ -31138,13 +31310,11 @@ sawReadOnlySpans = true; if (doc.history.done.length || doc.history.undone.length) doc.clearHistory(); } if (marker.collapsed) { - if (collapsedAtStart != collapsedAtEnd) - throw new Error("Inserting collapsed marker overlapping an existing one"); - marker.size = size; + marker.id = ++nextMarkerId; marker.atomic = true; } if (cm) { if (updateMaxLine) cm.curOp.updateMaxLine = true; if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed) @@ -31213,11 +31383,11 @@ function markedSpansBefore(old, startCh, isInsert) { if (old) for (var i = 0, nw; i < old.length; ++i) { var span = old[i], marker = span.marker; var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) { + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); (nw || (nw = [])).push({from: span.from, to: endsAfter ? null : span.to, marker: marker}); } @@ -31227,11 +31397,11 @@ function markedSpansAfter(old, endCh, isInsert) { if (old) for (var i = 0, nw; i < old.length; ++i) { var span = old[i], marker = span.marker; var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) { + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh, to: span.to == null ? null : span.to - endCh, marker: marker}); } @@ -31277,17 +31447,13 @@ span.from += offset; if (sameLine) (first || (first = [])).push(span); } } } - if (sameLine && first) { - // Make sure we didn't create any zero-length spans - for (var i = 0; i < first.length; ++i) - if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark") - first.splice(i--, 1); - if (!first.length) first = null; - } + // Make sure we didn't create any zero-length spans + if (first) first = clearEmptySpans(first); + if (last && last != first) last = clearEmptySpans(last); var newMarkers = [first]; if (!sameLine) { // Fill gap with whole-line-spans var gap = change.text.length - 2, gapMarkers; @@ -31300,10 +31466,20 @@ newMarkers.push(last); } return newMarkers; } + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + spans.splice(i--, 1); + } + if (!spans.length) return null; + return spans; + } + function mergeOldSpans(doc, change) { var old = getOldSpans(doc, change); var stretched = stretchSpansOverChange(doc, change); if (!old) return stretched; if (!stretched) return old; @@ -31350,25 +31526,53 @@ } } return parts; } - function collapsedSpanAt(line, ch) { + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; } + + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) return lenDiff; + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) return -fromCmp; + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) return toCmp; + return b.id - a.id; + } + + function collapsedSpanAtSide(line, start) { var sps = sawCollapsedSpans && line.markedSpans, found; if (sps) for (var sp, i = 0; i < sps.length; ++i) { sp = sps[i]; - if (!sp.marker.collapsed) continue; - if ((sp.from == null || sp.from < ch) && - (sp.to == null || sp.to > ch) && - (!found || found.width < sp.marker.width)) + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) found = sp.marker; } return found; } - function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); } - function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); } + function conflictingCollapsedRange(doc, lineNo, from, to, marker) { + var line = getLine(doc, lineNo); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) continue; + var found = sp.marker.find(true); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; + if (fromCmp <= 0 && (cmp(found.to, from) || extraRight(sp.marker) - extraLeft(marker)) > 0 || + fromCmp >= 0 && (cmp(found.from, to) || extraLeft(sp.marker) - extraRight(marker)) < 0) + return true; + } + } + function visualLine(doc, line) { var merged; while (merged = collapsedSpanAtStart(line)) line = getLine(doc, merged.find().from.line); return line; @@ -31393,10 +31597,11 @@ if (span.marker.inclusiveRight && span.to == line.text.length) return true; for (var sp, i = 0; i < line.markedSpans.length; ++i) { sp = line.markedSpans[i]; if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to && + (sp.to == null || sp.to != span.from) && (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && lineIsHiddenInner(doc, line, sp)) return true; } } @@ -31470,10 +31675,11 @@ widget.line = line; if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) { var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop; updateLineHeight(line, line.height + widgetHeight(widget)); if (aboveVisible) addToScrollPos(cm, 0, widget.height); + cm.curOp.forceUpdate = true; } return true; }); return widget; } @@ -31486,10 +31692,11 @@ this.text = text; attachMarkedSpans(this, markedSpans); this.height = estimateHeight ? estimateHeight(this) : 1; }; eventMixin(Line); + Line.prototype.lineNo = function() { return lineNo(this); }; function updateLine(line, text, markedSpans, estimateHeight) { line.text = text; if (line.stateAfter) line.stateAfter = null; if (line.styles) line.styles = null; @@ -31506,40 +31713,51 @@ } // Run the given mode's parser over a line, update the styles // array, which contains alternating fragments of text and CSS // classes. - function runMode(cm, text, mode, state, f) { + function runMode(cm, text, mode, state, f, forceToEnd) { var flattenSpans = mode.flattenSpans; if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; var curStart = 0, curStyle = null; var stream = new StringStream(text, cm.options.tabSize), style; if (text == "" && mode.blankLine) mode.blankLine(state); while (!stream.eol()) { if (stream.pos > cm.options.maxHighlightLength) { flattenSpans = false; - // Webkit seems to refuse to render text nodes longer than 57444 characters - stream.pos = Math.min(text.length, stream.start + 50000); + if (forceToEnd) processLine(cm, text, state, stream.pos); + stream.pos = text.length; style = null; } else { style = mode.token(stream, state); } + if (cm.options.addModeClass) { + var mName = CodeMirror.innerMode(mode, state).mode.name; + if (mName) style = "m-" + (style ? mName + " " + style : mName); + } if (!flattenSpans || curStyle != style) { if (curStart < stream.start) f(stream.start, curStyle); curStart = stream.start; curStyle = style; } stream.start = stream.pos; } - if (curStart < stream.pos) f(stream.pos, curStyle); + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 characters + var pos = Math.min(stream.pos, curStart + 50000); + f(pos, curStyle); + curStart = pos; + } } - function highlightLine(cm, line, state) { + function highlightLine(cm, line, state, forceToEnd) { // A styles array always starts with a number identifying the // mode/overlays that it is based on (for easy invalidation). var st = [cm.state.modeGen]; // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);}); + runMode(cm, line.text, cm.doc.mode, state, function(end, style) { + st.push(end, style); + }, forceToEnd); // Run overlays, adjust style array. for (var o = 0; o < cm.state.overlays.length; ++o) { var overlay = cm.state.overlays[o], i = 1, at = 0; runMode(cm, line.text, overlay.mode, true, function(end, style) { @@ -31574,36 +31792,48 @@ return line.styles; } // Lightweight form of highlight -- proceed over this line and // update state, but don't save a style array. - function processLine(cm, line, state) { + function processLine(cm, text, state, startAt) { var mode = cm.doc.mode; - var stream = new StringStream(line.text, cm.options.tabSize); - if (line.text == "" && mode.blankLine) mode.blankLine(state); + var stream = new StringStream(text, cm.options.tabSize); + stream.start = stream.pos = startAt || 0; + if (text == "" && mode.blankLine) mode.blankLine(state); while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) { mode.token(stream, state); stream.start = stream.pos; } } - var styleToClassCache = {}; - function styleToClass(style) { + var styleToClassCache = {}, styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, builder) { if (!style) return null; - return styleToClassCache[style] || - (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-")); + for (;;) { + var lineClass = style.match(/(?:^|\s+)line-(background-)?(\S+)/); + if (!lineClass) break; + style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (builder[prop] == null) + builder[prop] = lineClass[2]; + else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop])) + builder[prop] += " " + lineClass[2]; + } + if (/^\s*$/.test(style)) return null; + var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")); } - function lineContent(cm, realLine, measure, copyWidgets) { + function buildLineContent(cm, realLine, measure, copyWidgets) { var merged, line = realLine, empty = true; while (merged = collapsedSpanAtStart(line)) line = getLine(cm.doc, merged.find().from.line); var builder = {pre: elt("pre"), col: 0, pos: 0, measure: null, measuredSomething: false, cm: cm, copyWidgets: copyWidgets}; - if (line.textClass) builder.pre.className = line.textClass; do { if (line.text) empty = false; builder.measure = line == realLine && measure; builder.pos = 0; @@ -31636,25 +31866,34 @@ if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure), span.nextSibling); } } + var textClass = builder.textClass ? builder.textClass + " " + (realLine.textClass || "") : realLine.textClass; + if (textClass) builder.pre.className = textClass; + signal(cm, "renderLine", cm, realLine, builder.pre); - return builder.pre; + return builder; } - var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g; + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + return token; + } + function buildToken(builder, text, style, startStyle, endStyle, title) { if (!text) return; - if (!tokenSpecialChars.test(text)) { + var special = builder.cm.options.specialChars; + if (!special.test(text)) { builder.col += text.length; var content = document.createTextNode(text); } else { var content = document.createDocumentFragment(), pos = 0; while (true) { - tokenSpecialChars.lastIndex = pos; - var m = tokenSpecialChars.exec(text); + special.lastIndex = pos; + var m = special.exec(text); var skipped = m ? m.index - pos : text.length - pos; if (skipped) { content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); builder.col += skipped; } @@ -31663,12 +31902,11 @@ if (m[0] == "\t") { var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); builder.col += tabWidth; } else { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + m[0].charCodeAt(0).toString(16); + var token = builder.cm.options.specialCharPlaceholder(m[0]); content.appendChild(token); builder.col += 1; } } } @@ -31684,26 +31922,25 @@ } function buildTokenMeasure(builder, text, style, startStyle, endStyle) { var wrapping = builder.cm.options.lineWrapping; for (var i = 0; i < text.length; ++i) { - var ch = text.charAt(i), start = i == 0; - if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) { - ch = text.slice(i, i + 2); - ++i; - } else if (i && wrapping && spanAffectsWrapping(text, i)) { + var start = i == 0, to = i + 1; + while (to < text.length && isExtendingChar(text.charAt(to))) ++to; + var ch = text.slice(i, to); + i = to - 1; + if (i && wrapping && spanAffectsWrapping(text, i)) builder.pre.appendChild(elt("wbr")); - } var old = builder.measure[builder.pos]; var span = builder.measure[builder.pos] = buildToken(builder, ch, style, start && startStyle, i == text.length - 1 && endStyle); if (old) span.leftSide = old.leftSide || old; // In IE single-space nodes wrap differently than spaces // embedded in larger text nodes, except when set to // white-space: normal (issue #1268). - if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) && + if (old_ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) && i < text.length - 1 && !/\s/.test(text.charAt(i + 1))) span.style.whiteSpace = "normal"; builder.pos += ch.length; } if (text.length) builder.measuredSomething = true; @@ -31715,11 +31952,11 @@ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0"; out += " "; return out; } return function(builder, text, style, startStyle, endStyle, title) { - return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title); + return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title); }; } function buildCollapsedSpan(builder, size, marker, ignoreWidget) { var widget = !ignoreWidget && marker.replacedWith; @@ -31748,11 +31985,11 @@ // and marked text into account. function insertLineContent(line, builder, styles) { var spans = line.markedSpans, allText = line.text, at = 0; if (!spans) { for (var i = 1; i < styles.length; i+=2) - builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1])); + builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder)); return; } var len = allText.length, pos = 0, i = 1, text = "", style; var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; @@ -31767,11 +32004,11 @@ if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } if (m.className) spanStyle += " " + m.className; if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; if (m.title && !title) title = m.title; - if (m.collapsed && (!collapsed || collapsed.marker.size < m.size)) + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) collapsed = sp; } else if (sp.from > pos && nextChange > sp.from) { nextChange = sp.from; } if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m); @@ -31798,11 +32035,11 @@ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} pos = end; spanStartStyle = ""; } text = allText.slice(at, at = styles[i++]); - style = styleToClass(styles[i++]); + style = interpretTokenStyle(styles[i++], builder); } } } // DOCUMENT DATA STRUCTURE @@ -31817,11 +32054,12 @@ var from = change.from, to = change.to, text = change.text; var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; // First adjust the line structure - if (from.ch == 0 && to.ch == 0 && lastText == "") { + if (from.ch == 0 && to.ch == 0 && lastText == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore)) { // This is a whole-line replace. Treated specially to make // sure line objects move the way they are supposed to. for (var i = 0, e = text.length - 1, added = []; i < e; ++i) added.push(new Line(text[i], spansFor(i), estimateHeight)); update(lastLine, lastLine.text, lastSpans); @@ -32099,14 +32337,15 @@ return {undo: hist.done.length, redo: hist.undone.length}; }, clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);}, markClean: function() { - this.cleanGeneration = this.changeGeneration(); + this.cleanGeneration = this.changeGeneration(true); }, - changeGeneration: function() { - this.history.lastOp = this.history.lastOrigin = null; + changeGeneration: function(forceSplit) { + if (forceSplit) + this.history.lastOp = this.history.lastOrigin = null; return this.history.generation; }, isClean: function (gen) { return this.history.generation == (gen || this.cleanGeneration); }, @@ -32124,11 +32363,12 @@ markText: function(from, to, options) { return markText(this, clipPos(this, from), clipPos(this, to), options, "range"); }, setBookmark: function(pos, options) { var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft}; + insertLeft: options && options.insertLeft, + clearWhenEmpty: false}; pos = clipPos(this, pos); return markText(this, pos, pos, realOpts, "bookmark"); }, findMarksAt: function(pos) { pos = clipPos(this, pos); @@ -32139,10 +32379,26 @@ (span.to == null || span.to >= pos.ch)) markers.push(span.marker.parent || span.marker); } return markers; }, + findMarks: function(from, to) { + from = clipPos(this, from); to = clipPos(this, to); + var found = [], lineNo = from.line; + this.iter(from.line, to.line + 1, function(line) { + var spans = line.markedSpans; + if (spans) for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + if (!(lineNo == from.line && from.ch > span.to || + span.from == null && lineNo != from.line|| + lineNo == to.line && span.from > to.ch)) + found.push(span.marker.parent || span.marker); + } + ++lineNo; + }); + return found; + }, getAllMarks: function() { var markers = []; this.iter(function(line) { var sps = line.markedSpans; if (sps) for (var i = 0; i < sps.length; ++i) @@ -32405,17 +32661,19 @@ cur = {changes: [historyChangeFromChange(doc, change)], generation: hist.generation, anchorBefore: doc.sel.anchor, headBefore: doc.sel.head, anchorAfter: selAfter.anchor, headAfter: selAfter.head}; hist.done.push(cur); - hist.generation = ++hist.maxGeneration; while (hist.done.length > hist.undoDepth) hist.done.shift(); } + hist.generation = ++hist.maxGeneration; hist.lastTime = time; hist.lastOp = opId; hist.lastOrigin = change.origin; + + if (!last) signal(doc, "historyAdded"); } function removeClearedSpans(spans) { if (!spans) return null; for (var i = 0, out; i < spans.length; ++i) { @@ -32693,22 +32951,23 @@ function bind(f) { var args = Array.prototype.slice.call(arguments, 1); return function(){return f.apply(null, args);}; } - var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; function isWordChar(ch) { return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); } function isEmpty(obj) { for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; return true; } - var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/; + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } // DOM UTILITIES function elt(tag, content, className, style) { var e = document.createElement(tag); @@ -32766,17 +33025,22 @@ }; else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) spanAffectsWrapping = function(str, i) { return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1)); }; - else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent)) + else if (webkit && /Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent)) spanAffectsWrapping = function(str, i) { + var code = str.charCodeAt(i - 1); + return code >= 8208 && code <= 8212; + }; + else if (webkit) + spanAffectsWrapping = function(str, i) { if (i > 1 && str.charCodeAt(i - 1) == 45) { if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true; if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false; } - return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1)); + return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|\u2026[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1)); }; var knownScrollbarWidth; function scrollbarWidth(measure) { if (knownScrollbarWidth != null) return knownScrollbarWidth; @@ -32840,18 +33104,18 @@ // KEY NAMING var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 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", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete", - 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home", - 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"}; + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"}; CodeMirror.keyNames = keyNames; (function() { // Number keys - for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); + for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i); // Alphabetic keys for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); // Function keys for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; })(); @@ -32904,33 +33168,33 @@ if (b == linedir) return false; return a < b; } var bidiOther; function getBidiPartAt(order, pos) { + bidiOther = null; for (var i = 0, found; i < order.length; ++i) { var cur = order[i]; - if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; } - if (cur.from == pos || cur.to == pos) { + if (cur.from < pos && cur.to > pos) return i; + if ((cur.from == pos || cur.to == pos)) { if (found == null) { found = i; } else if (compareBidiLevel(order, cur.level, order[found].level)) { - bidiOther = found; + if (cur.from != cur.to) bidiOther = found; return i; } else { - bidiOther = i; + if (cur.from != cur.to) bidiOther = i; return found; } } } - bidiOther = null; return found; } function moveInLine(line, pos, dir, byUnit) { if (!byUnit) return pos + dir; do pos += dir; - while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); + while (pos > 0 && isExtendingChar(line.text.charAt(pos))); return pos; } // This is somewhat involved. It is needed in order to move // 'visually' through bi-directional text -- i.e., pressing left @@ -32961,11 +33225,11 @@ } } function moveLogically(line, start, dir, byUnit) { var target = start + dir; - if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir; + if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; return target < 0 || target > line.text.length ? null : target; } // Bidirectional ordering algorithm // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm @@ -33053,11 +33317,11 @@ for (var i = 0; i < len; ++i) { var type = types[i]; if (type == ",") types[i] = "N"; else if (type == "%") { for (var end = i + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N"; + var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; for (var j = i; j < end; ++j) types[j] = replace; i = end - 1; } } @@ -33078,11 +33342,11 @@ // N2. Any remaining neutrals take the embedding direction. for (var i = 0; i < len; ++i) { if (isNeutral.test(types[i])) { for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} var before = (i ? types[i-1] : outerType) == "L"; - var after = (end < len - 1 ? types[end] : outerType) == "L"; + var after = (end < len ? types[end] : outerType) == "L"; var replace = before || after ? "L" : "R"; for (var j = i; j < end; ++j) types[j] = replace; i = end - 1; } } @@ -33128,11 +33392,11 @@ }; })(); // THE END - CodeMirror.version = "3.16.0"; + CodeMirror.version = "3.22.0"; return CodeMirror; })(); window.tinyMCEPreInit = window.tinyMCEPreInit || { base: '/assets/tinymce', @@ -36256,312 +36520,337 @@ if (base.blankLine) base.blankLine(state.base); if (overlay.blankLine) overlay.blankLine(state.overlay); } }; }; -CodeMirror.defineMode("css", function(config) { - return CodeMirror.getMode(config, "text/css"); -}); - -CodeMirror.defineMode("css-base", function(config, parserConfig) { +CodeMirror.defineMode("css", function(config, parserConfig) { "use strict"; + if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); + var indentUnit = config.indentUnit, - hooks = parserConfig.hooks || {}, - atMediaTypes = parserConfig.atMediaTypes || {}, - atMediaFeatures = parserConfig.atMediaFeatures || {}, + tokenHooks = parserConfig.tokenHooks, + mediaTypes = parserConfig.mediaTypes || {}, + mediaFeatures = parserConfig.mediaFeatures || {}, propertyKeywords = parserConfig.propertyKeywords || {}, colorKeywords = parserConfig.colorKeywords || {}, valueKeywords = parserConfig.valueKeywords || {}, - allowNested = !!parserConfig.allowNested, - type = null; + fontProperties = parserConfig.fontProperties || {}, + allowNested = parserConfig.allowNested; + var type, override; function ret(style, tp) { type = tp; return style; } + // Tokenizers + function tokenBase(stream, state) { var ch = stream.next(); - if (hooks[ch]) { - // result[0] is style and result[1] is type - var result = hooks[ch](stream, state); + if (tokenHooks[ch]) { + var result = tokenHooks[ch](stream, state); if (result !== false) return result; } - if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());} - else if (ch == "=") ret(null, "compare"); - else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); - else if (ch == "\"" || ch == "'") { + if (ch == "@") { + stream.eatWhile(/[\w\\\-]/); + return ret("def", stream.current()); + } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) { + return ret(null, "compare"); + } else if (ch == "\"" || ch == "'") { state.tokenize = tokenString(ch); return state.tokenize(stream, state); - } - else if (ch == "#") { + } else if (ch == "#") { stream.eatWhile(/[\w\\\-]/); return ret("atom", "hash"); - } - else if (ch == "!") { + } else if (ch == "!") { stream.match(/^\s*\w*/); return ret("keyword", "important"); - } - else if (/\d/.test(ch)) { + } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); - } - else if (ch === "-") { - if (/\d/.test(stream.peek())) { + } else if (ch === "-") { + if (/[\d.]/.test(stream.peek())) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); } else if (stream.match(/^[^-]+-/)) { return ret("meta", "meta"); } - } - else if (/[,+>*\/]/.test(ch)) { + } else if (/[,+>*\/]/.test(ch)) { return ret(null, "select-op"); - } - else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { + } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { return ret("qualifier", "qualifier"); - } - else if (ch == ":") { - return ret("operator", ch); - } - else if (/[;{}\[\]\(\)]/.test(ch)) { + } else if (/[:;{}\[\]\(\)]/.test(ch)) { return ret(null, ch); - } - else if (ch == "u" && stream.match("rl(")) { + } else if (ch == "u" && stream.match("rl(")) { stream.backUp(1); state.tokenize = tokenParenthesized; - return ret("property", "variable"); - } - else { + return ret("property", "word"); + } else if (/[\w\\\-]/.test(ch)) { stream.eatWhile(/[\w\\\-]/); - return ret("property", "variable"); + return ret("property", "word"); + } else { + return ret(null, null); } } - function tokenString(quote, nonInclusive) { + function tokenString(quote) { return function(stream, state) { var escaped = false, ch; while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) + if (ch == quote && !escaped) { + if (quote == ")") stream.backUp(1); break; + } escaped = !escaped && ch == "\\"; } - if (!escaped) { - if (nonInclusive) stream.backUp(1); - state.tokenize = tokenBase; - } + if (ch == quote || !escaped && quote != ")") state.tokenize = null; return ret("string", "string"); }; } function tokenParenthesized(stream, state) { stream.next(); // Must be '(' if (!stream.match(/\s*[\"\']/, false)) - state.tokenize = tokenString(")", true); + state.tokenize = tokenString(")"); else - state.tokenize = tokenBase; + state.tokenize = null; return ret(null, "("); } - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: [], - lastToken: null}; - }, + // Context management - token: function(stream, state) { + function Context(type, indent, prev) { + this.type = type; + this.indent = indent; + this.prev = prev; + } - // Use these terms when applicable (see http://www.xanthir.com/blog/b4E50) - // - // rule** or **ruleset: - // A selector + braces combo, or an at-rule. - // - // declaration block: - // A sequence of declarations. - // - // declaration: - // A property + colon + value combo. - // - // property value: - // The entire value of a property. - // - // component value: - // A single piece of a property value. Like the 5px in - // text-shadow: 0 0 5px blue;. Can also refer to things that are - // multiple terms, like the 1-4 terms that make up the background-size - // portion of the background shorthand. - // - // term: - // The basic unit of author-facing CSS, like a single number (5), - // dimension (5px), string ("foo"), or function. Officially defined - // by the CSS 2.1 grammar (look for the 'term' production) - // - // - // simple selector: - // A single atomic selector, like a type selector, an attr selector, a - // class selector, etc. - // - // compound selector: - // One or more simple selectors without a combinator. div.example is - // compound, div > .example is not. - // - // complex selector: - // One or more compound selectors chained with combinators. - // - // combinator: - // The parts of selectors that express relationships. There are four - // currently - the space (descendant combinator), the greater-than - // bracket (child combinator), the plus sign (next sibling combinator), - // and the tilda (following sibling combinator). - // - // sequence of selectors: - // One or more of the named type of selector chained with commas. + function pushContext(state, stream, type) { + state.context = new Context(type, stream.indentation() + indentUnit, state.context); + return type; + } - state.tokenize = state.tokenize || tokenBase; - if (state.tokenize == tokenBase && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (style && typeof style != "string") style = ret(style[0], style[1]); + function popContext(state) { + state.context = state.context.prev; + return state.context.type; + } - // Changing style returned based on context - var context = state.stack[state.stack.length-1]; - if (style == "variable") { - if (type == "variable-definition") state.stack.push("propertyValue"); - return state.lastToken = "variable-2"; - } else if (style == "property") { - var word = stream.current().toLowerCase(); - if (context == "propertyValue") { - if (valueKeywords.hasOwnProperty(word)) { - style = "string-2"; - } else if (colorKeywords.hasOwnProperty(word)) { - style = "keyword"; - } else { - style = "variable-2"; - } - } else if (context == "rule") { - if (!propertyKeywords.hasOwnProperty(word)) { - style += " error"; - } - } else if (context == "block") { - // if a value is present in both property, value, or color, the order - // of preference is property -> color -> value - if (propertyKeywords.hasOwnProperty(word)) { - style = "property"; - } else if (colorKeywords.hasOwnProperty(word)) { - style = "keyword"; - } else if (valueKeywords.hasOwnProperty(word)) { - style = "string-2"; - } else { - style = "tag"; - } - } else if (!context || context == "@media{") { - style = "tag"; - } else if (context == "@media") { - if (atMediaTypes[stream.current()]) { - style = "attribute"; // Known attribute - } else if (/^(only|not)$/.test(word)) { - style = "keyword"; - } else if (word == "and") { - style = "error"; // "and" is only allowed in @mediaType - } else if (atMediaFeatures.hasOwnProperty(word)) { - style = "error"; // Known property, should be in @mediaType( - } else { - // Unknown, expecting keyword or attribute, assuming attribute - style = "attribute error"; - } - } else if (context == "@mediaType") { - if (atMediaTypes.hasOwnProperty(word)) { - style = "attribute"; - } else if (word == "and") { - style = "operator"; - } else if (/^(only|not)$/.test(word)) { - style = "error"; // Only allowed in @media - } else { - // Unknown attribute or property, but expecting property (preceded - // by "and"). Should be in parentheses - style = "error"; - } - } else if (context == "@mediaType(") { - if (propertyKeywords.hasOwnProperty(word)) { - // do nothing, remains "property" - } else if (atMediaTypes.hasOwnProperty(word)) { - style = "error"; // Known property, should be in parentheses - } else if (word == "and") { - style = "operator"; - } else if (/^(only|not)$/.test(word)) { - style = "error"; // Only allowed in @media - } else { - style += " error"; - } - } else if (context == "@import") { - style = "tag"; - } else { - style = "error"; - } - } else if (style == "atom") { - if(!context || context == "@media{" || context == "block") { - style = "builtin"; - } else if (context == "propertyValue") { - if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { - style += " error"; - } - } else { - style = "error"; - } - } else if (context == "@media" && type == "{") { - style = "error"; - } + function pass(type, stream, state) { + return states[state.context.type](type, stream, state); + } + function popAndPass(type, stream, state, n) { + for (var i = n || 1; i > 0; i--) + state.context = state.context.prev; + return pass(type, stream, state); + } - // Push/pop context stack - if (type == "{") { - if (context == "@media" || context == "@mediaType") { - state.stack[state.stack.length-1] = "@media{"; - } - else { - var newContext = allowNested ? "block" : "rule"; - state.stack.push(newContext); - } + // Parser + + function wordAsValue(stream) { + var word = stream.current().toLowerCase(); + if (valueKeywords.hasOwnProperty(word)) + override = "atom"; + else if (colorKeywords.hasOwnProperty(word)) + override = "keyword"; + else + override = "variable"; + } + + var states = {}; + + states.top = function(type, stream, state) { + if (type == "{") { + return pushContext(state, stream, "block"); + } else if (type == "}" && state.context.prev) { + return popContext(state); + } else if (type == "@media") { + return pushContext(state, stream, "media"); + } else if (type == "@font-face") { + return "font_face_before"; + } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) { + return "keyframes"; + } else if (type && type.charAt(0) == "@") { + return pushContext(state, stream, "at"); + } else if (type == "hash") { + override = "builtin"; + } else if (type == "word") { + override = "tag"; + } else if (type == "variable-definition") { + return "maybeprop"; + } else if (type == "interpolation") { + return pushContext(state, stream, "interpolation"); + } else if (type == ":") { + return "pseudo"; + } else if (allowNested && type == "(") { + return pushContext(state, stream, "params"); + } + return state.context.type; + }; + + states.block = function(type, stream, state) { + if (type == "word") { + if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) { + override = "property"; + return "maybeprop"; + } else if (allowNested) { + override = stream.match(/^\s*:/, false) ? "property" : "tag"; + return "block"; + } else { + override += " error"; + return "maybeprop"; } - else if (type == "}") { - if (context == "interpolation") style = "operator"; - state.stack.pop(); - if (context == "propertyValue") state.stack.pop(); - } - else if (type == "interpolation") state.stack.push("interpolation"); - else if (type == "@media") state.stack.push("@media"); - else if (type == "@import") state.stack.push("@import"); - else if (context == "@media" && /\b(keyword|attribute)\b/.test(style)) - state.stack[state.stack.length-1] = "@mediaType"; - else if (context == "@mediaType" && stream.current() == ",") - state.stack[state.stack.length-1] = "@media"; - else if (type == "(") { - if (context == "@media" || context == "@mediaType") { - // Make sure @mediaType is used to avoid error on { - state.stack[state.stack.length-1] = "@mediaType"; - state.stack.push("@mediaType("); - } - } - else if (type == ")") { - if (context == "propertyValue" && state.stack[state.stack.length-2] == "@mediaType(") { - // In @mediaType( without closing ; after propertyValue - state.stack.pop(); - state.stack.pop(); - } - else if (context == "@mediaType(") { - state.stack.pop(); - } - } - else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue"); - else if (context == "propertyValue" && type == ";") state.stack.pop(); - else if (context == "@import" && type == ";") state.stack.pop(); + } else if (type == "meta") { + return "block"; + } else if (!allowNested && (type == "hash" || type == "qualifier")) { + override = "error"; + return "block"; + } else { + return states.top(type, stream, state); + } + }; - return state.lastToken = style; + states.maybeprop = function(type, stream, state) { + if (type == ":") return pushContext(state, stream, "prop"); + return pass(type, stream, state); + }; + + states.prop = function(type, stream, state) { + if (type == ";") return popContext(state); + if (type == "{" && allowNested) return pushContext(state, stream, "propBlock"); + if (type == "}" || type == "{") return popAndPass(type, stream, state); + if (type == "(") return pushContext(state, stream, "parens"); + + if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { + override += " error"; + } else if (type == "word") { + wordAsValue(stream); + } else if (type == "interpolation") { + return pushContext(state, stream, "interpolation"); + } + return "prop"; + }; + + states.propBlock = function(type, _stream, state) { + if (type == "}") return popContext(state); + if (type == "word") { override = "property"; return "maybeprop"; } + return state.context.type; + }; + + states.parens = function(type, stream, state) { + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == ")") return popContext(state); + return "parens"; + }; + + states.pseudo = function(type, stream, state) { + if (type == "word") { + override = "variable-3"; + return state.context.type; + } + return pass(type, stream, state); + }; + + states.media = function(type, stream, state) { + if (type == "(") return pushContext(state, stream, "media_parens"); + if (type == "}") return popAndPass(type, stream, state); + if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top"); + + if (type == "word") { + var word = stream.current().toLowerCase(); + if (word == "only" || word == "not" || word == "and") + override = "keyword"; + else if (mediaTypes.hasOwnProperty(word)) + override = "attribute"; + else if (mediaFeatures.hasOwnProperty(word)) + override = "property"; + else + override = "error"; + } + return state.context.type; + }; + + states.media_parens = function(type, stream, state) { + if (type == ")") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); + return states.media(type, stream, state); + }; + + states.font_face_before = function(type, stream, state) { + if (type == "{") + return pushContext(state, stream, "font_face"); + return pass(type, stream, state); + }; + + states.font_face = function(type, stream, state) { + if (type == "}") return popContext(state); + if (type == "word") { + if (!fontProperties.hasOwnProperty(stream.current().toLowerCase())) + override = "error"; + else + override = "property"; + return "maybeprop"; + } + return "font_face"; + }; + + states.keyframes = function(type, stream, state) { + if (type == "word") { override = "variable"; return "keyframes"; } + if (type == "{") return pushContext(state, stream, "top"); + return pass(type, stream, state); + }; + + states.at = function(type, stream, state) { + if (type == ";") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == "word") override = "tag"; + else if (type == "hash") override = "builtin"; + return "at"; + }; + + states.interpolation = function(type, stream, state) { + if (type == "}") return popContext(state); + if (type == "{" || type == ";") return popAndPass(type, stream, state); + if (type != "variable") override = "error"; + return "interpolation"; + }; + + states.params = function(type, stream, state) { + if (type == ")") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == "word") wordAsValue(stream); + return "params"; + }; + + return { + startState: function(base) { + return {tokenize: null, + state: "top", + context: new Context("top", base || 0, null)}; }, + token: function(stream, state) { + if (!state.tokenize && stream.eatSpace()) return null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style && typeof style == "object") { + type = style[1]; + style = style[0]; + } + override = style; + state.state = states[state.state](type, stream, state); + return override; + }, + indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[n-1] == "propertyValue" ? 2 : 1; - return state.baseIndent + n * indentUnit; + var cx = state.context, ch = textAfter && textAfter.charAt(0); + var indent = cx.indent; + if (cx.type == "prop" && ch == "}") cx = cx.prev; + if (cx.prev && + (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") || + ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") || + ch == "{" && (cx.type == "at" || cx.type == "media"))) { + indent = cx.indent - indentUnit; + cx = cx.prev; + } + return indent; }, electricChars: "}", blockCommentStart: "/*", blockCommentEnd: "*/", @@ -36576,33 +36865,33 @@ keys[array[i]] = true; } return keys; } - var atMediaTypes = keySet([ + var mediaTypes_ = [ "all", "aural", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "embossed" - ]); + ], mediaTypes = keySet(mediaTypes_); - var atMediaFeatures = keySet([ + var mediaFeatures_ = [ "width", "min-width", "max-width", "height", "min-height", "max-height", "device-width", "min-device-width", "max-device-width", "device-height", "min-device-height", "max-device-height", "aspect-ratio", "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", "max-color", "color-index", "min-color-index", "max-color-index", "monochrome", "min-monochrome", "max-monochrome", "resolution", "min-resolution", "max-resolution", "scan", "grid" - ]); + ], mediaFeatures = keySet(mediaFeatures_); - var propertyKeywords = keySet([ + var propertyKeywords_ = [ "align-content", "align-items", "align-self", "alignment-adjust", "alignment-baseline", "anchor-point", "animation", "animation-delay", - "animation-direction", "animation-duration", "animation-iteration-count", - "animation-name", "animation-play-state", "animation-timing-function", - "appearance", "azimuth", "backface-visibility", "background", - "background-attachment", "background-clip", "background-color", + "animation-direction", "animation-duration", "animation-fill-mode", + "animation-iteration-count", "animation-name", "animation-play-state", + "animation-timing-function", "appearance", "azimuth", "backface-visibility", + "background", "background-attachment", "background-clip", "background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "baseline-shift", "binding", "bleed", "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target", "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius", "border-bottom-right-radius", @@ -36629,14 +36918,15 @@ "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-synthesis", "font-variant", "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position", - "font-weight", "grid-cell", "grid-column", "grid-column-align", - "grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow", - "grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span", - "grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens", + "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", + "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end", + "grid-column-start", "grid-row", "grid-row-end", "grid-row-start", + "grid-template", "grid-template-areas", "grid-template-columns", + "grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon", "image-orientation", "image-rendering", "image-resolution", "inline-box-align", "justify-content", "left", "letter-spacing", "line-break", "line-height", "line-stacking", "line-stacking-ruby", "line-stacking-shift", "line-stacking-strategy", "list-style", "list-style-image", "list-style-position", "list-style-type", "margin", @@ -36680,13 +36970,13 @@ "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", "glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode" - ]); + ], propertyKeywords = keySet(propertyKeywords_); - var colorKeywords = keySet([ + var colorKeywords_ = [ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", @@ -36709,13 +36999,13 @@ "purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen" - ]); + ], colorKeywords = keySet(colorKeywords_); - var valueKeywords = keySet([ + var valueKeywords_ = [ "above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", "arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page", "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary", @@ -36794,12 +37084,20 @@ "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", "window", "windowframe", "windowtext", "x-large", "x-small", "xor", "xx-large", "xx-small" - ]); + ], valueKeywords = keySet(valueKeywords_); + var fontProperties_ = [ + "font-family", "src", "unicode-range", "font-variant", "font-feature-settings", + "font-stretch", "font-weight", "font-style" + ], fontProperties = keySet(fontProperties_); + + var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_); + CodeMirror.registerHelper("hintWords", "css", allWords); + function tokenCComment(stream, state) { var maybeEnd = false, ch; while ((ch = stream.next()) != null) { if (maybeEnd && ch == "/") { state.tokenize = null; @@ -36808,60 +37106,51 @@ maybeEnd = (ch == "*"); } return ["comment", "comment"]; } + function tokenSGMLComment(stream, state) { + if (stream.skipTo("-->")) { + stream.match("-->"); + state.tokenize = null; + } else { + stream.skipToEnd(); + } + return ["comment", "comment"]; + } + CodeMirror.defineMIME("text/css", { - atMediaTypes: atMediaTypes, - atMediaFeatures: atMediaFeatures, + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, - hooks: { + fontProperties: fontProperties, + tokenHooks: { "<": function(stream, state) { - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = null; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ["comment", "comment"]; - } - if (stream.eat("!")) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } + if (!stream.match("!--")) return false; + state.tokenize = tokenSGMLComment; + return tokenSGMLComment(stream, state); }, "/": function(stream, state) { - if (stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - return false; + if (!stream.eat("*")) return false; + state.tokenize = tokenCComment; + return tokenCComment(stream, state); } }, - name: "css-base" + name: "css" }); CodeMirror.defineMIME("text/x-scss", { - atMediaTypes: atMediaTypes, - atMediaFeatures: atMediaFeatures, + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, + fontProperties: fontProperties, allowNested: true, - hooks: { - "$": function(stream) { - stream.match(/^[\w-]+/); - if (stream.peek() == ":") { - return ["variable", "variable-definition"]; - } - return ["variable", "variable"]; - }, + tokenHooks: { "/": function(stream, state) { if (stream.eat("/")) { stream.skipToEnd(); return ["comment", "comment"]; } else if (stream.eat("*")) { @@ -36869,28 +37158,72 @@ return tokenCComment(stream, state); } else { return ["operator", "operator"]; } }, + ":": function(stream) { + if (stream.match(/\s*{/)) + return [null, "{"]; + return false; + }, + "$": function(stream) { + stream.match(/^[\w-]+/); + if (stream.match(/^\s*:/, false)) + return ["variable-2", "variable-definition"]; + return ["variable-2", "variable"]; + }, "#": function(stream) { - if (stream.eat("{")) { - return ["operator", "interpolation"]; + if (!stream.eat("{")) return false; + return [null, "interpolation"]; + } + }, + name: "css", + helperType: "scss" + }); + + CodeMirror.defineMIME("text/x-less", { + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, + propertyKeywords: propertyKeywords, + colorKeywords: colorKeywords, + valueKeywords: valueKeywords, + fontProperties: fontProperties, + allowNested: true, + tokenHooks: { + "/": function(stream, state) { + if (stream.eat("/")) { + stream.skipToEnd(); + return ["comment", "comment"]; + } else if (stream.eat("*")) { + state.tokenize = tokenCComment; + return tokenCComment(stream, state); } else { - stream.eatWhile(/[\w\\\-]/); - return ["atom", "hash"]; + return ["operator", "operator"]; } + }, + "@": function(stream) { + if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false; + stream.eatWhile(/[\w\\\-]/); + if (stream.match(/^\s*:/, false)) + return ["variable-2", "variable-definition"]; + return ["variable-2", "variable"]; + }, + "&": function() { + return ["atom", "atom"]; } }, - name: "css-base" + name: "css", + helperType: "less" }); })(); // TODO actually recognize syntax of TypeScript constructs CodeMirror.defineMode("javascript", function(config, parserConfig) { var indentUnit = config.indentUnit; var statementIndent = parserConfig.statementIndent; - var jsonMode = parserConfig.json; + var jsonldMode = parserConfig.jsonld; + var jsonMode = parserConfig.json || jsonldMode; var isTS = parserConfig.typescript; // Tokenizer var keywords = function(){ @@ -36898,37 +37231,35 @@ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); var operator = kw("operator"), atom = {type: "atom", style: "atom"}; var jsKeywords = { "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, + "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this") + "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), + "yield": C, "export": kw("export"), "import": kw("import"), "extends": C }; // Extend the 'normal' keywords with the TypeScript language extensions if (isTS) { var type = {type: "variable", style: "variable-3"}; var tsKeywords = { // object-like things "interface": kw("interface"), - "class": kw("class"), "extends": kw("extends"), "constructor": kw("constructor"), // scope modifiers "public": kw("public"), "private": kw("private"), "protected": kw("protected"), "static": kw("static"), - "super": kw("super"), - // types "string": type, "number": type, "bool": type, "any": type }; for (var attr in tsKeywords) { @@ -36938,107 +37269,158 @@ return jsKeywords; }(); var isOperatorChar = /[+\-*&%=<>!?|~^]/; + var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, next; + function readRegexp(stream) { + var escaped = false, next, inSet = false; while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; + if (!escaped) { + if (next == "/" && !inSet) return; + if (next == "[") inSet = true; + else if (inSet && next == "]") inSet = false; + } escaped = !escaped && next == "\\"; } - return escaped; } // Used as scratch variables to communicate multiple values without // consing up tons of objects. var type, content; function ret(tp, style, cont) { type = tp; content = cont; return style; } - function jsTokenBase(stream, state) { + function tokenBase(stream, state) { var ch = stream.next(); - if (ch == '"' || ch == "'") - return chain(stream, state, jsTokenString(ch)); - else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { return ret("number", "number"); - else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + } else if (ch == "." && stream.match("..")) { + return ret("spread", "meta"); + } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { return ret(ch); - else if (ch == "0" && stream.eat(/x/i)) { + } else if (ch == "=" && stream.eat(">")) { + return ret("=>", "operator"); + } else if (ch == "0" && stream.eat(/x/i)) { stream.eatWhile(/[\da-f]/i); return ret("number", "number"); - } - else if (/\d/.test(ch)) { + } else if (/\d/.test(ch)) { stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); return ret("number", "number"); - } - else if (ch == "/") { + } else if (ch == "/") { if (stream.eat("*")) { - return chain(stream, state, jsTokenComment); - } - else if (stream.eat("/")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); - } - else if (state.lastType == "operator" || state.lastType == "keyword c" || - /^[\[{}\(,;:]$/.test(state.lastType)) { - nextUntilUnescaped(stream, "/"); + } else if (state.lastType == "operator" || state.lastType == "keyword c" || + state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { + readRegexp(stream); stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla return ret("regexp", "string-2"); - } - else { + } else { stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); + return ret("operator", "operator", stream.current()); } - } - else if (ch == "#") { + } else if (ch == "`") { + state.tokenize = tokenQuasi; + return tokenQuasi(stream, state); + } else if (ch == "#") { stream.skipToEnd(); return ret("error", "error"); - } - else if (isOperatorChar.test(ch)) { + } else if (isOperatorChar.test(ch)) { stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - else { + return ret("operator", "operator", stream.current()); + } else { stream.eatWhile(/[\w\$_]/); var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; return (known && state.lastType != ".") ? ret(known.type, known.style, word) : ret("variable", "variable", word); } } - function jsTokenString(quote) { + function tokenString(quote) { return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = jsTokenBase; + var escaped = false, next; + if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ + state.tokenize = tokenBase; + return ret("jsonld-keyword", "meta"); + } + while ((next = stream.next()) != null) { + if (next == quote && !escaped) break; + escaped = !escaped && next == "\\"; + } + if (!escaped) state.tokenize = tokenBase; return ret("string", "string"); }; } - function jsTokenComment(stream, state) { + function tokenComment(stream, state) { var maybeEnd = false, ch; while (ch = stream.next()) { if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; + state.tokenize = tokenBase; break; } maybeEnd = (ch == "*"); } return ret("comment", "comment"); } + function tokenQuasi(stream, state) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && next == "\\"; + } + return ret("quasi", "string-2", stream.current()); + } + + var brackets = "([{}])"; + // This is a crude lookahead trick to try and notice that we're + // parsing the argument patterns for a fat-arrow function before we + // actually hit the arrow token. It only works if the arrow is on + // the same line as the arguments and there's no strange noise + // (comments) in between. Fallback is to only notice when we hit the + // arrow, and not declare the arguments as locals for the arrow + // body. + function findFatArrow(stream, state) { + if (state.fatArrowAt) state.fatArrowAt = null; + var arrow = stream.string.indexOf("=>", stream.start); + if (arrow < 0) return; + + var depth = 0, sawSomething = false; + for (var pos = arrow - 1; pos >= 0; --pos) { + var ch = stream.string.charAt(pos); + var bracket = brackets.indexOf(ch); + if (bracket >= 0 && bracket < 3) { + if (!depth) { ++pos; break; } + if (--depth == 0) break; + } else if (bracket >= 3 && bracket < 6) { + ++depth; + } else if (/[$\w]/.test(ch)) { + sawSomething = true; + } else if (sawSomething && !depth) { + ++pos; + break; + } + } + if (sawSomething && !depth) state.fatArrowAt = pos; + } + // Parser - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true}; + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; function JSLexical(indented, column, type, align, prev, info) { this.indented = indented; this.column = column; this.type = type; @@ -37048,10 +37430,14 @@ } function inScope(state, varname) { for (var v = state.localVars; v; v = v.next) if (v.name == varname) return true; + for (var cx = state.context; cx; cx = cx.prev) { + for (var v = cx.vars; v; v = v.next) + if (v.name == varname) return true; + } } function parseJS(state, style, type, content, stream) { var cc = state.cc; // Communicate our context to the combinators. @@ -37094,11 +37480,12 @@ cx.marked = "def"; if (inList(state.localVars)) return; state.localVars = {name: varname, next: state.localVars}; } else { if (inList(state.globalVars)) return; - state.globalVars = {name: varname, next: state.globalVars}; + if (parserConfig.globalVars) + state.globalVars = {name: varname, next: state.globalVars}; } } // Combinators @@ -37136,44 +37523,53 @@ else if (wanted == ";") return pass(); else return cont(arguments.callee); }; } - function statement(type) { - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); + function statement(type, value) { + if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); if (type == "keyword b") return cont(pushlex("form"), statement, poplex); if (type == "{") return cont(pushlex("}"), block, poplex); if (type == ";") return cont(); if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse); if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), - poplex, statement, poplex); + if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); if (type == "variable") return cont(pushlex("stat"), maybelabel); if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); if (type == "case") return cont(expression, expect(":")); if (type == "default") return cont(expect(":")); if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext); + if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex); + if (type == "class") return cont(pushlex("form"), className, objlit, poplex); + if (type == "export") return cont(pushlex("form"), afterExport, poplex); + if (type == "import") return cont(pushlex("form"), afterImport, poplex); return pass(pushlex("stat"), expression, expect(";"), poplex); } function expression(type) { return expressionInner(type, false); } function expressionNoComma(type) { return expressionInner(type, true); } function expressionInner(type, noComma) { + if (cx.state.fatArrowAt == cx.stream.start) { + var body = noComma ? arrowBodyNoComma : arrowBody; + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); + else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); + } + var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef); if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); - if (type == "operator") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), commasep(expressionNoComma, "]"), poplex, maybeop); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeop); + if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); + if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); + if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); + if (type == "{") return contCommasep(objprop, "}", null, maybeop); return cont(); } function maybeexpression(type) { if (type.match(/[;\}\)\],]/)) return pass(); return pass(expression); @@ -37188,20 +37584,43 @@ return maybeoperatorNoComma(type, value, false); } function maybeoperatorNoComma(type, value, noComma) { var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; var expr = noComma == false ? expression : expressionNoComma; + if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); if (type == "operator") { if (/\+\+|--/.test(value)) return cont(me); if (value == "?") return cont(expression, expect(":"), expr); return cont(expr); } + if (type == "quasi") { cx.cc.push(me); return quasi(value); } if (type == ";") return; - if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me); + if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } + function quasi(value) { + if (value.slice(value.length - 2) != "${") return cont(); + return cont(expression, continueQuasi); + } + function continueQuasi(type) { + if (type == "}") { + cx.marked = "string-2"; + cx.state.tokenize = tokenQuasi; + return cont(); + } + } + function arrowBody(type) { + findFatArrow(cx.stream, cx.state); + if (type == "{") return pass(statement); + return pass(expression); + } + function arrowBodyNoComma(type) { + findFatArrow(cx.stream, cx.state); + if (type == "{") return pass(statement); + return pass(expressionNoComma); + } function maybelabel(type) { if (type == ":") return cont(poplex, statement); return pass(maybeoperatorComma, expect(";"), poplex); } function property(type) { @@ -37210,20 +37629,25 @@ function objprop(type, value) { if (type == "variable") { cx.marked = "property"; if (value == "get" || value == "set") return cont(getterSetter); } else if (type == "number" || type == "string") { - cx.marked = type + " property"; + cx.marked = jsonldMode ? "property" : (type + " property"); + } else if (type == "[") { + return cont(expression, expect("]"), afterprop); } - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma); + if (atomicTypes.hasOwnProperty(type)) return cont(afterprop); } function getterSetter(type) { - if (type == ":") return cont(expression); - if (type != "variable") return cont(expect(":"), expression); + if (type != "variable") return pass(afterprop); cx.marked = "property"; return cont(functiondef); } + function afterprop(type) { + if (type == ":") return cont(expressionNoComma); + if (type == "(") return pass(functiondef); + } function commasep(what, end) { function proceed(type) { if (type == ",") { var lex = cx.state.lexical; if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; @@ -37232,110 +37656,174 @@ if (type == end) return cont(); return cont(expect(end)); } return function(type) { if (type == end) return cont(); - else return pass(what, proceed); + return pass(what, proceed); }; } + function contCommasep(what, end, info) { + for (var i = 3; i < arguments.length; i++) + cx.cc.push(arguments[i]); + return cont(pushlex(end, info), commasep(what, end), poplex); + } function block(type) { if (type == "}") return cont(); return pass(statement, block); } function maybetype(type) { - if (type == ":") return cont(typedef); - return pass(); + if (isTS && type == ":") return cont(typedef); } function typedef(type) { if (type == "variable"){cx.marked = "variable-3"; return cont();} - return pass(); } - function vardef1(type, value) { - if (type == "variable") { + function vardef() { + return pass(pattern, maybetype, maybeAssign, vardefCont); + } + function pattern(type, value) { + if (type == "variable") { register(value); return cont(); } + if (type == "[") return contCommasep(pattern, "]"); + if (type == "{") return contCommasep(proppattern, "}"); + } + function proppattern(type, value) { + if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { register(value); - return isTS ? cont(maybetype, vardef2) : cont(vardef2); + return cont(maybeAssign); } - return pass(); + if (type == "variable") cx.marked = "property"; + return cont(expect(":"), pattern, maybeAssign); } - function vardef2(type, value) { - if (value == "=") return cont(expressionNoComma, vardef2); - if (type == ",") return cont(vardef1); + function maybeAssign(_type, value) { + if (value == "=") return cont(expressionNoComma); } + function vardefCont(type) { + if (type == ",") return cont(vardef); + } function maybeelse(type, value) { if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); } + function forspec(type) { + if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); + } function forspec1(type) { - if (type == "var") return cont(vardef1, expect(";"), forspec2); + if (type == "var") return cont(vardef, expect(";"), forspec2); if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybein); + if (type == "variable") return cont(formaybeinof); return pass(expression, expect(";"), forspec2); } - function formaybein(_type, value) { - if (value == "in") return cont(expression); + function formaybeinof(_type, value) { + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } return cont(maybeoperatorComma, forspec2); } function forspec2(type, value) { if (type == ";") return cont(forspec3); - if (value == "in") return cont(expression); + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } return pass(expression, expect(";"), forspec3); } function forspec3(type) { if (type != ")") cont(expression); } function functiondef(type, value) { + if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); } - function funarg(type, value) { - if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();} + function funarg(type) { + if (type == "spread") return cont(funarg); + return pass(pattern, maybetype); } + function className(type, value) { + if (type == "variable") {register(value); return cont(classNameAfter);} + } + function classNameAfter(_type, value) { + if (value == "extends") return cont(expression); + } + function objlit(type) { + if (type == "{") return contCommasep(objprop, "}"); + } + function afterModule(type, value) { + if (type == "string") return cont(statement); + if (type == "variable") { register(value); return cont(maybeFrom); } + } + function afterExport(_type, value) { + if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } + if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } + return pass(statement); + } + function afterImport(type) { + if (type == "string") return cont(); + return pass(importSpec, maybeFrom); + } + function importSpec(type, value) { + if (type == "{") return contCommasep(importSpec, "}"); + if (type == "variable") register(value); + return cont(); + } + function maybeFrom(_type, value) { + if (value == "from") { cx.marked = "keyword"; return cont(expression); } + } + function arrayLiteral(type) { + if (type == "]") return cont(); + return pass(expressionNoComma, maybeArrayComprehension); + } + function maybeArrayComprehension(type) { + if (type == "for") return pass(comprehension, expect("]")); + if (type == ",") return cont(commasep(expressionNoComma, "]")); + return pass(commasep(expressionNoComma, "]")); + } + function comprehension(type) { + if (type == "for") return cont(forspec, comprehension); + if (type == "if") return cont(expression, comprehension); + } // Interface return { startState: function(basecolumn) { - return { - tokenize: jsTokenBase, - lastType: null, + var state = { + tokenize: tokenBase, + lastType: "sof", cc: [], lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), localVars: parserConfig.localVars, - globalVars: parserConfig.globalVars, context: parserConfig.localVars && {vars: parserConfig.localVars}, indented: 0 }; + if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars; + return state; }, token: function(stream, state) { if (stream.sol()) { if (!state.lexical.hasOwnProperty("align")) state.lexical.align = false; state.indented = stream.indentation(); + findFatArrow(stream, state); } - if (state.tokenize != jsTokenComment && stream.eatSpace()) return null; + if (state.tokenize != tokenComment && stream.eatSpace()) return null; var style = state.tokenize(stream, state); if (type == "comment") return style; state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; return parseJS(state, style, type, content, stream); }, indent: function(state, textAfter) { - if (state.tokenize == jsTokenComment) return CodeMirror.Pass; - if (state.tokenize != jsTokenBase) return 0; + if (state.tokenize == tokenComment) return CodeMirror.Pass; + if (state.tokenize != tokenBase) return 0; var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; // Kludge to prevent 'maybelse' from blocking lexical scope pops for (var i = state.cc.length - 1; i >= 0; --i) { var c = state.cc[i]; if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse || /^else\b/.test(textAfter)) break; + else if (c != maybeelse) break; } if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") lexical = lexical.prev; var type = lexical.type, closing = firstChar == type; - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0); + if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); else if (type == "form" && firstChar == "{") return lexical.indented; else if (type == "form") return lexical.indented + indentUnit; else if (type == "stat") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0); else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) @@ -37349,26 +37837,29 @@ blockCommentEnd: jsonMode ? null : "*/", lineComment: jsonMode ? null : "//", fold: "brace", helperType: jsonMode ? "json" : "javascript", + jsonldMode: jsonldMode, jsonMode: jsonMode }; }); CodeMirror.defineMIME("text/javascript", "javascript"); CodeMirror.defineMIME("text/ecmascript", "javascript"); CodeMirror.defineMIME("application/javascript", "javascript"); CodeMirror.defineMIME("application/ecmascript", "javascript"); CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); +CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); CodeMirror.defineMode("xml", function(config, parserConfig) { var indentUnit = config.indentUnit; var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; - var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag || true; + var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; + if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; var Kludges = parserConfig.htmlMode ? { autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, @@ -37408,11 +37899,11 @@ allowMissing: false }; var alignCDATA = parserConfig.alignCDATA; // Return variables for tokenizers - var tagName, type; + var tagName, type, setStyle; function inText(stream, state) { function chain(parser) { state.tokenize = parser; return parser(stream, state); @@ -37439,11 +37930,11 @@ } else { var isClose = stream.eat("/"); tagName = ""; var c; while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; - if (!tagName) return "error"; + if (!tagName) return "tag error"; type = isClose ? "closeTag" : "openTag"; state.tokenize = inTag; return "tag"; } } else if (ch == "&") { @@ -37472,11 +37963,15 @@ return "tag"; } else if (ch == "=") { type = "equals"; return null; } else if (ch == "<") { - return "error"; + state.tokenize = inText; + state.state = baseState; + state.tagName = state.tagStart = null; + var next = state.tokenize(stream, state); + return next ? next + " error" : "error"; } else if (/[\'\"]/.test(ch)) { state.tokenize = inAttribute(ch); state.stringStartCol = stream.column(); return state.tokenize(stream, state); } else { @@ -37530,152 +38025,139 @@ } return "meta"; }; } - var curState, curStream, setStyle; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); + function Context(state, tagName, startOfLine) { + this.prev = state.context; + this.tagName = tagName; + this.indent = state.indented; + this.startOfLine = startOfLine; + if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) + this.noIndent = true; } - function cont() { - pass.apply(null, arguments); - return true; + function popContext(state) { + if (state.context) state.context = state.context.prev; } - - function pushContext(tagName, startOfLine) { - var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); - curState.context = { - prev: curState.context, - tagName: tagName, - indent: curState.indented, - startOfLine: startOfLine, - noIndent: noIndent - }; + function maybePopContext(state, nextTagName) { + var parentTagName; + while (true) { + if (!state.context) { + return; + } + parentTagName = state.context.tagName.toLowerCase(); + if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || + !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + return; + } + popContext(state); + } } - function popContext() { - if (curState.context) curState.context = curState.context.prev; - } - function element(type) { + function baseState(type, stream, state) { if (type == "openTag") { - curState.tagName = tagName; - curState.tagStart = curStream.column(); - return cont(attributes, endtag(curState.startOfLine)); + state.tagName = tagName; + state.tagStart = stream.column(); + return attrState; } else if (type == "closeTag") { var err = false; - if (curState.context) { - if (curState.context.tagName != tagName) { - if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) { - popContext(); - } - err = !curState.context || curState.context.tagName != tagName; + if (state.context) { + if (state.context.tagName != tagName) { + if (Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName.toLowerCase())) + popContext(state); + err = !state.context || state.context.tagName != tagName; } } else { err = true; } if (err) setStyle = "error"; - return cont(endclosetag(err)); + return err ? closeStateErr : closeState; + } else { + return baseState; } - return cont(); } - function endtag(startOfLine) { - return function(type) { - var tagName = curState.tagName; - curState.tagName = curState.tagStart = null; - if (type == "selfcloseTag" || - (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) { - maybePopContext(tagName.toLowerCase()); - return cont(); - } - if (type == "endTag") { - maybePopContext(tagName.toLowerCase()); - pushContext(tagName, startOfLine); - return cont(); - } - return cont(); - }; - } - function endclosetag(err) { - return function(type) { - if (err) setStyle = "error"; - if (type == "endTag") { popContext(); return cont(); } + function closeState(type, _stream, state) { + if (type != "endTag") { setStyle = "error"; - return cont(arguments.callee); - }; - } - function maybePopContext(nextTagName) { - var parentTagName; - while (true) { - if (!curState.context) { - return; - } - parentTagName = curState.context.tagName.toLowerCase(); - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || - !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { - return; - } - popContext(); + return closeState; } + popContext(state); + return baseState; } + function closeStateErr(type, stream, state) { + setStyle = "error"; + return closeState(type, stream, state); + } - function attributes(type) { - if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);} - if (type == "endTag" || type == "selfcloseTag") return pass(); + function attrState(type, _stream, state) { + if (type == "word") { + setStyle = "attribute"; + return attrEqState; + } else if (type == "endTag" || type == "selfcloseTag") { + var tagName = state.tagName, tagStart = state.tagStart; + state.tagName = state.tagStart = null; + if (type == "selfcloseTag" || + Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase())) { + maybePopContext(state, tagName.toLowerCase()); + } else { + maybePopContext(state, tagName.toLowerCase()); + state.context = new Context(state, tagName, tagStart == state.indented); + } + return baseState; + } setStyle = "error"; - return cont(attributes); + return attrState; } - function attribute(type) { - if (type == "equals") return cont(attvalue, attributes); + function attrEqState(type, stream, state) { + if (type == "equals") return attrValueState; if (!Kludges.allowMissing) setStyle = "error"; - else if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);} - return (type == "endTag" || type == "selfcloseTag") ? pass() : cont(); + return attrState(type, stream, state); } - function attvalue(type) { - if (type == "string") return cont(attvaluemaybe); - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();} + function attrValueState(type, stream, state) { + if (type == "string") return attrContinuedState; + if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} setStyle = "error"; - return (type == "endTag" || type == "selfCloseTag") ? pass() : cont(); + return attrState(type, stream, state); } - function attvaluemaybe(type) { - if (type == "string") return cont(attvaluemaybe); - else return pass(); + function attrContinuedState(type, stream, state) { + if (type == "string") return attrContinuedState; + return attrState(type, stream, state); } return { startState: function() { - return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, tagStart: null, context: null}; + return {tokenize: inText, + state: baseState, + indented: 0, + tagName: null, tagStart: null, + context: null}; }, token: function(stream, state) { - if (!state.tagName && stream.sol()) { - state.startOfLine = true; + if (!state.tagName && stream.sol()) state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - setStyle = type = tagName = null; + if (stream.eatSpace()) return null; + tagName = type = null; var style = state.tokenize(stream, state); - state.type = type; if ((style || type) && style != "comment") { - curState = state; curStream = stream; - while (true) { - var comb = state.cc.pop() || element; - if (comb(type || style)) break; - } + setStyle = null; + state.state = state.state(type || style, stream, state); + if (setStyle) + style = setStyle == "error" ? style + " error" : setStyle; } - state.startOfLine = false; - return setStyle || style; + return style; }, indent: function(state, textAfter, fullLine) { var context = state.context; // Indent multi-line strings (e.g. css). if (state.tokenize.isInAttribute) { return state.stringStartCol + 1; } - if ((state.tokenize != inTag && state.tokenize != inText) || - context && context.noIndent) + if (context && context.noIndent) return CodeMirror.Pass; + if (state.tokenize != inTag && state.tokenize != inText) return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; // Indent the starts of attribute names. if (state.tagName) { if (multilineTagIndentPastTag) return state.tagStart + state.tagName.length + 2; @@ -37703,11 +38185,14 @@ CodeMirror.defineMIME("text/xml", "xml"); CodeMirror.defineMIME("application/xml", "xml"); if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true}); + var htmlMode = CodeMirror.getMode(config, {name: "xml", + htmlMode: true, + multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, + multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag}); var cssMode = CodeMirror.getMode(config, "css"); var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes; scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, mode: CodeMirror.getMode(config, "javascript")}); @@ -37748,11 +38233,11 @@ var cur = stream.current(); var close = cur.search(pat), m; if (close > -1) stream.backUp(cur.length - close); else if (m = cur.match(/<\/?$/)) { stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur[0]); + if (!stream.match(pat, false)) stream.match(cur); } return style; } function script(stream, state) { if (stream.match(/^<\/\s*script\s*>/i, false)) { @@ -37797,12 +38282,10 @@ return state.localMode.indent(state.localState, textAfter); else return CodeMirror.Pass; }, - electricChars: "/{}:", - innerMode: function(state) { return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; } }; }, "xml", "javascript", "css"); @@ -38509,13 +38992,26 @@ // Default JSON-request options. var params = _.extend({ type: type, dataType: 'json', - beforeSend: function( xhr ) { + beforeSend: function(xhr, settings) { var token = $('meta[name="csrf-token"]').prop('content'); if (token) xhr.setRequestHeader('X-CSRF-Token', token); + }, + xhr: function() { + var xhr = new window.XMLHttpRequest(); + + xhr.upload.addEventListener('progress', function(evt){ + if (evt.lengthComputable) { + if (options.progress) { + options.progress(event.loaded, event.total) + } + } + }, false); + + return xhr; } }, options); if (!params.url) { params.url = getUrl(model) || urlError(); @@ -43898,11 +44394,11 @@ return buf; } String.prototype.truncate = function(length) { if (this.length > length) { - return this.slice(0, length - 3) + "..."; + return this.slice(0, length - 3) + '...'; } else { return this; } } @@ -44086,20 +44582,18 @@ })(Locomotive.Models.Account); }).call(this); (function() { - var _ref, _ref1, - __hasProp = {}.hasOwnProperty, + var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Locomotive.Models.ContentAsset = (function(_super) { __extends(ContentAsset, _super); function ContentAsset() { - _ref = ContentAsset.__super__.constructor.apply(this, arguments); - return _ref; + return ContentAsset.__super__.constructor.apply(this, arguments); } ContentAsset.prototype.paramRoot = 'content_asset'; ContentAsset.prototype.urlRoot = "" + Locomotive.mounted_on + "/content_assets"; @@ -44107,26 +44601,37 @@ ContentAsset.prototype.initialize = function() { return this.prepare(); }; ContentAsset.prototype.prepare = function() { + if (this.get('uploading')) { + this.set({ + filename: this.get('source').name.truncate(15) + }); + } this.set({ - image: this.get('content_type') === 'image' + image: this.get('content_type') === 'image', + with_thumbnail: this.get('content_type') === 'image' || this.get('content_type') === 'pdf' }); return this; }; + ContentAsset.prototype.toJSONForSave = function() { + return { + source: this.get('source') + }; + }; + return ContentAsset; })(Backbone.Model); Locomotive.Models.ContentAssetsCollection = (function(_super) { __extends(ContentAssetsCollection, _super); function ContentAssetsCollection() { - _ref1 = ContentAssetsCollection.__super__.constructor.apply(this, arguments); - return _ref1; + return ContentAssetsCollection.__super__.constructor.apply(this, arguments); } ContentAssetsCollection.prototype.model = Locomotive.Models.ContentAsset; ContentAssetsCollection.prototype.url = "" + Locomotive.mounted_on + "/content_assets"; @@ -44135,124 +44640,136 @@ })(Backbone.Collection); }).call(this); (function() { - var _ref, _ref1, - __hasProp = {}.hasOwnProperty, + var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Locomotive.Models.ContentEntry = (function(_super) { __extends(ContentEntry, _super); function ContentEntry() { - _ref = ContentEntry.__super__.constructor.apply(this, arguments); - return _ref; + return ContentEntry.__super__.constructor.apply(this, arguments); } ContentEntry.prototype.paramRoot = 'content_entry'; ContentEntry.prototype.urlRoot = "" + Locomotive.mounted_on + "/content_types/:slug/entries"; ContentEntry.prototype.initialize = function() { - var _this = this; this.urlRoot = this.urlRoot.replace(':slug', this.get('content_type_slug')); - _.each(this.get('has_many_custom_fields'), function(field) { - var collection, name; - name = field[0]; - collection = new Locomotive.Models.ContentEntriesCollection(_this.get(name)); - return _this.set_attribute(name, collection); - }); - return _.each(this.get('many_to_many_custom_fields'), function(field) { - var collection, name; - name = field[0]; - collection = new Locomotive.Models.ContentEntriesCollection(_this.get(name)); - collection.comparator = function(entry) { - return entry.get('__position') || 0; + _.each(this.get('has_many_custom_fields'), (function(_this) { + return function(field) { + var collection, name; + name = field[0]; + collection = new Locomotive.Models.ContentEntriesCollection(_this.get(name)); + return _this.set_attribute(name, collection); }; - return _this.set_attribute(name, collection); - }); + })(this)); + return _.each(this.get('many_to_many_custom_fields'), (function(_this) { + return function(field) { + var collection, name; + name = field[0]; + collection = new Locomotive.Models.ContentEntriesCollection(_this.get(name)); + collection.comparator = function(entry) { + return entry.get('__position') || 0; + }; + return _this.set_attribute(name, collection); + }; + })(this)); }; ContentEntry.prototype.set_attribute = function(attribute, value) { var data; data = {}; data[attribute] = value; return this.set(data); }; ContentEntry.prototype.update_attributes = function(attributes) { - var _this = this; - return _.each(this.get('file_custom_fields'), function(field) { - var attribute; - attribute = "" + field + "_url"; - _this.set_attribute(attribute, attributes[attribute]); - return _this.set_attribute("remove_" + field, false); - }); + return _.each(this.get('file_custom_fields'), (function(_this) { + return function(field) { + var attribute; + attribute = "" + field + "_url"; + _this.set_attribute(attribute, attributes[attribute]); + return _this.set_attribute("remove_" + field, false); + }; + })(this)); }; + ContentEntry.prototype.reset_attributes = function() { + return _.each(_.keys(this.attributes), (function(_this) { + return function(name) { + return _this.set_attribute(name, null); + }; + })(this)); + }; + ContentEntry.prototype.toMinJSON = function() { - var _this = this; - return _.tap({}, function(hash) { - return _.each(_this.attributes, function(val, key) { - if (key === 'id' || key === '_destroy' || key.indexOf('position_in_') === 0) { - return hash[key] = val; - } - }); - }); + return _.tap({}, (function(_this) { + return function(hash) { + return _.each(_this.attributes, function(val, key) { + if (key === 'id' || key === '_destroy' || key.indexOf('position_in_') === 0) { + return hash[key] = val; + } + }); + }; + })(this)); }; ContentEntry.prototype.toJSON = function() { - var _this = this; - return _.tap(ContentEntry.__super__.toJSON.apply(this, arguments), function(hash) { - if (hash['_slug'] === null) { - hash['_slug'] = ''; - } - _.each(_.keys(hash), function(key) { - if (!_.include(_this.get('safe_attributes'), key)) { - return delete hash[key]; + return _.tap(ContentEntry.__super__.toJSON.apply(this, arguments), (function(_this) { + return function(hash) { + if (hash['_slug'] === null) { + hash['_slug'] = ''; } - }); - _.each(_this.get('has_many_custom_fields'), function(field) { - var name; - name = field[0]; - if (_this.get(name).length > 0) { - return hash["" + name + "_attributes"] = _this.get(name).toMinJSON(); - } - }); - return _.each(_this.get('many_to_many_custom_fields'), function(field) { - var name, setter_name; - name = field[0]; - setter_name = field[1]; - return hash[setter_name] = _this.get(name).sort().map(function(entry) { - return entry.id; + _.each(_.keys(hash), function(key) { + if (!_.include(_this.get('safe_attributes'), key)) { + return delete hash[key]; + } }); - }); - }); + _.each(_this.get('has_many_custom_fields'), function(field) { + var name; + name = field[0]; + if (_this.get(name).length > 0) { + return hash["" + name + "_attributes"] = _this.get(name).toMinJSON(); + } + }); + return _.each(_this.get('many_to_many_custom_fields'), function(field) { + var name, setter_name; + name = field[0]; + setter_name = field[1]; + return hash[setter_name] = _this.get(name).sort().map(function(entry) { + return entry.id; + }); + }); + }; + })(this)); }; return ContentEntry; })(Backbone.Model); Locomotive.Models.ContentEntriesCollection = (function(_super) { __extends(ContentEntriesCollection, _super); function ContentEntriesCollection() { - _ref1 = ContentEntriesCollection.__super__.constructor.apply(this, arguments); - return _ref1; + return ContentEntriesCollection.__super__.constructor.apply(this, arguments); } ContentEntriesCollection.prototype.model = Locomotive.Models.ContentEntry; ContentEntriesCollection.prototype.url = "" + Locomotive.mounted_on + "/content_types/:slug/entries"; ContentEntriesCollection.prototype.toMinJSON = function() { - var _this = this; - return this.map(function(entry) { - return entry.toMinJSON(); - }); + return this.map((function(_this) { + return function(entry) { + return entry.toMinJSON(); + }; + })(this)); }; return ContentEntriesCollection; })(Backbone.Collection); @@ -45032,22 +45549,21 @@ })(Backbone.View); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).ContentAssets || (_base.ContentAssets = {}); Locomotive.Views.ContentAssets.PickerItemView = (function(_super) { __extends(PickerItemView, _super); function PickerItemView() { - _ref = PickerItemView.__super__.constructor.apply(this, arguments); - return _ref; + return PickerItemView.__super__.constructor.apply(this, arguments); } PickerItemView.prototype.tagName = 'li'; PickerItemView.prototype.className = 'asset'; @@ -45060,10 +45576,23 @@ PickerItemView.prototype.render = function() { $(this.el).html(ich.content_asset(this.model.toJSON())); return this; }; + PickerItemView.prototype.refresh = function() { + return $(this.el).html(ich.content_asset(this.model.toJSON())); + }; + + PickerItemView.prototype.uploaded_at = function(loaded, total) { + var percentage; + percentage = (loaded / total) * 100; + if (percentage < 20) { + percentage = 20; + } + return this.$('.uploading .progress-bar').css('width', "" + percentage + "%"); + }; + PickerItemView.prototype.select_asset = function(event) { event.stopPropagation() & event.preventDefault(); return this.on_select(this.model); }; @@ -45086,22 +45615,21 @@ })(Backbone.View); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).Shared || (_base.Shared = {}); Locomotive.Views.Shared.AssetPickerView = (function(_super) { __extends(AssetPickerView, _super); function AssetPickerView() { - _ref = AssetPickerView.__super__.constructor.apply(this, arguments); - return _ref; + return AssetPickerView.__super__.constructor.apply(this, arguments); } AssetPickerView.prototype.tag = 'div'; AssetPickerView.prototype.initialize = function() { @@ -45122,33 +45650,44 @@ AssetPickerView.prototype.fetch_assets = function() {}; AssetPickerView.prototype.build_uploader = function(el, link) {}; AssetPickerView.prototype.create_dialog = function() { - var _this = this; return this.dialog || (this.dialog = $(this.el).dialog({ autoOpen: false, modal: true, zIndex: window.application_view.unique_dialog_zindex(), - width: 650, - create: function(event, ui) { - var actions, input, link; - $(_this.el).prev().find('.ui-dialog-title').html(_this.$('h2').html()); - _this.$('h2').remove(); - actions = _this.$('.dialog-actions').appendTo($(_this.el).parent()).addClass('ui-dialog-buttonpane ui-widget-content ui-helper-clearfix'); - actions.find('#close-link').click(function(event) { - return _this.close(event); - }); - input = actions.find('input[type=file]'); - link = actions.find('#upload-link'); - return _this.build_uploader(input, link); - }, - open: function(event, ui, extra) { - return $(_this.el).dialog('overlayEl').bind('click', function() { - return _this.close(); - }); - } + dialogClass: this.dialog_class(), + width: 615, + minHeight: 520, + create: (function(_this) { + return function(event, ui) { + var actions, input, link; + $(_this.el).prev().find('.ui-dialog-title').html(_this.$('h2').html()); + _this.$('h2').remove(); + actions = _this.$('.dialog-actions').appendTo($(_this.el).parent()).addClass('ui-dialog-buttonpane ui-widget-content ui-helper-clearfix'); + actions.find('#close-link').click(function(event) { + return _this.close(event); + }); + input = actions.find('input[type=file]'); + link = actions.find('#upload-link'); + return _this.build_uploader(input, link); + }; + })(this), + open: (function(_this) { + return function(event, ui, extra) { + $(_this.el).dialog('overlayEl').bind('click', function() { + return _this.close(); + }); + return $(document.body).addClass('stop-scrolling'); + }; + })(this), + close: (function(_this) { + return function(event, ui, extra) { + return $(document.body).removeClass('stop-scrolling'); + }; + })(this) })); }; AssetPickerView.prototype.open = function() { return $(this.el).dialog('open'); @@ -45171,31 +45710,42 @@ AssetPickerView.prototype.center = function() { return $(this.el).dialog('option', 'position', 'center'); }; AssetPickerView.prototype.add_assets = function(collection) { - var _this = this; - collection.each(function(asset) { - return _this.add_asset(asset, true); - }); + collection.each((function(_this) { + return function(asset) { + return _this.add_asset(asset, true); + }; + })(this)); return this._refresh(); }; AssetPickerView.prototype.add_asset = function(asset, first) {}; AssetPickerView.prototype.remove_asset = function(asset) {}; + AssetPickerView.prototype.dialog_class = function() { + return 'asset-picker-dialog'; + }; + AssetPickerView.prototype._move_to_last_asset = function() { var limit; limit = this.$('ul.list li.clear').position(); if (limit != null) { return this.$('ul.list').animate({ scrollTop: limit.top }, 100); } }; + AssetPickerView.prototype._move_to_top = function() { + return this.$('ul.list').animate({ + scrollTop: 0 + }, 100); + }; + AssetPickerView.prototype._refresh = function() { if (this.collection.length === 0) { this.$('ul.list').hide() & this.$('p.no-items').show(); } else { this.$('p.no-items').hide() & this.$('ul.list').show(); @@ -45214,85 +45764,172 @@ })(Backbone.View); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).ContentAssets || (_base.ContentAssets = {}); Locomotive.Views.ContentAssets.PickerView = (function(_super) { __extends(PickerView, _super); function PickerView() { - _ref = PickerView.__super__.constructor.apply(this, arguments); - return _ref; + return PickerView.__super__.constructor.apply(this, arguments); } PickerView.prototype.number_items_per_row = 4; + PickerView.prototype.page = 1; + + PickerView.prototype.per_page = 12; + + PickerView.prototype.total_pages = null; + + PickerView.prototype.uploading = false; + PickerView.prototype._item_views = []; + PickerView.prototype.events = { + 'click .btn': 'toggle_filter_by_type', + 'change input[name=query]': 'fetch_assets' + }; + + PickerView.prototype.render = function() { + PickerView.__super__.render.apply(this, arguments); + this.enable_dropzone(); + this.enable_infinite_scroll(); + return this; + }; + PickerView.prototype.template = function() { return ich.content_asset_picker; }; - PickerView.prototype.fetch_assets = function() { - var _this = this; + PickerView.prototype.fetch_assets = function(event) { + var xhr; this._reset(); - return this.collection.fetch({ - success: function() { - return _this.open(); - } + xhr = this.collection.fetch({ + data: this._fetch_options(), + reset: true, + success: (function(_this) { + return function() { + return _this.open(); + }; + })(this) }); + return xhr.done((function(_this) { + return function() { + return _this._get_pagination_info(xhr); + }; + })(this)); }; + PickerView.prototype.toggle_filter_by_type = function(event) { + $(event.target).toggleClass('on'); + return this.fetch_assets(); + }; + PickerView.prototype.build_uploader = function(el, link) { - var _this = this; link.bind('click', function(event) { event.stopPropagation() & event.preventDefault(); - console.log(el); - window.foo = el; return el.click(); }); - return el.bind('change', function(event) { - return _.each(event.target.files, function(file) { - var asset; - asset = new Locomotive.Models.ContentAsset({ - source: file - }); - return asset.save({}, { - headers: { - 'X-Flash': true - }, - success: function(model, response) { - return _this.collection.add(model.prepare()); - }, - error: function() { - return _this.shake(); - } - }); - }); - }); + return el.bind('change', (function(_this) { + return function(event) { + return _this._persist_files(event); + }; + })(this)); }; PickerView.prototype.add_asset = function(asset, first) { var view; view = new Locomotive.Views.ContentAssets.PickerItemView({ model: asset, parent: this }); (this._item_views || (this._item_views = [])).push(view); - this.$('ul.list .clear').before(view.render().el); - this._refresh(); - if (first !== true) { - return this._move_to_last_asset(); + if (this.uploading) { + this.$('ul.list').prepend(view.render().el); + return this._refresh(); + } else { + this.$('ul.list .clear').before(view.render().el); + this._refresh(); + if (first !== true) { + return this._move_to_last_asset(); + } } }; + PickerView.prototype.enable_dropzone = function() { + var dropzone; + if (!(window.File && window.FileList && window.FileReader)) { + return; + } + dropzone = this.$('ul.list').parent(); + dropzone.on('dragover', (function(_this) { + return function(event) { + _this._stop_event(event); + return dropzone.addClass('hovered'); + }; + })(this)); + dropzone.on('dragleave', (function(_this) { + return function(event) { + _this._stop_event(event); + return dropzone.removeClass('hovered'); + }; + })(this)); + dropzone.on('dragenter', (function(_this) { + return function(event) { + return _this._stop_event(event); + }; + })(this)); + return dropzone.on('drop', (function(_this) { + return function(event) { + _this._stop_event(event); + dropzone.removeClass('hovered'); + return _this._persist_files(event); + }; + })(this)); + }; + + PickerView.prototype.enable_infinite_scroll = function() { + var $list; + $list = this.$('ul.list'); + return $list.on('scroll', (function(_this) { + return function(event) { + if (_this.throttle_timer != null) { + clearTimeout(_this.throttle_timer); + } + return _this.throttle_timer = setTimeout(function() { + var height, isScrolledToEnd, scroll, xhr; + height = $list[0].scrollHeight - $list.innerHeight(); + scroll = $list.scrollTop(); + isScrolledToEnd = scroll >= height; + if (isScrolledToEnd && _this.page < _this.total_pages) { + _this.page += 1; + xhr = _this.collection.fetch({ + data: { + page: _this.page, + per_page: _this.per_page + }, + success: function() { + _this._refresh(); + return $list.scrollTop(scroll); + } + }); + return xhr.done(function() { + return _this._get_pagination_info(xhr); + }); + } + }, 100); + }; + })(this)); + }; + PickerView.prototype.remove_asset = function(asset) { var view; view = _.find(this._item_views, function(tmp) { return tmp.model === asset; }); @@ -45300,10 +45937,84 @@ view.remove(); } return this._refresh(); }; + PickerView.prototype.dialog_class = function() { + return 'content-asset-picker-dialog'; + }; + + PickerView.prototype._fetch_options = function() { + return _.tap({ + per_page: this.per_page + }, (function(_this) { + return function(options) { + options.types = []; + _this.$('.asset-types .btn.on').each(function() { + return options.types.push($(this).data('type')); + }); + return options.query = _this.$('input[name=query]').val(); + }; + })(this)); + }; + + PickerView.prototype._persist_files = function(event) { + var files; + files = event.target.files || event.originalEvent.dataTransfer.files; + this._move_to_top(); + this.uploading = true; + _.each(files, (function(_this) { + return function(file) { + var asset, view; + asset = new Locomotive.Models.ContentAsset({ + uploading: true, + source: file + }); + _this.collection.add(asset.prepare(), { + at: 0 + }); + view = _this._find_view_by_asset(asset); + return asset.save({}, { + headers: { + 'X-Flash': true + }, + success: function(model, response) { + asset.set({ + uploading: false + }); + asset.prepare(); + return view.refresh(); + }, + error: function() { + return _this.shake(); + }, + progress: function(loaded, total) { + return view.uploaded_at(loaded, total); + } + }); + }; + })(this)); + this.uploading = false; + return this._recalculate_pagination(_.size(files)); + }; + + PickerView.prototype._recalculate_pagination = function(number_assets_added) { + var number_assets_to_delete, previous_total_pages; + previous_total_pages = this.total_pages; + if (this.page < this.total_pages) { + number_assets_to_delete = number_assets_added % this.per_page; + while (number_assets_to_delete -= 1) { + this.collection.pop(); + } + } + this.total_entries += number_assets_added; + this.total_pages = Math.ceil(this.total_entries / this.per_page); + if (this.page === previous_total_pages || previous_total_pages === 0) { + return this.page = this.total_pages; + } + }; + PickerView.prototype._on_refresh = function() { var self; self = this; return this.$('ul.list li.asset').each(function(index) { if ((index + 1) % self.number_items_per_row === 0) { @@ -45312,11 +46023,29 @@ return $(this).removeClass('last'); } }); }; + PickerView.prototype._find_view_by_asset = function(asset) { + return _.find(this._item_views || [], function(view) { + return view.model.cid === asset.cid; + }); + }; + + PickerView.prototype._stop_event = function(event) { + return event.stopPropagation() & event.preventDefault(); + }; + + PickerView.prototype._get_pagination_info = function(xhr) { + this.total_pages = parseInt(xhr.getResponseHeader('X-Total-Pages')); + this.per_page = parseInt(xhr.getResponseHeader('X-Per-Page')); + return this.total_entries = parseInt(xhr.getResponseHeader('X-Total-Entries')); + }; + PickerView.prototype._reset = function() { + this.page = 1; + this.total_pages = null; _.each(this._item_views || [], function(view) { return view.remove(); }); return PickerView.__super__._reset.call(this); }; @@ -45533,22 +46262,21 @@ })(Backbone.View); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).ContentEntries || (_base.ContentEntries = {}); Locomotive.Views.ContentEntries.FormView = (function(_super) { __extends(FormView, _super); function FormView() { - _ref = FormView.__super__.constructor.apply(this, arguments); - return _ref; + return FormView.__super__.constructor.apply(this, arguments); } FormView.prototype.el = '#content'; FormView.prototype._select_field_view = null; @@ -45608,181 +46336,193 @@ showTime: false }); }; FormView.prototype.enable_richtexteditor = function() { - var _this = this; - return _.each(this.$('li.input.rte textarea.html'), function(textarea) { - var settings; - settings = _.extend({}, _this.tinyMCE_settings(), { - oninit: (function(editor) { - return $.cmd('S', (function() { + return _.each(this.$('li.input.rte textarea.html'), (function(_this) { + return function(textarea) { + var settings; + settings = _.extend({}, _this.tinyMCE_settings(), { + oninit: (function(editor) { + return $.cmd('S', (function() { + editor.save(); + $(textarea).trigger('changeSilently'); + return _this.$('form').trigger('submit'); + }), [], { + ignoreCase: true, + document: editor.dom.doc + }); + }), + onchange_callback: function(editor) { editor.save(); - $(textarea).trigger('changeSilently'); - return _this.$('form').trigger('submit'); - }), [], { - ignoreCase: true, - document: editor.dom.doc - }); - }), - onchange_callback: function(editor) { - editor.save(); - return $(textarea).trigger('changeSilently'); - } - }); - return $(textarea).tinymce(settings); - }); + return $(textarea).trigger('changeSilently'); + } + }); + return $(textarea).tinymce(settings); + }; + })(this)); }; FormView.prototype.enable_select_fields = function() { - var _this = this; this._select_field_view = new Locomotive.Views.Shared.Fields.SelectView({ model: this.content_type }); - return _.each(this.model.get('select_custom_fields'), function(name) { - var $input_wrapper; - $input_wrapper = _this.$("#" + _this.model.paramRoot + "_" + name + "_id_input"); - $input_wrapper.append(ich.edit_select_options_button()); - return $input_wrapper.find('a.edit-options-button').bind('click', function(event) { - event.stopPropagation() & event.preventDefault(); - return _this._select_field_view.render_for(name, function(options) { - var $select; - $select = $input_wrapper.find('select'); - $select.find('option[value!=""]').remove(); - return _.each(options, function(option) { - if (!option.destroyed()) { - return $select.append(new Option(option.get('name'), option.get('id'), false, option.get('id') === _this.model.get("" + name + "_id"))); - } + return _.each(this.model.get('select_custom_fields'), (function(_this) { + return function(name) { + var $input_wrapper; + $input_wrapper = _this.$("#" + _this.model.paramRoot + "_" + name + "_id_input"); + $input_wrapper.append(ich.edit_select_options_button()); + return $input_wrapper.find('a.edit-options-button').bind('click', function(event) { + event.stopPropagation() & event.preventDefault(); + return _this._select_field_view.render_for(name, function(options) { + var $select; + $select = $input_wrapper.find('select'); + $select.find('option[value!=""]').remove(); + return _.each(options, function(option) { + if (!option.destroyed()) { + return $select.append(new Option(option.get('name'), option.get('id'), false, option.get('id') === _this.model.get("" + name + "_id"))); + } + }); }); }); - }); - }); + }; + })(this)); }; FormView.prototype.enable_belongs_to_fields = function() { - var prefix, - _this = this; + var prefix; prefix = this.namespace != null ? "" + this.namespace + "_" : ''; - return _.each(this.model.get('belongs_to_custom_fields'), function(name) { - var $el, view; - $el = _this.$("#" + prefix + _this.model.paramRoot + "_" + name + "_id"); - if ($el.length > 0) { - view = new Locomotive.Views.Shared.Fields.BelongsToView({ - model: _this.model, - name: name, - el: $el - }); - _this._belongs_to_field_views.push(view); - return view.render(); - } - }); + return _.each(this.model.get('belongs_to_custom_fields'), (function(_this) { + return function(name) { + var $el, view; + $el = _this.$("#" + prefix + _this.model.paramRoot + "_" + name + "_id"); + if ($el.length > 0) { + view = new Locomotive.Views.Shared.Fields.BelongsToView({ + model: _this.model, + name: name, + el: $el + }); + _this._belongs_to_field_views.push(view); + return view.render(); + } + }; + })(this)); }; FormView.prototype.enable_file_fields = function() { - var prefix, - _this = this; + var prefix; prefix = this.namespace != null ? "" + this.namespace + "_" : ''; - return _.each(this.model.get('file_custom_fields'), function(name) { - var view; - view = new Locomotive.Views.Shared.Fields.FileView({ - model: _this.model, - name: name, - namespace: _this.namespace - }); - _this._file_field_views.push(view); - return _this.$("#" + prefix + _this.model.paramRoot + "_" + name + "_input label").after(view.render().el); - }); + return _.each(this.model.get('file_custom_fields'), (function(_this) { + return function(name) { + var view; + view = new Locomotive.Views.Shared.Fields.FileView({ + model: _this.model, + name: name, + namespace: _this.namespace + }); + _this._file_field_views.push(view); + return _this.$("#" + prefix + _this.model.paramRoot + "_" + name + "_input label").after(view.render().el); + }; + })(this)); }; FormView.prototype.enable_has_many_fields = function() { - var _this = this; if (!this.model.isNew()) { - return _.each(this.model.get('has_many_custom_fields'), function(field) { - var inverse_of, name, new_entry, view; + return _.each(this.model.get('has_many_custom_fields'), (function(_this) { + return function(field) { + var inverse_of, name, new_entry, view; + name = field[0]; + inverse_of = field[1]; + new_entry = new Locomotive.Models.ContentEntry(_this.options["" + name + "_new_entry"]); + view = new Locomotive.Views.Shared.Fields.HasManyView({ + model: _this.model, + name: name, + new_entry: new_entry, + inverse_of: inverse_of + }); + if (view.ui_enabled()) { + _this._has_many_field_views.push(view); + return _this.$("#" + _this.model.paramRoot + "_" + name + "_input label").after(view.render().el); + } + }; + })(this)); + } + }; + + FormView.prototype.enable_many_to_many_fields = function() { + return _.each(this.model.get('many_to_many_custom_fields'), (function(_this) { + return function(field) { + var name, view; name = field[0]; - inverse_of = field[1]; - new_entry = new Locomotive.Models.ContentEntry(_this.options["" + name + "_new_entry"]); - view = new Locomotive.Views.Shared.Fields.HasManyView({ + view = new Locomotive.Views.Shared.Fields.ManyToManyView({ model: _this.model, name: name, - new_entry: new_entry, - inverse_of: inverse_of + all_entries: _this.options["all_" + name + "_entries"] }); if (view.ui_enabled()) { - _this._has_many_field_views.push(view); + _this._many_to_many_field_views.push(view); return _this.$("#" + _this.model.paramRoot + "_" + name + "_input label").after(view.render().el); } - }); - } + }; + })(this)); }; - FormView.prototype.enable_many_to_many_fields = function() { - var _this = this; - return _.each(this.model.get('many_to_many_custom_fields'), function(field) { - var name, view; - name = field[0]; - view = new Locomotive.Views.Shared.Fields.ManyToManyView({ - model: _this.model, - name: name, - all_entries: _this.options["all_" + name + "_entries"] - }); - if (view.ui_enabled()) { - _this._many_to_many_field_views.push(view); - return _this.$("#" + _this.model.paramRoot + "_" + name + "_input label").after(view.render().el); - } - }); - }; - FormView.prototype.slugify_label_field = function() { return this.$('li.input.highlighted > input[type=text]').slugify({ target: this.$('#content_entry__slug'), url: window.permalink_service_url }); }; FormView.prototype.refresh_file_fields = function() { - var _this = this; - return _.each(this._file_field_views, function(view) { - return view.refresh(); - }); + return _.each(this._file_field_views, (function(_this) { + return function(view) { + return view.refresh(); + }; + })(this)); }; FormView.prototype.refresh = function() { - var _this = this; this.$('li.input.toggle input[type=checkbox]').checkToggle('sync'); - return _.each(this._file_field_views, function(view) { - return view.refresh(); - }); + return this.refresh_file_fields(); }; FormView.prototype.reset = function() { - var _this = this; this.$('li.input.string input[type=text], li.input.text textarea, li.input.date input[type=text]').val('').trigger('change'); - _.each(this.$('li.input.rte textarea.html'), function(textarea) { - $(textarea).tinymce().setContent(''); - return $(textarea).trigger('change'); - }); - _.each(this._file_field_views, function(view) { - return view.reset(); - }); + _.each(this.$('li.input.rte textarea.html'), (function(_this) { + return function(textarea) { + $(textarea).tinymce().setContent(''); + return $(textarea).trigger('change'); + }; + })(this)); + _.each(this._file_field_views, (function(_this) { + return function(view) { + return view.reset(); + }; + })(this)); return this.$('li.input.toggle input[type=checkbox]').checkToggle('sync'); }; FormView.prototype.remove = function() { - var _this = this; this.$('li.input.date input[type=text]').datepicker('destroy'); this.$('li.input.date_time input[type=text]').datetimepicker('destroy'); this._select_field_view.remove(); - _.each(this._file_field_views, function(view) { - return view.remove(); - }); - _.each(this._has_many_field_views, function(view) { - return view.remove(); - }); - _.each(this._many_to_many_field_views, function(view) { - return view.remove(); - }); + _.each(this._file_field_views, (function(_this) { + return function(view) { + return view.remove(); + }; + })(this)); + _.each(this._has_many_field_views, (function(_this) { + return function(view) { + return view.remove(); + }; + })(this)); + _.each(this._many_to_many_field_views, (function(_this) { + return function(view) { + return view.remove(); + }; + })(this)); return FormView.__super__.remove.apply(this, arguments); }; FormView.prototype.tinyMCE_settings = function() { return window.Locomotive.tinyMCE.defaultSettings; @@ -45792,11 +46532,11 @@ })(Locomotive.Views.Shared.FormView); }).call(this); (function() { - var _base, _ref, + var _base, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).ContentEntries || (_base.ContentEntries = {}); @@ -45804,12 +46544,11 @@ Locomotive.Views.ContentEntries.PopupFormView = (function(_super) { __extends(PopupFormView, _super); function PopupFormView() { this.reset = __bind(this.reset, this); - _ref = PopupFormView.__super__.constructor.apply(this, arguments); - return _ref; + return PopupFormView.__super__.constructor.apply(this, arguments); } PopupFormView.prototype.initialize = function() { this.create_dialog(); return PopupFormView.__super__.initialize.call(this); @@ -45819,55 +46558,60 @@ PopupFormView.__super__.render.call(this); return this; }; PopupFormView.prototype.save = function(event) { - var _this = this; + this.touch_richtexteditor(); return this.save_in_ajax(event, { headers: { 'X-Flash': true }, - on_success: function(response, xhr) { - var entry; - entry = new Locomotive.Models.ContentEntry(JSON.parse(xhr.responseText)); - _this.options.parent_view.insert_or_update_entry(entry); - return _this.close(); - } + on_success: (function(_this) { + return function(response, xhr) { + var entry; + entry = new Locomotive.Models.ContentEntry(JSON.parse(xhr.responseText)); + _this.options.parent_view.insert_or_update_entry(entry); + return _this.close(); + }; + })(this) }); }; PopupFormView.prototype.create_dialog = function() { - var _this = this; return this.dialog = $(this.el).dialog({ autoOpen: false, modal: true, dialogClass: 'content-entry-popup', zIndex: window.application_view.unique_dialog_zindex(), width: 770, - create: function(event, ui) { - var actions; - $(_this.el).prev().find('.ui-dialog-title').html(_this.$('h2').html()); - _this.$('h2').remove(); - actions = _this.$('.dialog-actions').appendTo($(_this.el).parent()).addClass('ui-dialog-buttonpane ui-widget-content ui-helper-clearfix'); - actions.find('#close-link').click(function(event) { - return _this.close(event); - }); - return actions.find('input[type=submit]').click(function(event) { - var $buttons_pane, $form; - $form = _this.$el.find('form'); - $buttons_pane = $(event.target).parent(); - $.rails.disableFormElements($buttons_pane); - return $form.trigger('submit').bind('ajax:complete', function() { - return $.rails.enableFormElements($buttons_pane); + create: (function(_this) { + return function(event, ui) { + var actions; + $(_this.el).prev().find('.ui-dialog-title').html(_this.$('h2').html()); + _this.$('h2').remove(); + actions = _this.$('.dialog-actions').appendTo($(_this.el).parent()).addClass('ui-dialog-buttonpane ui-widget-content ui-helper-clearfix'); + actions.find('#close-link').click(function(event) { + return _this.close(event); }); - }); - }, - open: function(event, ui, extra) { - return $(_this.el).dialog('overlayEl').bind('click', function() { - return _this.close(); - }); - } + return actions.find('input[type=submit]').click(function(event) { + var $buttons_pane, $form; + $form = _this.$el.find('form'); + $buttons_pane = $(event.target).parent(); + $.rails.disableFormElements($buttons_pane); + return $form.trigger('submit').bind('ajax:complete', function() { + return $.rails.enableFormElements($buttons_pane); + }); + }); + }; + })(this), + open: (function(_this) { + return function(event, ui, extra) { + return $(_this.el).dialog('overlayEl').bind('click', function() { + return _this.close(); + }); + }; + })(this) }); }; PopupFormView.prototype.open = function() { var parent_el; @@ -45895,10 +46639,11 @@ PopupFormView.prototype.center = function() { return $(this.el).dialog('option', 'position', 'center'); }; PopupFormView.prototype.reset = function(entry) { + this.model.reset_attributes(); this.model.set(entry.attributes); if (entry.isNew()) { this.model.id = null; return PopupFormView.__super__.reset.call(this); } else { @@ -45910,10 +46655,18 @@ PopupFormView.prototype.enable_has_many_fields = function() {}; PopupFormView.prototype.enable_many_to_many_fields = function() {}; + PopupFormView.prototype.touch_richtexteditor = function() { + return _.each(this.$('li.input.rte textarea.html'), (function(_this) { + return function(textarea) { + return $(textarea).tinymce().save(); + }; + })(this)); + }; + PopupFormView.prototype.tinyMCE_settings = function() { return window.Locomotive.tinyMCE.popupSettings; }; return PopupFormView; @@ -47286,22 +48039,21 @@ })(Backbone.View); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).InlineEditor || (_base.InlineEditor = {}); Locomotive.Views.InlineEditor.ApplicationView = (function(_super) { __extends(ApplicationView, _super); function ApplicationView() { - _ref = ApplicationView.__super__.constructor.apply(this, arguments); - return _ref; + return ApplicationView.__super__.constructor.apply(this, arguments); } ApplicationView.prototype.el = 'body'; ApplicationView.prototype.initialize = function() { @@ -47322,65 +48074,67 @@ this.toolbar_view.render(); return this.content_assets_picker_view.render(); }; ApplicationView.prototype.enable_iframe_autoheight = function() { - var iframe, - _this = this; + var iframe; iframe = this.iframe; - return iframe.load(function() { - var iframe_content; - if (_this._$('meta[name=inline-editor]').size() > 0) { - iframe_content = iframe.contents(); - iframe_content.resize(function() { - var elem; - elem = $(this); - if (elem.outerHeight(true) > iframe.outerHeight(true)) { - return iframe.css({ - height: elem.outerHeight(true) - }); - } - }); - return iframe_content.resize(); - } else { - _this.toolbar_view.show_status('disabled', true).hide_editing_mode_block(); - return _this.enhance_iframe_links(); - } - }); + return iframe.load((function(_this) { + return function() { + var iframe_content; + if (_this._$('meta[name=inline-editor]').size() > 0) { + iframe_content = iframe.contents(); + iframe_content.resize(function() { + var elem; + elem = $(this); + if (elem.outerHeight(true) > iframe.outerHeight(true)) { + return iframe.css({ + height: elem.outerHeight(true) + }); + } + }); + return iframe_content.resize(); + } else { + _this.toolbar_view.show_status('disabled', true).hide_editing_mode_block(); + return _this.enhance_iframe_links(); + } + }; + })(this)); }; ApplicationView.prototype.set_page = function(attributes) { this.page = new Locomotive.Models.Page(attributes); this.toolbar_view.model = this.page; this.enhance_iframe(); return this.toolbar_view.refresh(); }; ApplicationView.prototype.enhance_iframe = function() { - var _window, - _this = this; + var _window; _window = this._window(); _window.Aloha.settings.locale = window.locale; window.document.title = _window.document.title; window.history.replaceState('OBJECT', 'TITLE', _window.location.href.replace('_edit', '_admin')); if ($.browser.webkit) { window.history.pushState('OBJECT', 'TITLE', _window.location.href.replace('_edit', '_admin')); } this.enhance_iframe_links(_window.Aloha.jQuery); - return _window.Aloha.bind('aloha-editable-deactivated', function(event, editable) { - return _this.toolbar_view.notify(editable.editable); - }); + return _window.Aloha.bind('aloha-editable-deactivated', (function(_this) { + return function(event, editable) { + return _this.toolbar_view.notify(editable.editable); + }; + })(this)); }; ApplicationView.prototype.enhance_iframe_links = function(_jQuery) { var toolbar_view, _window; toolbar_view = this.toolbar_view; _jQuery || (_jQuery = this._$); _window = this._window(); return _jQuery('a[class!="ui-tabs-anchor"]').live('click', function(event) { var link, url; - link = _jQuery(event.target); + link = _jQuery(this); url = link.attr('href'); if ((url != null) && url.indexOf('#') !== 0 && /^(www|http)/.exec(url) === null && /(\/_edit)$/.exec(url) === null && /^\/sites\//.exec(url) === null) { if (!link.parents('div.editable-long-text, div.editable-short-text').hasClass('aloha-editable')) { if (url === '/') { url = '/index'; @@ -47653,22 +48407,21 @@ })(Locomotive.Views.Shared.FormView); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).Pages || (_base.Pages = {}); Locomotive.Views.Pages.FormView = (function(_super) { __extends(FormView, _super); function FormView() { - _ref = FormView.__super__.constructor.apply(this, arguments); - return _ref; + return FormView.__super__.constructor.apply(this, arguments); } FormView.prototype.el = '#content'; FormView.prototype.events = { @@ -47718,42 +48471,44 @@ this.editor.replaceSelection(text); return this.image_picker_view.close(); }; FormView.prototype.replace_template = function(event) { - var link, - _this = this; + var link; event.stopPropagation() & event.preventDefault(); link = $(event.target).closest('a'); return $.rails.ajax({ url: link.attr('href'), type: 'get', dataType: 'json', - success: function(data) { - return _this.editor.setValue(data.raw_template); - } + success: (function(_this) { + return function(data) { + return _this.editor.setValue(data.raw_template); + }; + })(this) }); }; FormView.prototype.enable_liquid_editing = function() { - var input, - _this = this; + var input; input = this.$('#page_raw_template'); if (input.size() > 0) { this.editor = CodeMirror.fromTextArea(input.get()[0], { mode: 'liquid', autoMatchParens: false, lineNumbers: true, passDelay: 50, tabMode: 'shift', theme: 'default' }); - return this.editor.on('change', function(editor, change) { - return _this.model.set({ - raw_template: editor.getValue() - }); - }); + return this.editor.on('change', (function(_this) { + return function(editor, change) { + return _this.model.set({ + raw_template: editor.getValue() + }); + }; + })(this)); } }; FormView.prototype.after_inputs_fold = function() { return this.editor.refresh(); @@ -47775,101 +48530,109 @@ this.editable_elements_view.collection = this.model.get('editable_elements'); return this.editable_elements_view.refresh(); }; FormView.prototype.slugify_title = function() { - var _this = this; this.$('#page_title').slugify({ target: this.$('#page_slug'), url: window.permalink_service_url }); - return this.$('#page_slug').bind('change', (function(event) { - return _this.touched_url = true; - })); + return this.$('#page_slug').bind('change', ((function(_this) { + return function(event) { + return _this.touched_url = true; + }; + })(this))); }; FormView.prototype.listen_for_url_changes = function() { - var _this = this; - return setInterval((function() { - if (_this.touched_url) { - return _this.change_page_url() & (_this.touched_url = false); - } - }), 1200); + return setInterval(((function(_this) { + return function() { + if (_this.touched_url) { + return _this.change_page_url() & (_this.touched_url = false); + } + }; + })(this)), 1200); }; FormView.prototype.change_page_url = function() { - var _this = this; return $.rails.ajax({ url: this.$('#page_slug').data('url'), type: 'get', dataType: 'json', data: { parent_id: this.$('#page_parent_id').val(), slug: this.$('#page_slug').val() }, - success: function(data) { - _this.$('#page_slug_input .inline-hints').html(data.url).effect('highlight'); - if (data.templatized_parent) { - _this.$('li#page_slug_input').show(); - return _this.$('li#page_templatized_input, li#page_target_klass_name_input').hide(); - } else { - if (!_this.model.get('redirect')) { - return _this.$('li#page_templatized_input').show(); + success: (function(_this) { + return function(data) { + _this.$('#page_slug_input .inline-hints').html(data.url).effect('highlight'); + if (data.templatized_parent) { + _this.$('li#page_slug_input').show(); + return _this.$('li#page_templatized_input, li#page_target_klass_name_input').hide(); + } else { + if (!_this.model.get('redirect')) { + return _this.$('li#page_templatized_input').show(); + } } - } - } + }; + })(this) }); }; FormView.prototype.enable_response_type_select = function() { - var _this = this; - return this.$('li#page_response_type_input').change(function(event) { - if ($(event.target).val() === 'text/html') { - return _this.$('li#page_redirect_input, li#page_redirect_url_input, li#page_redirect_type_input').show(); - } else { - _this.model.set({ - redirect: false - }); - return _this.$('li#page_redirect_input, li#page_redirect_url_input, li#page_redirect_type_input').hide(); - } - }); + return this.$('li#page_response_type_input').change((function(_this) { + return function(event) { + if ($(event.target).val() === 'text/html') { + return _this.$('li#page_redirect_input, li#page_redirect_url_input, li#page_redirect_type_input').show(); + } else { + _this.model.set({ + redirect: false + }); + return _this.$('li#page_redirect_input, li#page_redirect_url_input, li#page_redirect_type_input').hide(); + } + }; + })(this)); }; FormView.prototype.enable_templatized_checkbox = function() { - var _this = this; this._enable_checkbox('templatized', { features: ['slug', 'redirect', 'listed'], - on_callback: function() { - return _this.$('li#page_target_klass_name_input').show(); - }, - off_callback: function() { - return _this.$('li#page_target_klass_name_input').hide(); - } + on_callback: (function(_this) { + return function() { + return _this.$('li#page_target_klass_name_input').show(); + }; + })(this), + off_callback: (function(_this) { + return function() { + return _this.$('li#page_target_klass_name_input').hide(); + }; + })(this) }); if (this.model.get('templatized_from_parent') === true) { return this.$('li#page_templatized_input').hide(); } }; FormView.prototype.enable_redirect_checkbox = function() { - var _this = this; return this._enable_checkbox('redirect', { features: ['templatized', 'cache_strategy'], - on_callback: function() { - return _this.$('li#page_redirect_url_input, li#page_redirect_type_input').show(); - }, - off_callback: function() { - return _this.$('li#page_redirect_url_input, li#page_redirect_type_input').hide(); - } + on_callback: (function(_this) { + return function() { + return _this.$('li#page_redirect_url_input, li#page_redirect_type_input').show(); + }; + })(this), + off_callback: (function(_this) { + return function() { + return _this.$('li#page_redirect_url_input, li#page_redirect_type_input').hide(); + }; + })(this) }); }; FormView.prototype.enable_other_checkboxes = function() { - var _this = this; - return _.each(['published', 'listed'], function(exp) { - return _this.$('li#page_' + exp + '_input input[type=checkbox]').checkToggle(); - }); + this.$('li.toggle input[type=checkbox].simple-toggle').checkToggle(); + return this.$('li.toggle.simple-toggle input[type=checkbox]').checkToggle(); }; return FormView; })(Locomotive.Views.Shared.FormView); @@ -48049,79 +48812,135 @@ })(Locomotive.Views.Pages.FormView); }).call(this); (function() { - var _base, _base1, _ref, + var _base, _base1, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).Shared || (_base.Shared = {}); (_base1 = Locomotive.Views.Shared).Fields || (_base1.Fields = {}); - Locomotive.Views.Shared.Fields.BelongsToView = (function(_super) { - __extends(BelongsToView, _super); + Locomotive.Views.Shared.Fields.RelationshipView = (function(_super) { + __extends(RelationshipView, _super); - function BelongsToView() { - _ref = BelongsToView.__super__.constructor.apply(this, arguments); - return _ref; + function RelationshipView() { + return RelationshipView.__super__.constructor.apply(this, arguments); } - BelongsToView.prototype.render = function() { - this.enable_select2(); - return this; - }; - - BelongsToView.prototype.enable_select2 = function() { - var options, - _this = this; - options = $(this.el).data(); - $(this.el).select2({ + RelationshipView.prototype.enable_select2 = function(element, options) { + options || (options = {}); + options.init_selection_fn || (options.init_selection_fn = function(element, callback) { + return null; + }); + return element.select2({ width: '50%', minimumInputLength: 1, quietMillis: 100, allowClear: true, placeholder: ' ', + initSelection: options.init_selection_fn, ajax: { url: options.url, data: function(term, page) { return { q: term, page: page }; }, - results: function(data, page) { - return { - results: data.map(function(item) { - return { - id: item._id, - text: item._label || '' - }; - }), - more: data.length === options.perPage + results: (function(_this) { + return function(data, page) { + return { + results: _this.build_results(data, options.groupBy), + more: data.length === options.perPage + }; }; - } - }, - initSelection: function(el, callback) { - return callback({ - id: el.val(), - text: options.value - }); + })(this) } }); - return $(this.el).on('select2-selecting', function(el) { - return _this.model.set("" + _this.options.name + "_id", el.val); - }); }; - return BelongsToView; + RelationshipView.prototype.build_results = function(raw_data, group_by) { + return _.tap([], (function(_this) { + return function(list) { + return _.each(raw_data, function(data) { + var group, group_name; + if ((_this.collection == null) || (_this.collection.get(data._id) == null)) { + data.text = data._label; + if (group_by != null) { + group_name = _.result(data, group_by); + group = _.find(list, function(_group) { + return _group.text === group_name; + }); + if (group == null) { + group = { + text: group_name, + children: [] + }; + list.push(group); + } + return group.children.push(data); + } else { + return list.push(data); + } + } + }); + }; + })(this)); + }; + return RelationshipView; + })(Backbone.View); }).call(this); (function() { + var _base, _base1, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + (_base = Locomotive.Views).Shared || (_base.Shared = {}); + + (_base1 = Locomotive.Views.Shared).Fields || (_base1.Fields = {}); + + Locomotive.Views.Shared.Fields.BelongsToView = (function(_super) { + __extends(BelongsToView, _super); + + function BelongsToView() { + return BelongsToView.__super__.constructor.apply(this, arguments); + } + + BelongsToView.prototype.render = function() { + this.enable_select2(); + return this; + }; + + BelongsToView.prototype.enable_select2 = function() { + var options; + options = $(this.el).data(); + options.init_selection_fn = function(el, callback) { + return callback({ + id: el.val(), + text: options.value + }); + }; + BelongsToView.__super__.enable_select2.call(this, $(this.el), options); + return $(this.el).on('select2-selecting', (function(_this) { + return function(el) { + return _this.model.set("" + _this.options.name + "_id", el.val); + }; + })(this)); + }; + + return BelongsToView; + + })(Locomotive.Views.Shared.Fields.RelationshipView); + +}).call(this); +(function() { var _base, _base1, _ref, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).Shared || (_base.Shared = {}); @@ -48415,11 +49234,11 @@ })(Backbone.View); }).call(this); (function() { - var _base, _base1, _ref, + var _base, _base1, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).Shared || (_base.Shared = {}); @@ -48427,21 +49246,20 @@ Locomotive.Views.Shared.Fields.ManyToManyView = (function(_super) { __extends(ManyToManyView, _super); function ManyToManyView() { - _ref = ManyToManyView.__super__.constructor.apply(this, arguments); - return _ref; + return ManyToManyView.__super__.constructor.apply(this, arguments); } ManyToManyView.prototype.tagName = 'div'; ManyToManyView.prototype.className = 'list'; ManyToManyView.prototype.events = { 'click .new-entry a.add': 'add_entry', - 'keypress .new-entry select': 'add_entry', + 'keypress .new-entry input.selected-entry': 'add_entry', 'click ul span.actions a.remove': 'remove_entry' }; ManyToManyView.prototype.template = function() { return ich["" + this.options.name + "_list"]; @@ -48451,32 +49269,32 @@ return ich["" + this.options.name + "_entry"]; }; ManyToManyView.prototype.initialize = function() { _.bindAll(this, 'refresh_position_entries'); - this.collection = this.model.get(this.options.name); - return this.all_entries = this.options.all_entries; + return this.collection = this.model.get(this.options.name); }; ManyToManyView.prototype.render = function() { $(this.el).html(this.template()()).attr('id', "" + this.model.paramRoot + "_" + this.options.name + "_ids"); this.insert_entries(); this.make_entries_sortable(); - this.refresh_select_field(); + this.enable_select2(); return this; }; ManyToManyView.prototype.ui_enabled = function() { return this.template() != null; }; ManyToManyView.prototype.insert_entries = function() { - var _this = this; if (this.collection.length > 0) { - return this.collection.each(function(entry) { - return _this.insert_entry(entry); - }); + return this.collection.each((function(_this) { + return function(entry) { + return _this.insert_entry(entry); + }; + })(this)); } else { return this.$('.empty').show(); } }; @@ -48501,29 +49319,30 @@ update: this.refresh_position_entries }); }; ManyToManyView.prototype.refresh_position_entries = function() { - var _this = this; - return this.$('> ul > li').each(function(index, entry_html) { - var entry, id; - id = $(entry_html).data('data-entry-id'); - entry = _this.collection.get(id); - return entry.set_attribute("__position", index); - }); + return this.$('> ul > li').each((function(_this) { + return function(index, entry_html) { + var entry, id; + id = $(entry_html).data('data-entry-id'); + entry = _this.collection.get(id); + return entry.set_attribute("__position", index); + }; + })(this)); }; ManyToManyView.prototype.add_entry = function(event) { - var entry, entry_id; + var data, entry; event.stopPropagation() & event.preventDefault(); - entry_id = this.$('.new-entry select').val(); - entry = this.get_entry_from_id(entry_id); - if (entry == null) { + data = this.$('.new-entry .selected-entry').select2('data'); + if ((data == null) || _.isArray(data)) { return; } + entry = new Locomotive.Models.ContentEntry(data); this.insert_entry(entry); - return this.refresh_select_field(); + return this.$('.new-entry .selected-entry').select2('val', ''); }; ManyToManyView.prototype.remove_entry = function(event) { var entry; event.stopPropagation() & event.preventDefault(); @@ -48532,70 +49351,31 @@ this.collection.remove(entry); $(event.target).closest('li').remove(); if (this.$('> ul > li').size() === 0) { this.$('.empty').show(); } - return this.refresh_position_entries() & this.refresh_select_field(); + return this.refresh_position_entries(); } }; - ManyToManyView.prototype.refresh_select_field = function() { - var _this = this; - this.$('.new-entry select optgroup, .new-entry select option').remove(); - return _.each(this.all_entries, function(entry_or_group) { - var group_html, option; - if (_.isArray(entry_or_group.entries)) { - group_html = $('<optgroup/>').attr('label', entry_or_group.name); - _.each(entry_or_group.entries, function(entry) { - var option; - if (_this.collection.get(entry._id) == null) { - option = new Option(entry._label, entry._id, false); - return group_html.append(option); - } - }); - return _this.$('.new-entry select').append(group_html); - } else { - if (_this.collection.get(entry_or_group._id) == null) { - option = new Option(entry_or_group._label, entry_or_group._id, false); - return _this.$('.new-entry select').append(option); - } - } - }); + ManyToManyView.prototype.enable_select2 = function() { + var $input, options; + $input = this.$('.new-entry .selected-entry'); + options = $input.data(); + return ManyToManyView.__super__.enable_select2.call(this, $input, options); }; ManyToManyView.prototype.get_entry_from_element = function(element) { var entry_html, id; entry_html = $(element).closest('li'); id = $(entry_html).data('data-entry-id'); return this.collection.get(id); }; - ManyToManyView.prototype.get_entry_from_id = function(id) { - var entry, - _this = this; - entry = null; - _.each(this.all_entries, function(entry_or_group) { - if (_.isArray(entry_or_group.entries)) { - return entry || (entry = _.detect(entry_or_group.entries, function(_entry) { - return _entry._id === id; - })); - } else { - if (entry_or_group._id === id) { - return entry = entry_or_group; - } - } - }); - if (entry != null) { - return new Locomotive.Models.ContentEntry(entry); - } else { - return null; - } - }; - return ManyToManyView; - })(Backbone.View); + })(Locomotive.Views.Shared.Fields.RelationshipView); }).call(this); (function() { var _base, _base1, _ref, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, @@ -49073,22 +49853,21 @@ })(Locomotive.Views.Shared.FormView); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).Snippets || (_base.Snippets = {}); Locomotive.Views.Snippets.FormView = (function(_super) { __extends(FormView, _super); function FormView() { - _ref = FormView.__super__.constructor.apply(this, arguments); - return _ref; + return FormView.__super__.constructor.apply(this, arguments); } FormView.prototype.el = '#content'; FormView.prototype.events = { @@ -49116,12 +49895,11 @@ }; FormView.prototype.slugify_name = function() { return this.$('#snippet_name').slugify({ target: this.$('#snippet_slug'), - url: window.permalink_service_url, - underscore: true + url: window.permalink_service_url }); }; FormView.prototype.open_image_picker = function(event) { event.stopPropagation() & event.preventDefault(); @@ -49135,41 +49913,43 @@ this.editor.replaceSelection(text); return this.image_picker_view.close(); }; FormView.prototype.replace_template = function(event) { - var link, - _this = this; + var link; event.stopPropagation() & event.preventDefault(); link = $(event.target).closest('a'); return $.rails.ajax({ url: link.attr('href'), type: 'get', dataType: 'json', - success: function(data) { - return _this.editor.setValue(data.template); - } + success: (function(_this) { + return function(data) { + return _this.editor.setValue(data.template); + }; + })(this) }); }; FormView.prototype.enable_liquid_editing = function() { - var input, - _this = this; + var input; input = this.$('#snippet_template'); this.editor = CodeMirror.fromTextArea(input.get()[0], { mode: 'liquid', autoMatchParens: false, lineNumbers: false, passDelay: 50, tabMode: 'shift', theme: 'default medium' }); - return this.editor.on('change', function(editor, change) { - return _this.model.set({ - template: editor.getValue() - }); - }); + return this.editor.on('change', (function(_this) { + return function(editor, change) { + return _this.model.set({ + template: editor.getValue() + }); + }; + })(this)); }; FormView.prototype.after_inputs_fold = function() { return this.editor.refresh(); }; @@ -49481,22 +50261,21 @@ })(Locomotive.Views.ThemeAssets.FormView); }).call(this); (function() { - var _base, _ref, + var _base, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; (_base = Locomotive.Views).ThemeAssets || (_base.ThemeAssets = {}); Locomotive.Views.ThemeAssets.ImagePickerView = (function(_super) { __extends(ImagePickerView, _super); function ImagePickerView() { - _ref = ImagePickerView.__super__.constructor.apply(this, arguments); - return _ref; + return ImagePickerView.__super__.constructor.apply(this, arguments); } ImagePickerView.prototype.events = { 'click ul.list a': 'select_asset' }; @@ -49509,47 +50288,49 @@ ImagePickerView.prototype.template = function() { return ich.theme_image_picker; }; ImagePickerView.prototype.fetch_assets = function() { - var _this = this; this._reset(); return this.collection.fetch({ data: { content_type: 'image' }, - success: function() { - return _this.open(); - } + success: (function(_this) { + return function() { + return _this.open(); + }; + })(this) }); }; ImagePickerView.prototype.build_uploader = function(el, link) { - var _this = this; link.bind('click', function(event) { event.stopPropagation() & event.preventDefault(); return el.click(); }); - return el.bind('change', function(event) { - return _.each(event.target.files, function(file) { - var asset; - asset = new Locomotive.Models.ThemeAsset({ - source: file + return el.bind('change', (function(_this) { + return function(event) { + return _.each(event.target.files, function(file) { + var asset; + asset = new Locomotive.Models.ThemeAsset({ + source: file + }); + return asset.save({}, { + headers: { + 'X-Flash': true + }, + success: function(model) { + return _this.collection.add(model); + }, + error: function() { + return _this.shake(); + } + }); }); - return asset.save({}, { - headers: { - 'X-Flash': true - }, - success: function(model) { - return _this.collection.add(model); - }, - error: function() { - return _this.shake(); - } - }); - }); - }); + }; + })(this)); }; ImagePickerView.prototype.select_asset = function(event) { event.stopPropagation() & event.preventDefault(); if (this.options.on_select) { @@ -49925,6 +50706,6 @@ $(document).ready(function() { $.datepicker.setDefaults($.datepicker.regional[window.locale]); }); -;TI"required_assets_digest;TI"%3278809b02741b32a867a3bf3c0a4b25;FI" _version;TI"%ffd318ca8b794f42f5029101c2cf5d91;F +;TI"required_assets_digest;TI"%b00294ded64bfd6313083a653b4b4b7a;FI" _version;TI"%ffd318ca8b794f42f5029101c2cf5d91;F \ No newline at end of file