<commit_before>// -- settings, immutable -- //
var BRIGHTNESS_FACTOR = 10; // Higher = brighter
var STAR_SIZE_PIXELS = 1.5;
var STAR_RANGE_INDICES = 10; // Higher = more random looking, comp expensive
var LEVEL_DEPTH = 5; // Higher = more (faint) stars, comp expensive

// TODO:
// - touchscreen support
// - resize / fullscreen
// - older browsers / polyfill

var MAX_INT = -1 >>> 1;

// -- zoom and pan, altered by listeners -- //
var offsetX = 0; // Top left has this x coordinate in world frame.
var offsetY = 0;
// scale of 1 means 1 world unit = 1 canvas pixel
// scale of 100 means 1 world unit = 100 canvas pixels
var scale = 1;

var canvas = document.getElementById("starfield");
canvas.style['background-color'] = 'black';
var context = canvas.getContext('2d');

var timestamps = [];

function hashFnv32a(str) {
  var i, l,
    hval = 0x811c9dc5;

  for (i = 0, l = str.length; i < l; i++) {
    hval ^= str.charCodeAt(i);
    hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) +
      (hval << 24);
  }
  return hval >> 0;
}

var cache = new RRCache(100000);
function cachedHash(to_hash) {
  var cached = cache.get(to_hash);
  if (cached) return cached; else {
    var digest = [
      hashFnv32a(to_hash + 'a'),
      hashFnv32a(to_hash + 'b'),
      hashFnv32a(to_hash + 'c')
    ];
    cache.set(to_hash, digest);
    return digest;
  }
}

function render() {
  var worldWidth = canvas.width / scale;
  var worldHeight = canvas.height / scale;

  // The level at which you would expect one star in current viewport.
  var levelForCurrentScale = - Math.log(worldWidth * worldHeight) / 2
  var startLevel = Math.floor(levelForCurrentScale);
  context.clearRect(0, 0, canvas.width, canvas.height);

  // setting fillStyle is expensive, so quantize and batch it.
  var brightnessToWorldPositions = [];
  for (var i = 0; i < 100; i++) brightnessToWorldPositions.push([]);

  for (level = startLevel; level < startLevel + LEVEL_DEPTH; level++) {
    var spacing = Math.exp(-level);
    for (
      xIndex = Math.floor(offsetX / spacing) - STAR_RANGE_INDICES;
      xIndex <= Math.ceil((offsetX + worldWidth) / spacing)
        + STAR_RANGE_INDICES;
      xIndex++
    ) {
      for (
        yIndex = Math.floor(offsetY / spacing) - STAR_RANGE_INDICES;
        yIndex <= Math.ceil((offsetY + worldHeight) / spacing)
          + STAR_RANGE_INDICES;
        yIndex++
      ) {
        var hash = cachedHash(xIndex + ':' + yIndex + ':' + level);
        brightnessToWorldPositions[
          Math.floor(
	    100 * Math.atan(
              Math.exp(-level + (hash[2] / MAX_INT)) * BRIGHTNESS_FACTOR
                / Math.exp(-levelForCurrentScale)
            ) * 2 / Math.PI
          )
        ].push([
          xIndex * spacing
            + (hash[0] / MAX_INT) * spacing * STAR_RANGE_INDICES,
          yIndex * spacing
            + (hash[1] / MAX_INT) * spacing * STAR_RANGE_INDICES,
        ]);
      }
    }
  }

  for (i = 0; i < 100; i++) {
    context.fillStyle = 'rgba(255, 255, 255, ' + i / 100 + ')';
    var to_paint = brightnessToWorldPositions[i];
    for (var j = 0; j < to_paint.length; j++) {
      context.fillRect(
        (to_paint[j][0] - offsetX) * scale,
        (to_paint[j][1] - offsetY) * scale,
        STAR_SIZE_PIXELS,
        STAR_SIZE_PIXELS
      );
    }
  }

  timestamps.push(new Date().getTime());
  if (timestamps.length > 10) {
    console.log(
      (9 * 1000 / (timestamps[9] - timestamps[0])).toFixed(2) + ' fps'
    );
    timestamps = [];
  }
  requestAnimationFrame(render);
}

requestAnimationFrame(render);
<commit_msg>tweak brightness to prevent stars popping in and out<commit_after>// -- settings, immutable -- //
var BRIGHTNESS_FACTOR = 15; // Higher = brighter
var STAR_SIZE_PIXELS = 1.5;
var STAR_RANGE_INDICES = 10; // Higher = more random looking, comp expensive
var LEVEL_DEPTH = 5; // Higher = more (faint) stars, comp expensive

// TODO:
// - touchscreen support
// - resize / fullscreen
// - older browsers / polyfill

var MAX_INT = -1 >>> 1;

// -- zoom and pan, altered by listeners -- //
var offsetX = 0; // Top left has this x coordinate in world frame.
var offsetY = 0;
// scale of 1 means 1 world unit = 1 canvas pixel
// scale of 100 means 1 world unit = 100 canvas pixels
var scale = 1;

var canvas = document.getElementById("starfield");
canvas.style['background-color'] = 'black';
var context = canvas.getContext('2d');

var timestamps = [];

function hashFnv32a(str) {
  var i, l,
    hval = 0x811c9dc5;

  for (i = 0, l = str.length; i < l; i++) {
    hval ^= str.charCodeAt(i);
    hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) +
      (hval << 24);
  }
  return hval >> 0;
}

var cache = new RRCache(100000);
function cachedHash(to_hash) {
  var cached = cache.get(to_hash);
  if (cached) return cached; else {
    var digest = [
      hashFnv32a(to_hash + 'a'),
      hashFnv32a(to_hash + 'b'),
      hashFnv32a(to_hash + 'c')
    ];
    cache.set(to_hash, digest);
    return digest;
  }
}

function render() {
  var worldWidth = canvas.width / scale;
  var worldHeight = canvas.height / scale;

  // The level at which you would expect one star in current viewport.
  var levelForCurrentScale = - Math.log(worldWidth * worldHeight) / 2
  var startLevel = Math.floor(levelForCurrentScale);
  context.clearRect(0, 0, canvas.width, canvas.height);

  // setting fillStyle is expensive, so quantize and batch it.
  var brightnessToWorldPositions = [];
  for (var i = 0; i < 100; i++) brightnessToWorldPositions.push([]);

  for (level = startLevel; level < startLevel + LEVEL_DEPTH; level++) {
    var spacing = Math.exp(-level);
    for (
      xIndex = Math.floor(offsetX / spacing) - STAR_RANGE_INDICES;
      xIndex <= Math.ceil((offsetX + worldWidth) / spacing)
        + STAR_RANGE_INDICES;
      xIndex++
    ) {
      for (
        yIndex = Math.floor(offsetY / spacing) - STAR_RANGE_INDICES;
        yIndex <= Math.ceil((offsetY + worldHeight) / spacing)
          + STAR_RANGE_INDICES;
        yIndex++
      ) {
        var hash = cachedHash(xIndex + ':' + yIndex + ':' + level);
        brightnessToWorldPositions[
          Math.floor(Math.max(0,
	    100 * Math.atan(
              (
                Math.exp(
                  levelForCurrentScale - level - Math.abs(hash[2] / MAX_INT)
                ) - Math.exp(
                  // This is to prevent the lowest level of stars from
                  // suddenly popping in and out with high brightness.
                  levelForCurrentScale - (startLevel + LEVEL_DEPTH)
                )
              ) * BRIGHTNESS_FACTOR
            ) * 2 / Math.PI
          ))
        ].push([
          xIndex * spacing
            + (hash[0] / MAX_INT) * spacing * STAR_RANGE_INDICES,
          yIndex * spacing
            + (hash[1] / MAX_INT) * spacing * STAR_RANGE_INDICES,
        ]);
      }
    }
  }

  for (i = 0; i < 100; i++) {
    context.fillStyle = 'rgba(255, 255, 255, ' + i / 100 + ')';
    var to_paint = brightnessToWorldPositions[i];
    for (var j = 0; j < to_paint.length; j++) {
      context.fillRect(
        (to_paint[j][0] - offsetX) * scale,
        (to_paint[j][1] - offsetY) * scale,
        STAR_SIZE_PIXELS,
        STAR_SIZE_PIXELS
      );
    }
  }

  timestamps.push(new Date().getTime());
  if (timestamps.length > 10) {
    console.log(
      (9 * 1000 / (timestamps[9] - timestamps[0])).toFixed(2) + ' fps'
    );
    timestamps = [];
  }
  requestAnimationFrame(render);
}

requestAnimationFrame(render);
<|endoftext|>


<commit_before>var Stateless = (function(){
  'use strict';
  var skipped = {};
  var handlers = [];
  var hashRegex = /#(.*)$/;

  var fire = function(state) {
    for (var i = 0; i < handlers.length; i++) {
      handlers[i](state);
    }
  };

  var getState = function() {
    // Workaround for Firefox which automatically
    // decodes the hash fragment [bug:483304]
    var hash = hashRegex.exec(window.location.href);
    return hash ? hash[1] : '';
  };

  var off = function(fn) {
    var idx = handlers.indexOf(fn);
    if (idx !== -1)
      handlers.splice(idx, 1);
  };

  window.addEventListener('hashchange', function() {
    var state = getState();
    if (skipped[state])
      delete skipped[state];
    else
      fire(state);
  });

  return {
    // Control
    off: off,
    clear:    function() { handlers = []; },
    skip:     function(s) { skipped[s] = true; },
    onChange: function(fn) { handlers.push(fn); },

    // Firing
    pull:     function() { fire(getState()); },
    push:     function(state) { window.location.hash = '#' + state; },
    replace:  function(state) { window.location.replace('#' + state); },
  };
})();
<commit_msg>Stylistic changes<commit_after>var Stateless = (function(){
  'use strict';
  var skipped = {};
  var handlers = [];
  var hashRegex = /#(.*)$/;

  var fire = function(state) {
    for (var i = 0; i < handlers.length; i++) {
      handlers[i](state);
    }
  };

  var getState = function() {
    // Workaround for Firefox which automatically
    // decodes the hash fragment [bug:483304]
    var hash = hashRegex.exec(window.location.href);
    return hash ? hash[1] : '';
  };

  var off = function(fn) {
    var idx = handlers.indexOf(fn);
    if (idx !== -1)
      handlers.splice(idx, 1);
  };

  window.addEventListener('hashchange', function() {
    var state = getState();
    if (skipped[state])
      delete skipped[state];
    else
      fire(state);
  });

  return {
    // Control
    off: off,
    clear:    function() { handlers = []; },
    skip:     function(s) { skipped[s] = true; },
    onChange: function(fn) { handlers.push(fn); },

    // Firing
    pull:    function() { fire(getState()); },
    push:    function(state) { window.location.hash = '#' + state; },
    replace: function(state) { window.location.replace('#' + state); },
  };
})();
<|endoftext|>


