/* globals $ */ var smapi = smapi || {}; /** * Manages the logic for line range selections. * @param {int} maxLines The maximum number of lines in the content. */ smapi.LineNumberRange = function (maxLines) { var self = this; /** * @var {int} minLine The first line in the selection, or null if no lines selected. */ self.minLine = null; /** * @var {int} maxLine The last line in the selection, or null if no lines selected. */ self.maxLine = null; /** * Parse line numbers from a URL hash. * @param {string} hash the URL hash to parse. */ self.parseFromUrlHash = function (hash) { self.minLine = null; self.maxLine = null; // parse hash var hashParts = hash.match(/^#L(\d+)(?:-L(\d+))?$/); if (!hashParts || hashParts.length <= 1) return; // extract min/max lines self.minLine = parseInt(hashParts[1]); self.maxLine = parseInt(hashParts[2]) || self.minLine; }; /** * Generate a URL hash for the current line range. * @returns {string} The generated URL hash. */ self.buildHash = function() { if (!self.minLine) return ""; else if (self.minLine === self.maxLine) return "#L" + self.minLine; else return "#L" + self.minLine + "-L" + self.maxLine; } /** * Get a list of all selected lines. * @returns {Array} The selected line numbers. */ self.getLinesSelected = function() { // format if (!self.minLine) return []; var lines = []; for (var i = self.minLine; i <= self.maxLine; i++) lines.push(i); return lines; }; return self; }; /** * UI logic for the JSON validator page. * @param {string} urlFormat The URL format for a file, with $schemaName and $id placeholders. * @param {string} pasteID The Pastebin paste ID for the content being viewed, if any. */ smapi.jsonValidator = function (urlFormat, pasteID) { /** * The original content element. */ var originalContent = $("#raw-content").clone(); /** * The currently highlighted lines. */ var selection = new smapi.LineNumberRange(); /** * Rebuild the syntax-highlighted element. */ var formatCode = function () { // reset if needed $(".sunlight-container").replaceWith(originalContent.clone()); // apply default highlighting Sunlight.highlightAll({ lineHighlight: selection.getLinesSelected() }); // fix line links $(".sunlight-line-number-margin a").each(function() { var link = $(this); var lineNumber = parseInt(link.text()); link .attr("id", "L" + lineNumber) .attr("href", "#L" + lineNumber) .removeAttr("name") .data("line-number", lineNumber); }); }; /** * Scroll the page so the selected range is visible. */ var scrollToRange = function() { if (!selection.minLine) return; var targetLine = Math.max(1, selection.minLine - 5); $("#L" + targetLine).get(0).scrollIntoView(); }; /** * Initialize the JSON validator page. */ var init = function () { // set initial code formatting selection.parseFromUrlHash(location.hash); formatCode(); scrollToRange(); // update code formatting on hash change $(window).on("hashchange", function() { selection.parseFromUrlHash(location.hash); formatCode(); scrollToRange(); }); // change format $("#output #format").on("change", function() { var schemaName = $(this).val(); location.href = urlFormat.replace("$schemaName", schemaName).replace("$id", pasteID); }); // upload form var submit = $("#submit"); var input = $("#input"); if (input.length) { // disable submit if it's empty var toggleSubmit = function () { var hasText = !!input.val().trim(); submit.prop("disabled", !hasText); }; input.on("input", toggleSubmit); toggleSubmit(); // drag & drop file input.on({ 'dragover dragenter': function (e) { e.preventDefault(); e.stopPropagation(); }, 'drop': function (e) { var dataTransfer = e.originalEvent.dataTransfer; if (dataTransfer && dataTransfer.files.length) { e.preventDefault(); e.stopPropagation(); var file = dataTransfer.files[0]; var reader = new FileReader(); reader.onload = $.proxy(function (file, $input, event) { $input.val(event.target.result); toggleSubmit(); }, this, file, $("#input")); reader.readAsText(file); } } }); } }; init(); };