<commit_before>/*
 * Brython-server default javascript
 */

/*
 * bsConsole
 *
 * Console Proxy routes alert and prompt calls to our own handler.
 */
var bsConsole = function(){
    var consolequeue = [];
    var consoletimer = null;
    const CONSOLETIMEOUT = 10;
    const CONSOLEID = "#console";
    const OLDPROMPT = window.prompt;

    // periodically update the console control
    function Timeout() {
        var textarea = $(CONSOLEID)
        textarea.append(consolequeue.join(""))
        textarea.scrollTop(textarea[0].scrollHeight);
        consolequeue = [];
        consoletimer = null;
    }

    function Initialize() {
        // take over the prompt dialog so we can display prompt text in the console
        window.prompt = function(text, defvalue) {
            // flush any pending console writes
            if (consoletimer) {
                window.clearTimeout(consoletimer);
                Timeout(); // flush the queue
            }
            consolequeue.push(text);  // put prompt
            Timeout(); // onto console
            var returnedValue = OLDPROMPT(text, defvalue);
            consolequeue.push(returnedValue);  // and the response...
            consolequeue.push('\n');
            Timeout();
            return returnedValue;
        }
        // now seize the output
        takeOverConsole();
    }

    // Console hijacker - http://tobyho.com/2012/07/27/taking-over-console-log/
    // target is ID of alternate destination
    function takeOverConsole(){
        var console = window.console;
        if (!console) return;
        function intercept(method){
            var original = console[method]
            console[method] = function(){
                for (i = 0; i < arguments.length; i++) {
                    if (arguments[i].indexOf("Error 404 means that Python module") != 0) {
                        if (!consoletimer) {
                            consoletimer = window.setTimeout(Timeout, CONSOLETIMEOUT);
                        }
                        consolequeue.push(arguments[i]);
                    }
                }
                if (original.apply){
                    // Do this for normal browsers
                    original.apply(console, arguments)
                }else{
                    // Do this for IE
                    var message = Array.prototype.slice.apply(arguments).join(' ')
                    original(message)
                }
            }
        }
        var methods = ['log', 'warn', 'error']
        for (var i = 0; i < methods.length; i++)
            intercept(methods[i])
    }

    // clear the console output
    function clearConsole() {
        $(CONSOLEID).html('');
    }

    // public API
    return{
        timeout:Timeout,
        init:Initialize,
        clear:clearConsole
    }
}();

/* END bsConsole */

/*
 * bsUI
 *
 * User Interface Functionality
 */
var bsUI = function(){

    const GITHUB_URL = '#github_url'
    const SHARE_URL = '#share_url'
    const URL_SUBMIT = '#url_submit'
    const URL_INPUT = '#url_input'
    const RUN_EDIT = '#run_edit'
    const RUN_EDIT_FORM = '#run_edit_form'

    var editor = null;

    function Initialize() {
        // Github link is not visible by default
        $(GITHUB_URL).hide();
        // Share link is not visible by default
        var share_link = $(SHARE_URL);
        if (share_link) {
            share_link.hide();
        }
        // Capture <enter> key on GITHUB_URL and direct to URL_SUBMIT
        $(URL_INPUT).keyup(function(event){
            if(event.keyCode == 13){
                event.preventDefault();
                $(URL_SUBMIT).click();
            }
        });

    }

    // Show github link
    function showGithub(path) {
        var element = $(GITHUB_URL);
        element.attr('href', path);
        element.show();
    }

    // Show share link
    function showShareURL(data) {
        var element = $(SHARE_URL)
        var baseargs = "?user=" + data['user'] + "&repo=" + data['repo'] + "&name=" + data['name'];
        if (data['path'] == '') {
            element.attr('href', baseargs)
        }
        else {
            element.attr('href', baseargs +  "&path=" + data['path'])
        }
        element.show()
    }

    // Execute the EDIT button
    function runEdit() {
        $(RUN_EDIT).val($(GITHUB_URL).attr('href'))
        $(RUN_EDIT_FORM).submit();
    }

    // Create editor
    function startEditor() {
        editor = ace.edit("editor");
        editor.setTheme("ace/theme/eclipse");
        editor.setShowPrintMargin(true);
        editor.setDisplayIndentGuides(true);
        editor.getSession().setMode("ace/mode/python");
        editor.$blockScrolling = Infinity;
    }

    // Get editor content
    function getEditor() {
        if (editor) {
            return editor.getValue()
        }
    }

    // Set editor content
    function setEditor(text) {
        if (editor) {
            editor.setValue(text);
        }
    }

    // Clear editor selection
    function clearEditorSelection() {
        if (editor) {
            editor.selection.clearSelection();
        }
    }

    // Public API
    return {
        URL_INPUT:URL_INPUT,
        init:Initialize,
        showgithub:showGithub,
        showshareurl:showShareURL,
        runedit:runEdit,
        starteditor:startEditor,
        geteditor:getEditor,
        seteditor:setEditor,
        clearselect:clearEditorSelection
    }

}();
/* END bsUI */

/*
 * bsGithubUtil
 *
 * Github Utilities
 */
var bsGithubUtil = function(){

    // create a Github file path
    function createGithubPath(data) {
        var path = data['path'];
        if (path.length > 0 && path.substr(path.length-1) != "/") {
            path += "/";
        }
        path += data['name'];
        return path
    }

    // create a Github URL text for speciic file
    function createGithubURL(data) {
        var url = "https://github.com/" + data['user'] + "/" + data['repo']
        url += "/blob/master/" + createGithubPath(data);
        return url
    }

    // parse Github URL text
    function parseGithubURL(url_input) {
        var data = null;
        // attempt a single file match
        // example: https://github.com/tiggerntatie/brython-student-test/blob/master/hello.py
        // example: https://github.com/tiggerntatie/hhs-cp-site/blob/master/hhscp/static/exemplars/c02hello.py
        // example subtree: https://github.com/tiggerntatie/hhs-cp-site/tree/master/hhscp/static/exemplars
        var gittreematch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+)\/tree\/master\/(.+)/);
        var gitfilematch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+)\/blob\/master\/([^/]+)/);
        var gittreefilematch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+)\/blob\/master\/(.+)\/([^/]+)/);
        var gitrepomatch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+).*/);
        if (gitrepomatch) {
            data = {'user':gitrepomatch[1], 'repo':gitrepomatch[2], 'path':'', 'name':''};
            if (gittreematch) {
                data['path'] = gittreematch[3];
            }
            if (gittreefilematch) {
                data['path'] = gittreefilematch[3];
                data['name'] = gittreefilematch[4];
            }
            else if (gitfilematch) {
                data['name'] = gitfilematch[3];
            }
        }
        return data;
    }

    // parse the url_input and return structure with user, repo, path, name
    function parseGithub(UI) {
        return parseGithubURL($(UI.URL_INPUT).val())
    }

    return {
        parse:parseGithub,
        parseurl:parseGithubURL,
        createurl:createGithubURL
    }

}();
/* END bsGithubUtil */

/*
 * bsController
 *
 * Miscellaneous actions and network transactions
 */
var bsController = function(){

    var maincontent = ''
    var mainscript = null;
    const __MAIN__ = "__main__";

    // Execute the brython interpreter
    function runBrython(console, argdict) {
        console.clear();
        brython(argdict);
    }

    function removeMainScript() {
        if (mainscript) {
            document.head.removeChild(mainscript);
        }
    }

    function initMainScript() {
        removeMainScript()
        mainscript = document.createElement('script');
        mainscript.type = "text/python";
        mainscript.async = false;
        mainscript.id = __MAIN__;
    }

    // Set main python script as inline
    function setMainValue(txt) {
        initMainScript()
        mainscript.innerHTML = txt;
        document.head.appendChild(mainscript);
    }

    // load script from github, embed in html and execute
    // data dictionary input includes user, repo, name and path (fragment)
    function runGithub(Console, UI, data) {
        var result = loadGithubtoScript(UI,data);
        if (result) {
            setMainValue(maincontent);
            if (mainscript) {
                runBrython(Console, {debug:1, ipy_id:[__MAIN__]});
            }
        }
    }

    // update server with new editor content (all the time!)
    function sendEditorChange(UI) {
        var data = {'editcontent':UI.geteditor(),
            'url_input':$(UI.URL_INPUT).val()};
        var xhr = new XMLHttpRequest();
        xhr.open('PUT', 'api/v1/update', false);  // synchronous
        xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
        // send the collected data as JSON
        xhr.send(JSON.stringify(data));
        var result = JSON.parse(xhr.responseText);
    }

    // re-execute current mainscript
    function runCurrent(Console) {
        if (mainscript) {
                runBrython(Console, {debug:1, ipy_id:[__MAIN__]});
        }
    }

    // execute contents of editor and update server with new content
    function runEditor(UI, Console) {
        sendEditorChange(UI);
        setMainValue(UI.geteditor());
        runCurrent(Console)
    }

    // send request to login to github
    function loginGithub(UI) {
        sendEditorChange(UI)
        $('#run_auth_request').submit();
    }

    // send request to logout of github
    // only FORGETS out github authorization - does not log out of github, per se
    function logoutGithub() {
        $('#run_auth_forget').submit();
    }

    // send request to commit/save to github
    function commitGithub(GH, UI) {
        var d = new Date()
        var ds = d.toLocaleDateString()
        var ts = d.toLocaleTimeString()
        var data = GH.parse(UI);
        data['editcontent'] = UI.geteditor();
        data['commitmsg'] = "Updated from Brython Server: "+ds+" "+ts;
        var xhr = new XMLHttpRequest();
        xhr.open('PUT', 'api/v1/commit', false);  // synchronous
        xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
        // send the collected data as JSON
        xhr.send(JSON.stringify(data));
        var result = JSON.parse(xhr.responseText);
    }

    // read main github script name and content
    // return file name
    function loadGithubtoScript(UI, data) {
        if (data) {
            var xhr = new XMLHttpRequest();
            xhr.open('PUT', 'api/v1/load', false);  // synchronous
            xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
            // send the collected data as JSON
            xhr.send(JSON.stringify(data));
            var result = JSON.parse(xhr.responseText);
            if (xhr.status == 200 && result['success'] && result['name']) {
                maincontent = result['content'];
                UI.showgithub(result['path']);
                return result;
            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    // load main github script name, insert content in editor
    function loadGithub(GH, UI) {
        var data = GH.parse(UI);
        var result = loadGithubtoScript(UI, data);
        if (result) {
            // now that we have a full URL for the file, parse again
            data = GH.parseurl(result['path']);
            $(UI.URL_INPUT).val(GH.createurl(data))
            UI.showshareurl(data);
            UI.seteditor(maincontent);
            UI.clearselect();
            sendEditorChange(UI);
        }
    }

    return {
        rungithub:runGithub,
        run:runCurrent,
        login:loginGithub,
        logout:logoutGithub,
        commit:commitGithub,
        load:loadGithub,
        runeditor:runEditor,
    }
}()
/* END bsController */

// Execute from here
bsConsole.init();<commit_msg>forgot to init UI<commit_after>/*
 * Brython-server default javascript
 */

/*
 * bsConsole
 *
 * Console Proxy routes alert and prompt calls to our own handler.
 */
var bsConsole = function(){
    var consolequeue = [];
    var consoletimer = null;
    const CONSOLETIMEOUT = 10;
    const CONSOLEID = "#console";
    const OLDPROMPT = window.prompt;

    // periodically update the console control
    function Timeout() {
        var textarea = $(CONSOLEID)
        textarea.append(consolequeue.join(""))
        textarea.scrollTop(textarea[0].scrollHeight);
        consolequeue = [];
        consoletimer = null;
    }

    function Initialize() {
        // take over the prompt dialog so we can display prompt text in the console
        window.prompt = function(text, defvalue) {
            // flush any pending console writes
            if (consoletimer) {
                window.clearTimeout(consoletimer);
                Timeout(); // flush the queue
            }
            consolequeue.push(text);  // put prompt
            Timeout(); // onto console
            var returnedValue = OLDPROMPT(text, defvalue);
            consolequeue.push(returnedValue);  // and the response...
            consolequeue.push('\n');
            Timeout();
            return returnedValue;
        }
        // now seize the output
        takeOverConsole();
    }

    // Console hijacker - http://tobyho.com/2012/07/27/taking-over-console-log/
    // target is ID of alternate destination
    function takeOverConsole(){
        var console = window.console;
        if (!console) return;
        function intercept(method){
            var original = console[method]
            console[method] = function(){
                for (i = 0; i < arguments.length; i++) {
                    if (arguments[i].indexOf("Error 404 means that Python module") != 0) {
                        if (!consoletimer) {
                            consoletimer = window.setTimeout(Timeout, CONSOLETIMEOUT);
                        }
                        consolequeue.push(arguments[i]);
                    }
                }
                if (original.apply){
                    // Do this for normal browsers
                    original.apply(console, arguments)
                }else{
                    // Do this for IE
                    var message = Array.prototype.slice.apply(arguments).join(' ')
                    original(message)
                }
            }
        }
        var methods = ['log', 'warn', 'error']
        for (var i = 0; i < methods.length; i++)
            intercept(methods[i])
    }

    // clear the console output
    function clearConsole() {
        $(CONSOLEID).html('');
    }

    // public API
    return{
        timeout:Timeout,
        init:Initialize,
        clear:clearConsole
    }
}();

/* END bsConsole */

/*
 * bsUI
 *
 * User Interface Functionality
 */
var bsUI = function(){

    const GITHUB_URL = '#github_url'
    const SHARE_URL = '#share_url'
    const URL_SUBMIT = '#url_submit'
    const URL_INPUT = '#url_input'
    const RUN_EDIT = '#run_edit'
    const RUN_EDIT_FORM = '#run_edit_form'

    var editor = null;

    function Initialize() {
        // Github link is not visible by default
        $(GITHUB_URL).hide();
        // Share link is not visible by default
        var share_link = $(SHARE_URL);
        if (share_link) {
            share_link.hide();
        }
        // Capture <enter> key on GITHUB_URL and direct to URL_SUBMIT
        $(URL_INPUT).keyup(function(event){
            if(event.keyCode == 13){
                event.preventDefault();
                $(URL_SUBMIT).click();
            }
        });

    }

    // Show github link
    function showGithub(path) {
        var element = $(GITHUB_URL);
        element.attr('href', path);
        element.show();
    }

    // Show share link
    function showShareURL(data) {
        var element = $(SHARE_URL)
        var baseargs = "?user=" + data['user'] + "&repo=" + data['repo'] + "&name=" + data['name'];
        if (data['path'] == '') {
            element.attr('href', baseargs)
        }
        else {
            element.attr('href', baseargs +  "&path=" + data['path'])
        }
        element.show()
    }

    // Execute the EDIT button
    function runEdit() {
        $(RUN_EDIT).val($(GITHUB_URL).attr('href'))
        $(RUN_EDIT_FORM).submit();
    }

    // Create editor
    function startEditor() {
        editor = ace.edit("editor");
        editor.setTheme("ace/theme/eclipse");
        editor.setShowPrintMargin(true);
        editor.setDisplayIndentGuides(true);
        editor.getSession().setMode("ace/mode/python");
        editor.$blockScrolling = Infinity;
    }

    // Get editor content
    function getEditor() {
        if (editor) {
            return editor.getValue()
        }
    }

    // Set editor content
    function setEditor(text) {
        if (editor) {
            editor.setValue(text);
        }
    }

    // Clear editor selection
    function clearEditorSelection() {
        if (editor) {
            editor.selection.clearSelection();
        }
    }

    // Public API
    return {
        URL_INPUT:URL_INPUT,
        init:Initialize,
        showgithub:showGithub,
        showshareurl:showShareURL,
        runedit:runEdit,
        starteditor:startEditor,
        geteditor:getEditor,
        seteditor:setEditor,
        clearselect:clearEditorSelection
    }

}();
/* END bsUI */

/*
 * bsGithubUtil
 *
 * Github Utilities
 */
var bsGithubUtil = function(){

    // create a Github file path
    function createGithubPath(data) {
        var path = data['path'];
        if (path.length > 0 && path.substr(path.length-1) != "/") {
            path += "/";
        }
        path += data['name'];
        return path
    }

    // create a Github URL text for speciic file
    function createGithubURL(data) {
        var url = "https://github.com/" + data['user'] + "/" + data['repo']
        url += "/blob/master/" + createGithubPath(data);
        return url
    }

    // parse Github URL text
    function parseGithubURL(url_input) {
        var data = null;
        // attempt a single file match
        // example: https://github.com/tiggerntatie/brython-student-test/blob/master/hello.py
        // example: https://github.com/tiggerntatie/hhs-cp-site/blob/master/hhscp/static/exemplars/c02hello.py
        // example subtree: https://github.com/tiggerntatie/hhs-cp-site/tree/master/hhscp/static/exemplars
        var gittreematch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+)\/tree\/master\/(.+)/);
        var gitfilematch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+)\/blob\/master\/([^/]+)/);
        var gittreefilematch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+)\/blob\/master\/(.+)\/([^/]+)/);
        var gitrepomatch = url_input.match(/.*github\.com\/([^/]+)\/([^/]+).*/);
        if (gitrepomatch) {
            data = {'user':gitrepomatch[1], 'repo':gitrepomatch[2], 'path':'', 'name':''};
            if (gittreematch) {
                data['path'] = gittreematch[3];
            }
            if (gittreefilematch) {
                data['path'] = gittreefilematch[3];
                data['name'] = gittreefilematch[4];
            }
            else if (gitfilematch) {
                data['name'] = gitfilematch[3];
            }
        }
        return data;
    }

    // parse the url_input and return structure with user, repo, path, name
    function parseGithub(UI) {
        return parseGithubURL($(UI.URL_INPUT).val())
    }

    return {
        parse:parseGithub,
        parseurl:parseGithubURL,
        createurl:createGithubURL
    }

}();
/* END bsGithubUtil */

/*
 * bsController
 *
 * Miscellaneous actions and network transactions
 */
var bsController = function(){

    var maincontent = ''
    var mainscript = null;
    const __MAIN__ = "__main__";

    // Execute the brython interpreter
    function runBrython(console, argdict) {
        console.clear();
        brython(argdict);
    }

    function removeMainScript() {
        if (mainscript) {
            document.head.removeChild(mainscript);
        }
    }

    function initMainScript() {
        removeMainScript()
        mainscript = document.createElement('script');
        mainscript.type = "text/python";
        mainscript.async = false;
        mainscript.id = __MAIN__;
    }

    // Set main python script as inline
    function setMainValue(txt) {
        initMainScript()
        mainscript.innerHTML = txt;
        document.head.appendChild(mainscript);
    }

    // load script from github, embed in html and execute
    // data dictionary input includes user, repo, name and path (fragment)
    function runGithub(Console, UI, data) {
        var result = loadGithubtoScript(UI,data);
        if (result) {
            setMainValue(maincontent);
            if (mainscript) {
                runBrython(Console, {debug:1, ipy_id:[__MAIN__]});
            }
        }
    }

    // update server with new editor content (all the time!)
    function sendEditorChange(UI) {
        var data = {'editcontent':UI.geteditor(),
            'url_input':$(UI.URL_INPUT).val()};
        var xhr = new XMLHttpRequest();
        xhr.open('PUT', 'api/v1/update', false);  // synchronous
        xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
        // send the collected data as JSON
        xhr.send(JSON.stringify(data));
        var result = JSON.parse(xhr.responseText);
    }

    // re-execute current mainscript
    function runCurrent(Console) {
        if (mainscript) {
                runBrython(Console, {debug:1, ipy_id:[__MAIN__]});
        }
    }

    // execute contents of editor and update server with new content
    function runEditor(UI, Console) {
        sendEditorChange(UI);
        setMainValue(UI.geteditor());
        runCurrent(Console)
    }

    // send request to login to github
    function loginGithub(UI) {
        sendEditorChange(UI)
        $('#run_auth_request').submit();
    }

    // send request to logout of github
    // only FORGETS out github authorization - does not log out of github, per se
    function logoutGithub() {
        $('#run_auth_forget').submit();
    }

    // send request to commit/save to github
    function commitGithub(GH, UI) {
        var d = new Date()
        var ds = d.toLocaleDateString()
        var ts = d.toLocaleTimeString()
        var data = GH.parse(UI);
        data['editcontent'] = UI.geteditor();
        data['commitmsg'] = "Updated from Brython Server: "+ds+" "+ts;
        var xhr = new XMLHttpRequest();
        xhr.open('PUT', 'api/v1/commit', false);  // synchronous
        xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
        // send the collected data as JSON
        xhr.send(JSON.stringify(data));
        var result = JSON.parse(xhr.responseText);
    }

    // read main github script name and content
    // return file name
    function loadGithubtoScript(UI, data) {
        if (data) {
            var xhr = new XMLHttpRequest();
            xhr.open('PUT', 'api/v1/load', false);  // synchronous
            xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
            // send the collected data as JSON
            xhr.send(JSON.stringify(data));
            var result = JSON.parse(xhr.responseText);
            if (xhr.status == 200 && result['success'] && result['name']) {
                maincontent = result['content'];
                UI.showgithub(result['path']);
                return result;
            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    // load main github script name, insert content in editor
    function loadGithub(GH, UI) {
        var data = GH.parse(UI);
        var result = loadGithubtoScript(UI, data);
        if (result) {
            // now that we have a full URL for the file, parse again
            data = GH.parseurl(result['path']);
            $(UI.URL_INPUT).val(GH.createurl(data))
            UI.showshareurl(data);
            UI.seteditor(maincontent);
            UI.clearselect();
            sendEditorChange(UI);
        }
    }

    return {
        rungithub:runGithub,
        run:runCurrent,
        login:loginGithub,
        logout:logoutGithub,
        commit:commitGithub,
        load:loadGithub,
        runeditor:runEditor,
    }
}()
/* END bsController */

// Execute from here
bsConsole.init();
bsUI.init();<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "c9", "settings", "ui", "menus", "ace",
        "ace.gotoline", "tabManager"
    ];
    main.provides = ["ace.status"];
    return main;

    function main(options, imports, register) {
        var c9        = imports.c9;
        var Plugin    = imports.Plugin;
        var settings  = imports.settings;
        var ui        = imports.ui;
        var tabs      = imports.tabManager;
        var menus     = imports.menus;
        var gotoline  = imports["ace.gotoline"];
        var aceHandle = imports.ace;

        var skin    = require("text!./skin.xml");
        var markup  = require("text!./statusbar.xml");
        var menuAml = require("text!./menu.xml");

        var aceWhitespace = require("ace/ext/whitespace");
        var lang = require("ace/lib/lang");

        /***** Generic Load *****/

        // Set up the generic handle
        var deps       = main.consumes.slice(0, main.consumes.length - 1);
        var handle     = new Plugin("Ajax.org", deps);
        var handleEmit = handle.getEmitter();

        var statusbars = {};
        var menuItem, menu, menuTabs;

        handle.on("load", function(){
            settings.on("read", function(e){
                settings.setDefaults("user/ace/statusbar", [["show", "true"]]);

                if (settings.getBool("user/ace/statusbar/@show"))
                    handleEmit("show");
            }, handle);

            menuItem = new apf.item({
                test : "1",
                type : "check",
                checked : "[{settings.model}::user/ace/statusbar/@show]"
                // -> if you're looking for disabled, check the init function :-)
                // the moment that someone clicks this thing well call preinit
                // (its already called if the user has it checked on IDE load)
            });

            menus.addItemByPath("View/Status Bar", menuItem, 600, handle);

            aceHandle.on("create", function(e){
                if (e.editor.type != "ace")
                    return;

                var editor = e.editor;
                var statusbar;

                editor.on("draw", function(){
                    statusbar = new Statusbar(editor);
                }, editor);
                editor.on("unload", function h2(){
                    if (statusbar) statusbar.unload();
                }, editor);
            });

            ui.insertMarkup(null, menuAml, handle);

            menu     = handle.getElement("menu");
            menuTabs = handle.getElement("menuTabs");

            var currentSession;
            function setCurrentSession(menu){
                var node = menu.opener;
                while (node && node.localName != "tab")
                    node = node.parentNode;
                if (!node) return;

                var tab = node.cloud9pane.getTab();
                currentSession = tab.document.getSession();
            }

            function setOption(name, value){
                if (currentSession) {
                    currentSession.session.setOption(name, value);
                    currentSession.statusBar.update();
                }
            }

            function getOption(name){
                return currentSession && currentSession.session.getOption(name);
            }

            // Checkboxes
            menu.on("afterrender", function(e){
                var itmSbWrap   = window.itmSbWrap;
                var itmSbWrapVP = window.itmSbWrapVP;

                itmSbWrap.on("click", function(){
                    setOption("wrap", itmSbWrap.checked
                        ? itmSbWrapVP.checked || "printMargin"
                        : false);
                });
                itmSbWrapVP.on("click", function(){
                    setOption("wrap", itmSbWrap.checked
                        ? itmSbWrapVP.checked || "printMargin"
                        : false);
                });

                function update(e){
                    if (!e || e.value){
                        setCurrentSession(menu);

                        var wrap = getOption("wrap");
                        itmSbWrap.setAttribute("checked", !ui.isFalse(wrap));
                        itmSbWrapVP.setAttribute("checked", wrap != "printMargin");
                    }
                }

                menu.on("prop.visible", update);
                update();
            });

            // Menu Tab functionality
            var handlers = [
                function(){ setOption("useSoftTabs", this.checked) },
                function(){},
                function(){ setOption("tabSize", 2) },
                function(){ setOption("tabSize", 3) },
                function(){ setOption("tabSize", 4) },
                function(){ setOption("tabSize", 8) },
                function(){
                    var tab = tabs.focussedTab;
                    if (!tab) return;
                    var session = tab.document.getSession();
                    aceWhitespace.detectIndentation(session.session);
                    var useSoftTabs = session.session.getOption("useSoftTabs");
                    var tabSize     = session.session.getOption("tabSize");
                    menuTabs.childNodes[0].setAttribute("checked", useSoftTabs);
                    if (tabSize < 9)
                        menuTabs.childNodes[tabSize + 1].setAttribute("selected", true);
                    session.statusBar.update();
                },
                // Tabs to Spaces
                function(){
                    var tab = tabs.focussedTab;
                    if (!tab) return;
                    var session = tab.document.getSession();
                    aceWhitespace.convertIndentation(session.session, " ");
                    session.statusBar.update();
                },
                // Spaces to Tabs
                function(){
                    var tab = tabs.focussedTab;
                    if (!tab) return;
                    var session = tab.document.getSession();
                    aceWhitespace.convertIndentation(session.session, "\t");
                    session.statusBar.update();
                }
            ];

            menuTabs.on("afterrender", function(e){
                var items = menuTabs.selectNodes("a:item");
                items.forEach(function(node, idx){
                    node.on("click", handlers[idx]);
                });

                var itmTabSize  = window.itmTabSize;
                itmTabSize.on("afterchange", function(){
                    setOption("tabSize", this.value);
                    update();
                });

                var lut = [0,0,2,3,4,0,0,0,5];

                function update(e){
                    if (e && !e.value)
                        return;

                    setCurrentSession(menuTabs);

                    items[0].setAttribute("checked", getOption("useSoftTabs"));

                    var tabSize = getOption("tabSize") || 1;
                    items.forEach(function(node, idx){
                        node.setAttribute("selected", "false");
                    });
                    if (lut[tabSize])
                        items[lut[tabSize]].setAttribute("selected", "true");
                    itmTabSize.setAttribute("value", getOption("tabSize"));
                }

                menuTabs.on("prop.visible", update);
                update();
            });
        });

        /***** Methods *****/

        var drawn = false;
        function draw(){
            if (drawn) return;
            drawn = true;

            // Import Skin
            ui.insertSkin({
                name         : "c9statusbar",
                data         : skin,
                "media-path" : options.staticPrefix + "/images/",
                "icon-path"  : options.staticPrefix + "/icons/"
            }, handle);
        };

        function getStatusbar(editor){
            return statusbars[editor.name];
        }

        function show(){
            settings.set("user/ace/statusbar/@show", "true");
        }

        function hide(){
            settings.set("user/ace/statusbar/@show", "false");
        }

        /***** Register and define API *****/

        /**
         * Manages the status bar instances for ace.
         * @singleton
         **/
        handle.freezePublicAPI({
            /**
             * Show all the status bars.
             */
            show : show,

            /**
             * Hide all the status bars.
             */
            hide : hide,

            /**
             * Retrieve the status bar that belongs to an ace editor.
             * @param {Editor} ace  The ace editor the status bar belongs to.
             * @return {ace.status.Statusbar}
             */
            getStatusbar : getStatusbar,

            /**
             * Inserts CSS for the statusbar.
             * @private
             */
            draw : draw
        });

        /***** Initialization *****/

        var counter = 0;

        function Statusbar(editor){
            var plugin = new Plugin("Ajax.org", deps);
            var emit   = plugin.getEmitter();

            var showRange;

            var bar, lblSelection, lblStatus, lblRowCol, lblTabs, lblSyntax; // ui elements

            statusbars[editor.name] = plugin;

            var loaded = false;
            function load(){
                if (loaded) return false;
                loaded = true;

                function updateBarVisible(){
                    if (!settings.getBool("user/ace/statusbar/@show")) {
                        bar && bar.hide();
                        menuItem.enable();
                    }
                    else {
                        draw();
                        bar.show();
                        menuItem.enable();
                    }
                }

                settings.on("user/ace/statusbar", updateBarVisible, plugin);

                handle.on("show", show);

                if (settings.getBool("user/ace/statusbar/@show"))
                    draw();

                editor.on("documentLoad", function(e){
                    var session = e.doc.getSession();
                    session.statusBar = plugin;
                    session.session.on("changeMode", function(e){ statusUpdate.schedule(); });
                }, plugin);
                editor.on("documentActivate", function(e){ statusUpdate.schedule(); }, plugin);
                editor.on("documentUnload", function(e){
                    delete e.doc.getSession().statusBar;
                }, plugin);
            }

            var drawn = false;
            function draw(){
                if (drawn) return;
                drawn = true;

                handle.draw();

                // Create UI elements
                var htmlNode = editor.ace.container.parentNode.host;
                ui.insertMarkup(htmlNode, markup, plugin);

                function setTheme(e){
                    var theme    = e.theme;
                    if (!theme) return;

                    var cssClass = theme.cssClass;
                    var isDark   = theme.isDark;

                    var bg = ui.getStyleRule("." + cssClass, "backgroundColor");

                    bar.setAttribute("class", isDark ? "ace_dark" : "");
                    if (bg) {
                        bg = bg.replace(/rgb\((.*)\)/, "rgba($1, 0.9)");
                        bar.$ext.style.backgroundColor = bg;
                    }
                }
                editor.on("themeChange", setTheme);

                bar          = plugin.getElement("bar");
                lblSelection = plugin.getElement("lblSelectionLength");
                lblStatus    = plugin.getElement("lblEditorStatus");
                lblRowCol    = plugin.getElement("lblRowCol");
                lblTabs      = plugin.getElement("lblTabs");
                lblSyntax    = plugin.getElement("lblSyntax");

                // For editor search of submenus
                bar.editor = editor;

                // Set sub menus
                var button = plugin.getElement("btnSbPrefs");
                button.setAttribute("submenu", menu);

                lblTabs.setAttribute("submenu", menuTabs);

                var mnuSyntax = menus.get("View/Syntax").menu;
                lblSyntax.setAttribute("submenu", mnuSyntax);
                lblSyntax.on("mousedown", function(){
                    if (editor.activeDocument)
                        tabs.focusTab(editor.activeDocument.tab);
                });

                // Click behavior for the labels
                lblSelection.on("click", function(){
                    showRange = !showRange;
                    updateStatus();
                });

                lblRowCol.on("click", function(){
                    gotoline.gotoline();
                });

                // Hook into ace
                var ace = editor.ace;
                if (!ace.$hasStatusBar) {
                    // Throttle UI updates
                    ace.on("changeSelection", function() { selStatusUpdate.schedule() });
                    ace.on("changeStatus", function() { statusUpdate.schedule() });
                    ace.renderer.on("scrollbarVisibilityChanged", function(e, renderer) {
                        bar.$ext.style.right = renderer.scrollBarV.getWidth() + 5 + "px";
                        bar.$ext.style.bottom = renderer.scrollBarH.getHeight() + 3 + "px";
                    });
                    ace.$hasStatusBar = true;

                    var theme = editor.theme;
                    setTheme({theme: theme});
                }

                // Update status information
                updateStatus();

                emit("draw");
            }

            var selStatusUpdate = lang.delayedCall(updateSelStatus, 10);
            var statusUpdate    = lang.delayedCall(updateStatus, 10);

            /***** Helper Functions *****/

            function updateSelStatus(){
                var ace = editor.ace;
                if (!ace) return;

                if (!ace.selection.isEmpty()) {
                    var range = ace.getSelectionRange();
                    var selLen;

                    if (showRange) {
                        selLen = "(" +
                            (range.end.row - range.start.row) + ":" +
                            (range.end.column - range.start.column) + ")";
                    }
                    else {
                        selLen = "(" + ace.session.getTextRange(range).length + " Bytes)";
                    }

                    lblSelection.setAttribute("caption", selLen);
                }
                else {
                    lblSelection.setAttribute("caption", "");
                }

                var cursor = ace.selection.lead;
                lblRowCol.setAttribute("caption", (cursor.row + 1) + ":" + (cursor.column + 1));
            }

            function updateStatus() {
                var ace = editor.ace;

                updateSelStatus();

                lblTabs.setAttribute("caption",
                    (ace.getOption("useSoftTabs") ? "Spaces" : "Tabs") + ": "
                      + ace.getOption("tabSize")); // "\\[" + + "\\]");

                var status = "";
                if (ace.$vimModeHandler)
                    status = ace.$vimModeHandler.getStatusText();
                else if (ace.commands.recording)
                    status = "REC";

                lblStatus.setAttribute("caption", status);

                var caption = aceHandle.getSyntaxCaption(ace.session.syntax);
                lblSyntax && lblSyntax.setAttribute("caption", caption);
            }

            /***** Lifecycle *****/

            plugin.on("load", function(){
                load();
            });
            plugin.on("enable", function(){

            });
            plugin.on("disable", function(){

            });
            plugin.on("unload", function(){
                loaded = false;
            });

            /***** Register and define API *****/

            /**
             * The status bar for ace editors.
             * @class ace.status.Statusbar
             **/
            plugin.freezePublicAPI({
                /**
                 * Redraw the display of the statusbar
                 */
                update : updateStatus
            });

            plugin.load("acestatus" + counter++);

            return plugin;
        }

        register(null, {
            "ace.status" : handle
        });
    }
});<commit_msg>Fixes goto line integration with status bar<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "c9", "settings", "ui", "menus", "ace",
        "ace.gotoline", "tabManager"
    ];
    main.provides = ["ace.status"];
    return main;

    function main(options, imports, register) {
        var c9        = imports.c9;
        var Plugin    = imports.Plugin;
        var settings  = imports.settings;
        var ui        = imports.ui;
        var tabs      = imports.tabManager;
        var menus     = imports.menus;
        var gotoline  = imports["ace.gotoline"];
        var aceHandle = imports.ace;

        var skin    = require("text!./skin.xml");
        var markup  = require("text!./statusbar.xml");
        var menuAml = require("text!./menu.xml");

        var aceWhitespace = require("ace/ext/whitespace");
        var lang = require("ace/lib/lang");

        /***** Generic Load *****/

        // Set up the generic handle
        var deps       = main.consumes.slice(0, main.consumes.length - 1);
        var handle     = new Plugin("Ajax.org", deps);
        var handleEmit = handle.getEmitter();

        var statusbars = {};
        var menuItem, menu, menuTabs;

        handle.on("load", function(){
            settings.on("read", function(e){
                settings.setDefaults("user/ace/statusbar", [["show", "true"]]);

                if (settings.getBool("user/ace/statusbar/@show"))
                    handleEmit("show");
            }, handle);

            menuItem = new apf.item({
                test : "1",
                type : "check",
                checked : "[{settings.model}::user/ace/statusbar/@show]"
                // -> if you're looking for disabled, check the init function :-)
                // the moment that someone clicks this thing well call preinit
                // (its already called if the user has it checked on IDE load)
            });

            menus.addItemByPath("View/Status Bar", menuItem, 600, handle);

            aceHandle.on("create", function(e){
                if (e.editor.type != "ace")
                    return;

                var editor = e.editor;
                var statusbar;

                editor.on("draw", function(){
                    statusbar = new Statusbar(editor);
                }, editor);
                editor.on("unload", function h2(){
                    if (statusbar) statusbar.unload();
                }, editor);
            });

            ui.insertMarkup(null, menuAml, handle);

            menu     = handle.getElement("menu");
            menuTabs = handle.getElement("menuTabs");

            var currentSession;
            function setCurrentSession(menu){
                var node = menu.opener;
                while (node && node.localName != "tab")
                    node = node.parentNode;
                if (!node) return;

                var tab = node.cloud9pane.getTab();
                currentSession = tab.document.getSession();
            }

            function setOption(name, value){
                if (currentSession) {
                    currentSession.session.setOption(name, value);
                    currentSession.statusBar.update();
                }
            }

            function getOption(name){
                return currentSession && currentSession.session.getOption(name);
            }

            // Checkboxes
            menu.on("afterrender", function(e){
                var itmSbWrap   = window.itmSbWrap;
                var itmSbWrapVP = window.itmSbWrapVP;

                itmSbWrap.on("click", function(){
                    setOption("wrap", itmSbWrap.checked
                        ? itmSbWrapVP.checked || "printMargin"
                        : false);
                });
                itmSbWrapVP.on("click", function(){
                    setOption("wrap", itmSbWrap.checked
                        ? itmSbWrapVP.checked || "printMargin"
                        : false);
                });

                function update(e){
                    if (!e || e.value){
                        setCurrentSession(menu);

                        var wrap = getOption("wrap");
                        itmSbWrap.setAttribute("checked", !ui.isFalse(wrap));
                        itmSbWrapVP.setAttribute("checked", wrap != "printMargin");
                    }
                }

                menu.on("prop.visible", update);
                update();
            });

            // Menu Tab functionality
            var handlers = [
                function(){ setOption("useSoftTabs", this.checked) },
                function(){},
                function(){ setOption("tabSize", 2) },
                function(){ setOption("tabSize", 3) },
                function(){ setOption("tabSize", 4) },
                function(){ setOption("tabSize", 8) },
                function(){
                    var tab = tabs.focussedTab;
                    if (!tab) return;
                    var session = tab.document.getSession();
                    aceWhitespace.detectIndentation(session.session);
                    var useSoftTabs = session.session.getOption("useSoftTabs");
                    var tabSize     = session.session.getOption("tabSize");
                    menuTabs.childNodes[0].setAttribute("checked", useSoftTabs);
                    if (tabSize < 9)
                        menuTabs.childNodes[tabSize + 1].setAttribute("selected", true);
                    session.statusBar.update();
                },
                // Tabs to Spaces
                function(){
                    var tab = tabs.focussedTab;
                    if (!tab) return;
                    var session = tab.document.getSession();
                    aceWhitespace.convertIndentation(session.session, " ");
                    session.statusBar.update();
                },
                // Spaces to Tabs
                function(){
                    var tab = tabs.focussedTab;
                    if (!tab) return;
                    var session = tab.document.getSession();
                    aceWhitespace.convertIndentation(session.session, "\t");
                    session.statusBar.update();
                }
            ];

            menuTabs.on("afterrender", function(e){
                var items = menuTabs.selectNodes("a:item");
                items.forEach(function(node, idx){
                    node.on("click", handlers[idx]);
                });

                var itmTabSize  = window.itmTabSize;
                itmTabSize.on("afterchange", function(){
                    setOption("tabSize", this.value);
                    update();
                });

                var lut = [0,0,2,3,4,0,0,0,5];

                function update(e){
                    if (e && !e.value)
                        return;

                    setCurrentSession(menuTabs);

                    items[0].setAttribute("checked", getOption("useSoftTabs"));

                    var tabSize = getOption("tabSize") || 1;
                    items.forEach(function(node, idx){
                        node.setAttribute("selected", "false");
                    });
                    if (lut[tabSize])
                        items[lut[tabSize]].setAttribute("selected", "true");
                    itmTabSize.setAttribute("value", getOption("tabSize"));
                }

                menuTabs.on("prop.visible", update);
                update();
            });
        });

        /***** Methods *****/

        var drawn = false;
        function draw(){
            if (drawn) return;
            drawn = true;

            // Import Skin
            ui.insertSkin({
                name         : "c9statusbar",
                data         : skin,
                "media-path" : options.staticPrefix + "/images/",
                "icon-path"  : options.staticPrefix + "/icons/"
            }, handle);
        };

        function getStatusbar(editor){
            return statusbars[editor.name];
        }

        function show(){
            settings.set("user/ace/statusbar/@show", "true");
        }

        function hide(){
            settings.set("user/ace/statusbar/@show", "false");
        }

        /***** Register and define API *****/

        /**
         * Manages the status bar instances for ace.
         * @singleton
         **/
        handle.freezePublicAPI({
            /**
             * Show all the status bars.
             */
            show : show,

            /**
             * Hide all the status bars.
             */
            hide : hide,

            /**
             * Retrieve the status bar that belongs to an ace editor.
             * @param {Editor} ace  The ace editor the status bar belongs to.
             * @return {ace.status.Statusbar}
             */
            getStatusbar : getStatusbar,

            /**
             * Inserts CSS for the statusbar.
             * @private
             */
            draw : draw
        });

        /***** Initialization *****/

        var counter = 0;

        function Statusbar(editor){
            var plugin = new Plugin("Ajax.org", deps);
            var emit   = plugin.getEmitter();

            var showRange;

            var bar, lblSelection, lblStatus, lblRowCol, lblTabs, lblSyntax; // ui elements

            statusbars[editor.name] = plugin;

            var loaded = false;
            function load(){
                if (loaded) return false;
                loaded = true;

                function updateBarVisible(){
                    if (!settings.getBool("user/ace/statusbar/@show")) {
                        bar && bar.hide();
                        menuItem.enable();
                    }
                    else {
                        draw();
                        bar.show();
                        menuItem.enable();
                    }
                }

                settings.on("user/ace/statusbar", updateBarVisible, plugin);

                handle.on("show", show);

                if (settings.getBool("user/ace/statusbar/@show"))
                    draw();

                editor.on("documentLoad", function(e){
                    var session = e.doc.getSession();
                    session.statusBar = plugin;
                    session.session.on("changeMode", function(e){ statusUpdate.schedule(); });
                }, plugin);
                editor.on("documentActivate", function(e){ statusUpdate.schedule(); }, plugin);
                editor.on("documentUnload", function(e){
                    delete e.doc.getSession().statusBar;
                }, plugin);
            }

            var drawn = false;
            function draw(){
                if (drawn) return;
                drawn = true;

                handle.draw();

                // Create UI elements
                var htmlNode = editor.ace.container.parentNode.host;
                ui.insertMarkup(htmlNode, markup, plugin);

                function setTheme(e){
                    var theme    = e.theme;
                    if (!theme) return;

                    var cssClass = theme.cssClass;
                    var isDark   = theme.isDark;

                    var bg = ui.getStyleRule("." + cssClass, "backgroundColor");

                    bar.setAttribute("class", isDark ? "ace_dark" : "");
                    if (bg) {
                        bg = bg.replace(/rgb\((.*)\)/, "rgba($1, 0.9)");
                        bar.$ext.style.backgroundColor = bg;
                    }
                }
                editor.on("themeChange", setTheme);

                bar          = plugin.getElement("bar");
                lblSelection = plugin.getElement("lblSelectionLength");
                lblStatus    = plugin.getElement("lblEditorStatus");
                lblRowCol    = plugin.getElement("lblRowCol");
                lblTabs      = plugin.getElement("lblTabs");
                lblSyntax    = plugin.getElement("lblSyntax");

                // For editor search of submenus
                bar.editor = editor;

                // Set sub menus
                var button = plugin.getElement("btnSbPrefs");
                button.setAttribute("submenu", menu);

                lblTabs.setAttribute("submenu", menuTabs);

                var mnuSyntax = menus.get("View/Syntax").menu;
                lblSyntax.setAttribute("submenu", mnuSyntax);
                lblSyntax.on("mousedown", function(){
                    if (editor.activeDocument)
                        tabs.focusTab(editor.activeDocument.tab);
                });

                // Click behavior for the labels
                lblSelection.on("click", function(){
                    showRange = !showRange;
                    updateStatus();
                });

                lblRowCol.on("click", function(){
                    gotoline.gotoline(null, null, true);
                });

                // Hook into ace
                var ace = editor.ace;
                if (!ace.$hasStatusBar) {
                    // Throttle UI updates
                    ace.on("changeSelection", function() { selStatusUpdate.schedule() });
                    ace.on("changeStatus", function() { statusUpdate.schedule() });
                    ace.renderer.on("scrollbarVisibilityChanged", function(e, renderer) {
                        bar.$ext.style.right = renderer.scrollBarV.getWidth() + 5 + "px";
                        bar.$ext.style.bottom = renderer.scrollBarH.getHeight() + 3 + "px";
                    });
                    ace.$hasStatusBar = true;

                    var theme = editor.theme;
                    setTheme({theme: theme});
                }

                // Update status information
                updateStatus();

                emit("draw");
            }

            var selStatusUpdate = lang.delayedCall(updateSelStatus, 10);
            var statusUpdate    = lang.delayedCall(updateStatus, 10);

            /***** Helper Functions *****/

            function updateSelStatus(){
                var ace = editor.ace;
                if (!ace) return;

                if (!ace.selection.isEmpty()) {
                    var range = ace.getSelectionRange();
                    var selLen;

                    if (showRange) {
                        selLen = "(" +
                            (range.end.row - range.start.row) + ":" +
                            (range.end.column - range.start.column) + ")";
                    }
                    else {
                        selLen = "(" + ace.session.getTextRange(range).length + " Bytes)";
                    }

                    lblSelection.setAttribute("caption", selLen);
                }
                else {
                    lblSelection.setAttribute("caption", "");
                }

                var cursor = ace.selection.lead;
                lblRowCol.setAttribute("caption", (cursor.row + 1) + ":" + (cursor.column + 1));
            }

            function updateStatus() {
                var ace = editor.ace;

                updateSelStatus();

                lblTabs.setAttribute("caption",
                    (ace.getOption("useSoftTabs") ? "Spaces" : "Tabs") + ": "
                      + ace.getOption("tabSize")); // "\\[" + + "\\]");

                var status = "";
                if (ace.$vimModeHandler)
                    status = ace.$vimModeHandler.getStatusText();
                else if (ace.commands.recording)
                    status = "REC";

                lblStatus.setAttribute("caption", status);

                var caption = aceHandle.getSyntaxCaption(ace.session.syntax);
                lblSyntax && lblSyntax.setAttribute("caption", caption);
            }

            /***** Lifecycle *****/

            plugin.on("load", function(){
                load();
            });
            plugin.on("enable", function(){

            });
            plugin.on("disable", function(){

            });
            plugin.on("unload", function(){
                loaded = false;
            });

            /***** Register and define API *****/

            /**
             * The status bar for ace editors.
             * @class ace.status.Statusbar
             **/
            plugin.freezePublicAPI({
                /**
                 * Redraw the display of the statusbar
                 */
                update : updateStatus
            });

            plugin.load("acestatus" + counter++);

            return plugin;
        }

        register(null, {
            "ace.status" : handle
        });
    }
});<|endoftext|>


<commit_before>/**
 * StopFlash
 *
 * https://github.com/JWhile/StopFlash
 *
 * stopflash.js
 */

// class StopFlashUI extends Builder
function StopFlashUI(elements)
{
    this.super('div');

    this.content = new StopFlashTabs()
        .className('content')
        .addTab(new Builder('div')
            .className('tab')
            .text('Home tab'))
        .addTab(new Builder('div')
            .className('tab')
            .text('Whitelist tab'))
        .addTab(new Builder('div')
            .className('tab')
            .text('Options tab'));

    var self = this;

    this.append(new Builder('div')
            .className('head')
            .append(new Builder('p')
                .className('logo')
                .html('STOP Flash'))
        .append(new Builder('div')
            .className('menu')
            .append(new Builder('a')
                .text('Home')
                .event('click', function()
                {
                    self.content.setTab(0);
                }))
            .append(new Builder('a')
                .text('Whitelist')
                .event('click', function()
                {
                    self.content.setTab(1);
                }))
            .append(new Builder('a')
                .text('Options')
                .event('click', function()
                {
                    self.content.setTab(2);
                })))
        .append(this.content)
        .append(new Builder('div')
            .className('foot')
            .html('https://github.com/JWhile/StopFlash'))
}
fus.extend(StopFlashUI, Builder);

// class StopFlashTabs extends Builder
function StopFlashTabs()
{
    this.super('div');

    this.tabs = []; // :Array<Builder>
}
// function addTab(Builder builder)@Chainable
StopFlashTabs.prototype.addTab = function(builder)
{
    this.tabs.push(new Builder('div')
        .className('tab')
        .css('left', (this.tabs.length * 300) +'px')
        .append(builder.className('tab-content'))
        .insert(this));

    if(this.tabs.length === 1)
    {
        this.setTab(0);
    }

    return this;
};
// function setTab(int index):void
StopFlashTabs.prototype.setTab = function(index)
{
    this.css('left', '-'+ (index * 300) +'px')
        .css('height', Builder.getStyle(this.tabs[index], 'height'));
};
fus.extend(StopFlashTabs, Builder);

// main
var main = function(elements)
{
    new StopFlashUI(elements)
        .insert(document.body);
};

chrome.tabs.query({'highlighted': true, 'currentWindow': true}, function(tabs)
{
    chrome.tabs.sendMessage(tabs[0].id, {'getElements': 'stopflash'}, main);
});
<commit_msg>Add icons in logo<commit_after>/**
 * StopFlash
 *
 * https://github.com/JWhile/StopFlash
 *
 * stopflash.js
 */

// class StopFlashUI extends Builder
function StopFlashUI(elements)
{
    this.super('div');

    this.content = new StopFlashTabs()
        .className('content')
        .addTab(new Builder('div')
            .className('tab')
            .text('Home tab'))
        .addTab(new Builder('div')
            .className('tab')
            .text('Whitelist tab'))
        .addTab(new Builder('div')
            .className('tab')
            .text('Options tab'));

    var self = this;

    this.append(new Builder('div')
            .className('head')
            .append(new Builder('p')
                .className('logo')
                .html('STP Flash'))
        .append(new Builder('div')
            .className('menu')
            .append(new Builder('a')
                .text('Home')
                .event('click', function()
                {
                    self.content.setTab(0);
                }))
            .append(new Builder('a')
                .text('Whitelist')
                .event('click', function()
                {
                    self.content.setTab(1);
                }))
            .append(new Builder('a')
                .text('Options')
                .event('click', function()
                {
                    self.content.setTab(2);
                })))
        .append(this.content)
        .append(new Builder('div')
            .className('foot')
            .html('https://github.com/JWhile/StopFlash'))
}
fus.extend(StopFlashUI, Builder);

// class StopFlashTabs extends Builder
function StopFlashTabs()
{
    this.super('div');

    this.tabs = []; // :Array<Builder>
}
// function addTab(Builder builder)@Chainable
StopFlashTabs.prototype.addTab = function(builder)
{
    this.tabs.push(new Builder('div')
        .className('tab')
        .css('left', (this.tabs.length * 300) +'px')
        .append(builder.className('tab-content'))
        .insert(this));

    if(this.tabs.length === 1)
    {
        this.setTab(0);
    }

    return this;
};
// function setTab(int index):void
StopFlashTabs.prototype.setTab = function(index)
{
    this.css('left', '-'+ (index * 300) +'px')
        .css('height', Builder.getStyle(this.tabs[index], 'height'));
};
fus.extend(StopFlashTabs, Builder);

// main
var main = function(elements)
{
    new StopFlashUI(elements)
        .insert(document.body);
};

chrome.tabs.query({'highlighted': true, 'currentWindow': true}, function(tabs)
{
    chrome.tabs.sendMessage(tabs[0].id, {'getElements': 'stopflash'}, main);
});
<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars */
import React from 'react'
import Revalidation from '../../src/'

const get = username => new Promise(res => {
  const existingNames = ['foo', 'bar', 'baz', 'foobarbaz']
  setTimeout(() =>
      res({
        data: {
          exists: existingNames.indexOf(username.toLowerCase().trim()) !== -1,
        },
      }),
    1000)
})

// we need to check if user name exists
const isUnusedUserName = (username) => get(username)
  .then(({ data }) => !data.exists)

const SubmitForm = ({
  revalidation: { form, updateValue, updateState, valid, asyncErrors, errors, validateAll, pending, debounce },
  onSubmit,
  }) => {
  return (
    <form onSubmit={(e) => { e.preventDefault(); validateAll(onSubmit) }}>

        ID
        <input
          type="text"
          value={form.name}
          onChange={debounce.name(updateValue, 1000)}
        />
        {errors.name && errors.name.map((errMsg, index) => (

          {errMsg}
))}
         {asyncErrors.name &&
{asyncErrors.name[0]}
}

valid? {valid.toString()}

pending? {pending.toString()}

valid? {valid.toString()}

errors? {JSON.stringify(errors, null ,4)}

asyncErrors? {JSON.stringify(asyncErrors, null ,4)}

      <button>Submit</button>

      <button onClick={() => updateState({ name: '', random: '' })}>Reset</button>
    </form>
  )
}

const EnhancedSubmitForm = Revalidation(SubmitForm)

class SubmitPage extends React.Component<any, any> {
  constructor(props) {
    super(props)
    this.state = {form: {name: ''}}
  }

  render() {
    const validationRules = {
      name: [
        [x =>  x && x.length >= 6, 'Minimum length of 6'],
      ],
    }

    const asyncValidationRules = {
      name: [
        [isUnusedUserName, name => `Username ${name} is not available`]
      ]
    }

    return (
      <EnhancedSubmitForm
        onSubmit={this.props.onSubmit}
        rules={validationRules}
        initialState={this.state.form}
        asyncRules={asyncValidationRules}
        userNameExists={this.usernameExists}
        validateSingle={true}
        instantValidation={true}
      />
    )
  }
}

export default SubmitPage
<commit_msg>Updated the async to work with the loading prop<commit_after>/* eslint-disable no-unused-vars */
import React from 'react'
import Revalidation from '../../src/'

const get = username => new Promise(res => {
  const existingNames = ['foo', 'bar', 'baz', 'foobarbaz']
  setTimeout(() =>
      res({
        data: {
          exists: existingNames.indexOf(username.toLowerCase().trim()) !== -1,
        },
      }),
    1000)
})

// we need to check if user name exists
const isUnusedUserName = (username) => get(username)
  .then(({ data }) => !data.exists)

const SubmitForm = ({
  revalidation: { form, updateValue, updateState, valid, asyncErrors, errors, validateAll, loading, debounce },
  onSubmit,
  }) => {
  return (
    <form onSubmit={(e) => { e.preventDefault(); validateAll(onSubmit) }}>

        ID
        <input
          type="text"
          value={form.name}
          onChange={debounce.name(updateValue, 1000)}
        />
        {errors.name && errors.name.map((errMsg, index) => (

          {errMsg}
))}
         {asyncErrors.name &&
{asyncErrors.name[0]}
}

valid? {valid.toString()}

loading? {loading.toString()}

valid? {valid.toString()}

errors? {JSON.stringify(errors, null ,4)}

asyncErrors? {JSON.stringify(asyncErrors, null ,4)}

      <button>Submit</button>

      <button onClick={() => updateState({ name: '', random: '' })}>Reset</button>
    </form>
  )
}

const EnhancedSubmitForm = Revalidation(SubmitForm)

class SubmitPage extends React.Component<any, any> {
  constructor(props) {
    super(props)
    this.state = {form: {name: ''}}
  }

  render() {
    const validationRules = {
      name: [
        [x =>  x && x.length >= 6, 'Minimum length of 6'],
      ],
    }

    const asyncValidationRules = {
      name: [
        [isUnusedUserName, name => `Username ${name} is not available`]
      ]
    }

    return (
      <EnhancedSubmitForm
        onSubmit={this.props.onSubmit}
        rules={validationRules}
        initialState={this.state.form}
        asyncRules={asyncValidationRules}
        userNameExists={this.usernameExists}
        validateSingle={true}
        instantValidation={true}
      />
    )
  }
}

export default SubmitPage
<|endoftext|>


<commit_before>(function ($) {
	var wrapper_class_suffix = "_wrapper",
		select_button_class = "drop_btn",
		options = {
			throw_error_if_no_matching_label:false,
			drop_btn: false, // if you set this to true, you'll get a nice div.
			drop_btn_char: '' // if you specify a char here, the div mentioned above willget a span with the supplied char inside. the only reason this gets specified here and not in the css is because it's not using the pseudo-element/content:''; combo
		};

	var methods  =  {

		fancy_factory: function(settings){
			if(this.tagName === 'INPUT' && this.type !== 'radio' && this.type !== 'checkbox'){
				return this; //if the current tag is an input of type != check||radio, just fail here silently and pass the element along for further jquery function chaining
			}

			if(!!settings){
				for (var prop in settings){
					if(options.hasOwnProperty(prop)){options[prop] = settings[prop]} //if the user has specified settings, override the private options object
				}
			}

			var tagname = this.tagName.toLowerCase(), //current tag type name
				$el = $(this), //jquery wrapped current el
				$wrapper=null, //jquery wrapper visible wrapper div-to-be
				wrap_class = tagname !== 'input' ? tagname + wrapper_class_suffix : this.type + wrapper_class_suffix; //build class name to include "select" or either the input elem's type

			$el.wrap('
'); //wrap the input/select in a fancy wrapper
			$wrapper = $($el.parent()); //set the wrapper ref

			switch(tagname){ //call correct handler
			case 'select':
				methods._handle_selects($el, $wrapper);
				break;
			case 'input':
				methods._handle_checks_and_radios($el, $wrapper);
				break;
			}
		},
		_handle_selects: function($el, $wrapper){
			var visible_markup = '' + $('option:selected', $el).text() + '',
				drop_btn = (function(){ // build the dropdown button markup string with this anonymous, immediate function
					var d;
					if(!!options.drop_btn){
						d =  '
';//if a drop button is desired, use a jQuery selector relative to the element in question to find the selected option
						if(!!options.drop_btn_char ){
							d += ('' + options.drop_btn_char + ''); //build markup for drop down button
						}
						d += '
';
					}
					return d;
				}());

			$wrapper
				.prepend(visible_markup) //prepend visible, stylable div tag to beginning of wrapper's insides
				.append(drop_btn) //append the dropbutton to the end of wrapper's insides (if it doesn't exist after computations above, this will fail silently)
				.change(function(e){$(' > span', $wrapper).text($('option:selected', $el).text());}); // when the select changes, this event bubbles up to the wrapper and sets its text to the selected option
			$el
				.focusin(function(){$wrapper.toggleClass('dropdown_input_selected');}) //when in focus, add fuax focus class to wrapper
				.focusout(function(){$wrapper.toggleClass('dropdown_input_selected');}) //remove
				.keyup(function(e){$('> span', $wrapper).text($('option:selected', $el).text());}); //firefox doesn't fire the change event on selects until they blur
		},
		_handle_checks_and_radios: function($el, $wrapper){
			var matching_label = $(' + label[for=' + $el.attr('id')+']', $wrapper); //first check for label directly proceeding wrapper (where it should be after the input was wrapped) with matching 'for' attribute

			if(matching_label.length === 0 || !matching_label){
				matching_label = $( 'label[for=' + $el.attr('id') + ']' ); //if above doesn't work, search the dom for it.
			}
			if(matching_label.length === 1){
				$wrapper.append(matching_label);
			}else if(options.throw_error_if_no_matching_label){
				throw new Error("could not find matching  for: input[type=" + el.attr('type') +']#' + el.attr('id') );
			}
			if(!methods._check_for_selector(':checked')){
				methods._checked_selector_not_supported($el);
			}

		},
		_check_for_selector: function (selector){ //this function will run a test to see if the browser's css capabilities include the given selector (only purpose here is to test :checked)
			$('body').append("<input id='selector_support_test' style='position:absolute;left:100%;top:-100%;visibility:hidden;' type='checkbox' checked />");
			var c = $('#selector_support_test'),
				before = c.css('width'),
				after = 0;
			$('body').append("");
			after = c.css('width');
			c.remove();
			$('#selector_style_test').remove();
			return before !== after;
		},
		_checked_selector_not_supported: function ($el){
			$el.change(function(e){
				if($el.attr('type') === 'checkbox'){ //toggle the checked class if it's a checkbox
					if($el.prop('checked')){
						$el.addClass('checked');
					}else{
						$el.removeClass('checked');
					}
				}else if($el.attr('type') === 'radio'){ //if it's a radio, remove the class from all radios in the radio group, then add it to the target radio
					var local_group = $('input[type=radio][name='+ $el.attr('name')+']');
					$(local_group).each(function(i, local_input){
						$(local_input).removeClass('checked');
					});
					$el.addClass('checked');
				}
				$('body').addClass('force_redraw').removeClass('force_redraw');
			});
		}
	};

	//I've altered the default cw pattern here slightly to restrict access to one method and accept only a settings object as an argument
	$.fn.fancify_inputs  =  function (settings) {
		if (typeof settings === 'object' || !settings) {
			var args = arguments;
			return $(this).map(function(i, val) { return methods.fancy_factory.apply(this, args); });
		}
	}

}(jQuery));<commit_msg>fixing option stickiness bug<commit_after>(function ($) {

	"use strict";

	var wrapper_class_suffix = "_wrapper",
		select_button_class = "drop_btn",
		options = {},
		default_options = {
			throw_error_if_no_matching_label:false,
			drop_btn: false, // if you set this to true, you'll get a nice div.
			drop_btn_char: '' // if you specify a char here, the div mentioned above willget a span with the supplied char inside. the only reason this gets specified here and not in the css is because it's not using the pseudo-element/content:''; combo
		};

	var methods  =  {

		fancy_factory: function(settings){
			if(this.tagName === 'INPUT' && this.type !== 'radio' && this.type !== 'checkbox'){
				return this; //if the current tag is an input of type != check||radio, just fail here silently and pass the element along for further jquery function chaining
			}

			options = {}; //reset options
			if(settings === {}){ //if there are no custom settings, use the default
				options = $.extend(options, default_options);
			}else{ // otherwise use the custom ones supplied
				options = $.extend(options, settings);
			}

			var tagname = this.tagName.toLowerCase(), //current tag type name
				$el = $(this), //jquery wrapped current el
				$wrapper=null, //jquery wrapper visible wrapper div-to-be
				wrap_class = tagname !== 'input' ? tagname + wrapper_class_suffix : this.type + wrapper_class_suffix; //build class name to include "select" or either the input elem's type

			$el.wrap('
'); //wrap the input/select in a fancy wrapper
			$wrapper = $($el.parent()); //set the wrapper ref

			switch(tagname){ //call correct handler
			case 'select':
				methods._handle_selects($el, $wrapper);
				break;
			case 'input':
				methods._handle_checks_and_radios($el, $wrapper);
				break;
			}
		},
		_handle_selects: function($el, $wrapper){
			var visible_markup = '' + $('option:selected', $el).text() + '',
				drop_btn = (function(){ // build the dropdown button markup string with this anonymous, immediate function
								var d;
								if(!!options.drop_btn){
									d =  '
';//if a drop button is desired, use a jQuery selector relative to the element in question to find the selected option
									if(!!options.drop_btn_char ){
										d += ('' + options.drop_btn_char + ''); //build markup for drop down button
									}
									d += '
';
								}
								return d;
							}());

			$wrapper
				.prepend(visible_markup) //prepend visible, stylable div tag to beginning of wrapper's insides
				.append(drop_btn) //append the dropbutton to the end of wrapper's insides (if it doesn't exist after computations above, this will fail silently)
				.change(function(e){$(' > span', $wrapper).text($('option:selected', $el).text());}); // when the select changes, this event bubbles up to the wrapper and sets its text to the selected option
			$el
				.focusin(function(){$wrapper.toggleClass('dropdown_input_selected');}) //when in focus, add fuax focus class to wrapper
				.focusout(function(){$wrapper.toggleClass('dropdown_input_selected');}) //remove
				.keyup(function(e){$('> span', $wrapper).text($('option:selected', $el).text());}); //firefox doesn't fire the change event on selects until they blur
		},
		_handle_checks_and_radios: function($el, $wrapper){
			var matching_label = $(' + label[for=' + $el.attr('id')+']', $wrapper); //first check for label directly proceeding wrapper (where it should be after the input was wrapped) with matching 'for' attribute

			if(matching_label.length === 0 || !matching_label){
				matching_label = $( 'label[for=' + $el.attr('id') + ']' ); //if above doesn't work, search the dom for it.
			}
			if(matching_label.length === 1){
				$wrapper.append(matching_label);
			}else if(options.throw_error_if_no_matching_label){
				throw new Error("could not find matching  for: input[type=" + el.attr('type') +']#' + el.attr('id') );
			}
			if(!methods._check_for_selector(':checked')){
				methods._checked_selector_not_supported($el);
			}

		},
		_check_for_selector: function (selector){ //this function will run a test to see if the browser's css capabilities include the given selector (only purpose here is to test :checked)
			$('body').append("<input id='selector_support_test' style='position:absolute;left:100%;top:-100%;visibility:hidden;' type='checkbox' checked />");
			var c = $('#selector_support_test'),
				before = c.css('width'),
				after = 0;
			$('body').append("");
			after = c.css('width');
			c.remove();
			$('#selector_style_test').remove();
			return before !== after;
		},
		_checked_selector_not_supported: function ($el){
			$el.change(function(e){
				if($el.attr('type') === 'checkbox'){ //toggle the checked class if it's a checkbox
					if($el.prop('checked')){
						$el.addClass('checked');
					}else{
						$el.removeClass('checked');
					}
				}else if($el.attr('type') === 'radio'){ //if it's a radio, remove the class from all radios in the radio group, then add it to the target radio
					var local_group = $('input[type=radio][name='+ $el.attr('name')+']');
					$(local_group).each(function(i, local_input){
						$(local_input).removeClass('checked');
					});
					$el.addClass('checked');
				}
				$('body').addClass('force_redraw').removeClass('force_redraw');
			});
		}
	};

	//I've altered the default cw pattern here slightly to restrict access to one method and accept only a settings object as an argument
	$.fn.fancify_inputs  =  function (settings) {
		if (typeof settings === 'object' || !settings) {
			var args = arguments;
			return $(this).map(function(i, val) { return methods.fancy_factory.apply(this, args); });
		}
	}

}(jQuery));<|endoftext|>


<commit_before>// NOTE: The contents of this file will only be executed if
// you uncomment its entry in "web/static/js/app.js".

// To use Phoenix channels, the first step is to import Socket
// and connect at the socket path in "lib/my_app/endpoint.ex":
import {Socket} from "phoenix"

let socket = new Socket("/socket", {params: {token: window.userToken}})

// When you connect, you'll often need to authenticate the client.
// For example, imagine you have an authentication plug, `MyAuth`,
// which authenticates the session and assigns a `:current_user`.
// If the current user exists you can assign the user's token in
// the connection for use in the layout.
//
// In your "web/router.ex":
//
//     pipeline :browser do
//       ...
//       plug MyAuth
//       plug :put_user_token
//     end
//
//     defp put_user_token(conn, _) do
//       if current_user = conn.assigns[:current_user] do
//         token = Phoenix.Token.sign(conn, "user socket", current_user.id)
//         assign(conn, :user_token, token)
//       else
//         conn
//       end
//     end
//
// Now you need to pass this token to JavaScript. You can do so
// inside a script tag in "web/templates/layout/app.html.eex":
//
//     <script>window.userToken = "<%%= assigns[:user_token] %>";</script>
//
// You will need to verify the user token in the "connect/2" function
// in "web/channels/user_socket.ex":
//
//     def connect(%{"token" => token}, socket) do
//       # max_age: 1209600 is equivalent to two weeks in seconds
//       case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
//         {:ok, user_id} ->
//           {:ok, assign(socket, :user, user_id)}
//         {:error, reason} ->
//           :error
//       end
//     end
//
// Finally, pass the token on connect as below. Or remove it
// from connect if you don't care about authentication.

socket.connect()

// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("topic:subtopic", {})
channel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) })

export default socket
<commit_msg>Update instructions for token authentication in comments (#2334)<commit_after>// NOTE: The contents of this file will only be executed if
// you uncomment its entry in "web/static/js/app.js".

// To use Phoenix channels, the first step is to import Socket
// and connect at the socket path in "lib/my_app/endpoint.ex":
import {Socket} from "phoenix"

let socket = new Socket("/socket", {params: {token: window.userToken}})

// When you connect, you'll often need to authenticate the client.
// For example, imagine you have an authentication plug, `MyAuth`,
// which authenticates the session and assigns a `:current_user`.
// If the current user exists you can assign the user's token in
// the connection for use in the layout.
//
// In your "web/router.ex":
//
//     pipeline :browser do
//       ...
//       plug MyAuth
//       plug :put_user_token
//     end
//
//     defp put_user_token(conn, _) do
//       if current_user = conn.assigns[:current_user] do
//         token = Phoenix.Token.sign(conn, "user socket", current_user.id)
//         assign(conn, :user_token, token)
//       else
//         conn
//       end
//     end
//
// Now you need to pass this token to JavaScript. You can do so
// inside a script tag in "web/templates/layout/app.html.eex":
//
//     <script>window.userToken = "<%%= assigns[:user_token] %>";</script>
//
// You will need to verify the user token in the "connect/2" function
// in "web/channels/user_socket.ex":
//
//     def connect(%{"token" => token}, socket) do
//       # max_age: 1209600 is equivalent to two weeks in seconds
//       case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
//         {:ok, user_id} ->
//           {:ok, assign(socket, :user, user_id)}
//         {:error, reason} ->
//           :error
//       end
//     end
//
// Finally, pass the token to the Socket constructor as above.
// Or, remove it from the constructor if you don't care about
// authentication.

socket.connect()

// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("topic:subtopic", {})
channel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) })

export default socket
<|endoftext|>


<commit_before>'use strict';

const express = require('express');
const passport = require('passport');
const path = require('path');

module.exports = function ({ app, userController, itemListingController, favoritesController, uploadController }) {
  const apiRouter = new express.Router();
  apiRouter
    .post('/upload', passport.authenticate('jwt'), uploadController.createFile)
    .get('/users', passport.authenticate('jwt'), userController.profile)
    .post('/users', passport.authenticate('local'), userController.login)
    .put('/users', userController.register)
    .get('/logout', passport.authenticate('jwt'), userController.logout)
    .get('/favorites', passport.authenticate('jwt'), favoritesController.index)
    .post('/favorites', passport.authenticate('jwt'), favoritesController.create)
    .put('/favorites', passport.authenticate('jwt'), favoritesController.remove)
    .get('/gallery', itemListingController.index)
    .get('/gallery/:id', itemListingController.details)
    .post('/gallery', passport.authenticate('jwt'), itemListingController.createListing)
    .post('/gallery/:id', passport.authenticate('jwt'), itemListingController.submitOfferForListing)
    .put('/gallery/:id', passport.authenticate('jwt'), itemListingController.updateListing)
    .put('/gallery/:id/comments', passport.authenticate('jwt'), itemListingController.addCommentToListing);

  app.use('/api', apiRouter);

  app
    .get('/', function (req, res) {
      res
        .status(200)
        .sendFile(path.join(__dirname, '/../../dist/index.html'));
    })
    .get('*', function (req, res) {
      res
        .status(200)
        .sendFile(path.join(__dirname, '/../../dist/index.html'));
    });
};<commit_msg>2 new server routes for statistics<commit_after>'use strict';

const express = require('express');
const passport = require('passport');
const path = require('path');

module.exports = function ({ app, userController, itemListingController, favoritesController, uploadController, statistcsController }) {
  const apiRouter = new express.Router();
  apiRouter
    .post('/upload', passport.authenticate('jwt'), uploadController.createFile)
    .get('/users', passport.authenticate('jwt'), userController.profile)
    .post('/users', passport.authenticate('local'), userController.login)
    .put('/users', userController.register)
    .get('/logout', passport.authenticate('jwt'), userController.logout)
    .get('/favorites', passport.authenticate('jwt'), favoritesController.index)
    .post('/favorites', passport.authenticate('jwt'), favoritesController.create)
    .put('/favorites', passport.authenticate('jwt'), favoritesController.remove)
    .get('/gallery', itemListingController.index)
    .get('/gallery/:id', itemListingController.details)
    .post('/gallery', passport.authenticate('jwt'), itemListingController.createListing)
    .post('/gallery/:id', passport.authenticate('jwt'), itemListingController.submitOfferForListing)
    .put('/gallery/:id', passport.authenticate('jwt'), itemListingController.updateListing)
    .put('/gallery/:id/comments', passport.authenticate('jwt'), itemListingController.addCommentToListing)
    .get('/statistics/users', statistcsController.getUsersStatistics)
    .get('/statistics/items', statistcsController.getUsersStatistics);

  app.use('/api', apiRouter);

  app
    .get('/', function (req, res) {
      res
        .status(200)
        .sendFile(path.join(__dirname, '/../../dist/index.html'));
    })
    .get('*', function (req, res) {
      res
        .status(200)
        .sendFile(path.join(__dirname, '/../../dist/index.html'));
    });
};<|endoftext|>