<commit_before>/**
* @file A7Init.js
* @brief Script d'initialisation de l'extension
*/

// Si la langue n'est pas anglais
if(location.search.search(new RegExp('&lang=1$')) === -1)
{
    // Remplacement des AJAX
    var xhrProto = XMLHttpRequest.prototype,
        sendOrig = xhrProto.send,
        origOpen = xhrProto.open;

    xhrProto.send = function()
    {
        /* Wrap onreadystaechange callback */
        var callback = this.onreadystatechange;
        this.onreadystatechange = function()
        {
             if (this.readyState == 4)
             {
                 if(this._url === '/ajax_list.php' + location.search + '&start=0&updated=false&slang=')
                 {
                     XMLHttpRequest.prototype = xhrProto;
                     return;
                 }
             }
             callback.apply(this, arguments);
        };

        sendOrig.apply(this, arguments);
    };

    // Ajoute l'url à l'objet AJAX
    xhrProto.open = function (method, url)
    {
        this._url = url;
        return origOpen.apply(this, arguments);
    };
}

// Déclare l'objet page et la liste des lignes
var page;

// Si la page est déjà chargée
if (document.readyState === 'interactive' || document.readyState === 'complete')
{
    // Demande la page avec complément anglais
    list(0, false, 1);

    // Initie l'extension
    init();
}
// Sinon, attend la fin du chargement de la page
else
{
    document.addEventListener('DOMContentLoaded', function() { init(); }, false);
}

/**
 * @fn init Initialise les différents composants
 */
function init()
{
    // Récupère l'élément contenant la liste
    var list = document.getElementById('lista');

    // Attend le chargement des séquences
    if (list.innerHTML === '' || list.innerHTML === ' ')
    {
        setTimeout(init, 250);
        return;
    }

    // Récupère la langue du site
    var lang = document.getElementById('comboLang'),
        choosen = lang ? lang.options[lang.selectedIndex].value : (navigator.language || navigator.userLanguage || 'en');
    // Ne garde que le nescessaire
    loc = loc[choosen] ? loc[choosen] : loc.en;

    // La page ne contient pas de lignes de traduction
    if (!document.getElementById('trseqtop'))
    {
        console.log('[A7++] ' + loc.noAvailableLine);
        return;
    }

    // Récupère les infos de la page
    var pageInfos = {};
    location.search.substr(1).split('&').forEach(function(item)
    {
        pageInfos[item.split('=')[0]] = item.split('=')[1];
    });

    // Initialise l'objet page
    page = {
        lock: (document.getElementById('locktop') !== null) ? 1 : 0,
        stateIntervalId: null,
        refreshCommentsTimeoutId: null,
        queryInfos: pageInfos,
        commentNumber: -1,
        tempDisablePopupRemoval: false
        };

    // Démarre l'actualisation de l'avancement (toutes les minutes)
    page.stateIntervalId = setInterval(updateStateOfTranslation, A7Settings.stateUpdateInterval * 1000);

    // Ajoute la structure d'accueil des commentaires
    var listaParent = list.parentElement;

    listaParent.insertBefore(createCommentStruct(), listaParent.lastElementChild);

    // Récupère la taille enregistrée, l'état de lock et l'état d'épinglement
    if(localStorage)
    {
        updateCommentHeightFromSaved(listaParent.lastElementChild.previousElementSibling, 'A7ppCommentWindowSize', 180, 0.8);
        if(localStorage.getItem('A7ppCommentWindowPined') === "true")
        {
            pinComments();
        }
        if(localStorage.getItem('A7ppCommentWindowLockedDown') === "true")
        {
            lockComment();
        }
    }

    // Initie la requête pour savoir si on est en HI
    requestHICheck();

    // Actualisation des commentaires (ce qui active aussi l'actualisation à intervalles réguliers)
    refreshComments();

    linesChanged();

    // Permet le changement de la langue d'affichage du site (bugfix du site)
    changeAppLang();

    // Vérifie les mises à jour
    searchForUpdate();
}
<commit_msg>First AJAX request is not send anymore and the original prototype is been well replaced<commit_after>/**
* @file A7Init.js
* @brief Script d'initialisation de l'extension
*/

// Si la langue n'est pas anglais
if(location.search.search(new RegExp('&lang=1$')) === -1)
{
    // Remplacement des AJAX
    var xhrProto = XMLHttpRequest.prototype,
        sendOrig = xhrProto.send,
        origOpen = xhrProto.open;

    xhrProto.send = function()
    {
        try
        {
            sendOrig.apply(this, arguments);
        }
        catch(err)
        {
            // Remet en place jes AJAX de base
            XMLHttpRequest.prototype.send = sendOrig;
            XMLHttpRequest.prototype.open = origOpen;
            XMLHttpRequest.prototype = xhrProto;
        }
    };

    // Ajoute l'url à l'objet AJAX
    xhrProto.open = function (method, url)
    {
        // Fait échouer la première requête
        if(url === '/ajax_list.php' + location.search + '&start=0&updated=false&slang=')
        {
            return;
        }

        return origOpen.apply(this, arguments);
    };
}

// Déclare l'objet page et la liste des lignes
var page;

// Si la page est déjà chargée
if (document.readyState === 'interactive' || document.readyState === 'complete')
{
    // Demande la page avec complément anglais
    list(0, false, 1);

    // Initie l'extension
    init();
}
// Sinon, attend la fin du chargement de la page
else
{
    document.addEventListener('DOMContentLoaded', function() { init(); }, false);
}

/**
 * @fn init Initialise les différents composants
 */
function init()
{
    // Récupère l'élément contenant la liste
    var list = document.getElementById('lista');

    // Attend le chargement des séquences
    if (list.innerHTML === '' || list.innerHTML === ' ')
    {
        setTimeout(init, 250);
        return;
    }

    // Récupère la langue du site
    var lang = document.getElementById('comboLang'),
        choosen = lang ? lang.options[lang.selectedIndex].value : (navigator.language || navigator.userLanguage || 'en');
    // Ne garde que le nescessaire
    loc = loc[choosen] ? loc[choosen] : loc.en;

    // La page ne contient pas de lignes de traduction
    if (!document.getElementById('trseqtop'))
    {
        console.log('[A7++] ' + loc.noAvailableLine);
        return;
    }

    // Récupère les infos de la page
    var pageInfos = {};
    location.search.substr(1).split('&').forEach(function(item)
    {
        pageInfos[item.split('=')[0]] = item.split('=')[1];
    });

    // Initialise l'objet page
    page = {
        lock: (document.getElementById('locktop') !== null) ? 1 : 0,
        stateIntervalId: null,
        refreshCommentsTimeoutId: null,
        queryInfos: pageInfos,
        commentNumber: -1,
        tempDisablePopupRemoval: false
        };

    // Démarre l'actualisation de l'avancement (toutes les minutes)
    page.stateIntervalId = setInterval(updateStateOfTranslation, A7Settings.stateUpdateInterval * 1000);

    // Ajoute la structure d'accueil des commentaires
    var listaParent = list.parentElement;

    listaParent.insertBefore(createCommentStruct(), listaParent.lastElementChild);

    // Récupère la taille enregistrée, l'état de lock et l'état d'épinglement
    if(localStorage)
    {
        updateCommentHeightFromSaved(listaParent.lastElementChild.previousElementSibling, 'A7ppCommentWindowSize', 180, 0.8);
        if(localStorage.getItem('A7ppCommentWindowPined') === "true")
        {
            pinComments();
        }
        if(localStorage.getItem('A7ppCommentWindowLockedDown') === "true")
        {
            lockComment();
        }
    }

    // Initie la requête pour savoir si on est en HI
    requestHICheck();

    // Actualisation des commentaires (ce qui active aussi l'actualisation à intervalles réguliers)
    refreshComments();

    linesChanged();

    // Permet le changement de la langue d'affichage du site (bugfix du site)
    changeAppLang();

    // Vérifie les mises à jour
    searchForUpdate();
}
<|endoftext|>


<commit_before>/*
JS for doing vetting
*/

var new_vet_vectors, wkt, new_vet_draw_polygon_control, new_vet_modify_polygon_control, new_vet_move_polyogn_control;
// buttons 100%..
// buttons text
// make button to drop in polygon..

function clearNewVettingMode(e) {
    console.log("Clearing current mode");

    new_vet_draw_polygon_control.deactivate();
    $('#newvet_draw_polygon_button').removeClass('button_down');

    new_vet_modify_polygon_control.deactivate();
    $('#newvet_modify_polygon_button').removeClass('button_down');

    new_vet_modify_polygon_control.deactivate();
    $('#newvet_modify_polygon_button').removeClass('button_down');
}

function handleDrawPolygonClick(e) {
    e.preventDefault();

    if ( $(e.srcElement).hasClass('button_down') ) {
        clearNewVettingMode();
    } else {
        clearNewVettingMode();
        $(e.srcElement).toggleClass('button_down');
        new_vet_draw_polygon_control.activate();
    }
    updateHint();
}

function handleModifyPolygonClick(e) {
    e.preventDefault();

    if ( $(e.srcElement).hasClass('button_down') ) {
        clearNewVettingMode();
    } else {
        clearNewVettingMode();
        $(e.srcElement).toggleClass('button_down');
        new_vet_modify_polygon_control.activate();
    }
    updateHint();
}

function handleClearPolygonClick(e) {
    e.preventDefault();

    clearNewVettingMode();

    new_vet_vectors.removeAllFeatures();

    updateHint();
}

// Sets the vetting hint to a random hint
function updateHint() {
    var drawPolygonHints = [
        ''
    ];
    var modifyPolygonHints = [
        '
Press Delete while over a vertice to delete it
'
    ];

    if (new_vet_modify_polygon_control.active) {
        var hint = modifyPolygonHints[Math.floor(Math.random()*modifyPolygonHints.length)]
        $('#vethint').html(hint);
    } else if (new_vet_draw_polygon_control) {
        var hint = drawPolygonHints[Math.floor(Math.random()*drawPolygonHints.length)]
        $('#vethint').html(hint);
    } else {
        $('#vethint').html('');
    }
}

function initVetting() {
    console.log("Starting to init vetting");

    // DecLat, DecLng
    var geographic_proj = new OpenLayers.Projection("EPSG:4326");

    var wkt_in_options = {
         'internalProjection': Edgar.map.baseLayer.projection,
         'externalProjection': geographic_proj
    };
    wkt = new OpenLayers.Format.WKT(wkt_in_options);

// NOTE: Due to OpenLayers Bug.. can't do this.
//       The modify feature control draws points onto the vector layer
//       to show vertice drag points.. these drag points fail the geometryType
//       test.
    var new_vet_vectors_options = {
//       'geometryType': OpenLayers.Geometry.Polygon
    };
    new_vet_vectors = new OpenLayers.Layer.Vector("New Vetting Layer", new_vet_vectors_options);

    new_vet_draw_polygon_control = new OpenLayers.Control.DrawFeature(
        new_vet_vectors,
        OpenLayers.Handler.Polygon
    );

    new_vet_modify_polygon_control = new OpenLayers.Control.ModifyFeature(new_vet_vectors);

    // Specify the modify mode as re-shape
    new_vet_modify_polygon_control.mode = OpenLayers.Control.ModifyFeature.RESHAPE;

    // handle draw polygon press
    $('#newvet_draw_polygon_button').click( function(e) {
        handleDrawPolygonClick(e);
    });

    // handle modify polygon press
    $('#newvet_modify_polygon_button').click( function(e) {
        handleModifyPolygonClick(e);
    });

    // handle clear polygon press
    $('#newvet_clear_polygon_button').click( function(e) {
    });

    Edgar.map.addLayers([new_vet_vectors]);
    Edgar.map.addControl(new_vet_draw_polygon_control)
    Edgar.map.addControl(new_vet_modify_polygon_control)

    console.log("Finished init vetting");
}

function createNewVetting() {
    console.log("Processing create new vetting");
    // Get features from the vector layer (which are all known to be polygons)
    var new_vet_polygon_features = new_vet_vectors.features;

    if (new_vet_polygon_features.length === 0) {
        alert("No polygons provided");
        return false;
    }

    // Now convert our array of features into an array of geometries.
    var new_vet_polygon_geoms = [];
    for (var i = 0; i < new_vet_polygon_features.length; i++) {
        var i_feature = new_vet_polygon_features[i];
        var i_geom = i_feature.geometry;
        new_vet_polygon_geoms.push(i_geom);
    }

    // Create a MultiPolygon from our polygons.
    var new_vet_multipolygon = new OpenLayers.Geometry.MultiPolygon(new_vet_polygon_geoms);
    console.log("WKT");
    console.log(new_vet_multipolygon);

    // Get WKT (well known text) for the multipolygon
    var layer_wkt_str = wkt.extractGeometry(new_vet_multipolygon);
    // At this point, we have our WKT
    console.log(layer_wkt_str);

    var species_id = Edgar.mapdata.species.id;
    var new_vet_data = {
        area: layer_wkt_str,
        species_id: species_id,
        comment: $("#vetcomment").val(),
        classification: $("#vetclassification").val()
    };

    // At this point, we have filled out our submit form
    console.log("Post Data:");
    console.log(new_vet_data);
    var vet_data_as_json_str = JSON.stringify(new_vet_data);
    console.log(vet_data_as_json_str);
    var url = Edgar.baseUrl + "species/insert_vetting/" + species_id + ".json";

    // Send the new vet to the back-end
    $.post(url, vet_data_as_json_str, function(data, text_status, jqXHR) {
        console.log("New Vet Response", data, text_status, jqXHR);
        alert("New Vet Response: " + data);
    }, 'json');

    return true;
}

$(function() {

    var vetpanel = $('#newvet');
    var vetform = $('#vetform');

    $('#vet_submit').click( function(e) {
        e.preventDefault();

        // Drop out of any editing mode.
        clearNewVettingMode();

        alert('Cylon says: Create New Vetting Pressed');

        // Submit the vetting
        createNewVetting();

    });

    initVetting();

});
<commit_msg>Added missing clear polygon click call.<commit_after>/*
JS for doing vetting
*/

var new_vet_vectors, wkt, new_vet_draw_polygon_control, new_vet_modify_polygon_control, new_vet_move_polyogn_control;
// buttons 100%..
// buttons text
// make button to drop in polygon..

function clearNewVettingMode(e) {
    console.log("Clearing current mode");

    new_vet_draw_polygon_control.deactivate();
    $('#newvet_draw_polygon_button').removeClass('button_down');

    new_vet_modify_polygon_control.deactivate();
    $('#newvet_modify_polygon_button').removeClass('button_down');

    new_vet_modify_polygon_control.deactivate();
    $('#newvet_modify_polygon_button').removeClass('button_down');
}

function handleDrawPolygonClick(e) {
    e.preventDefault();

    if ( $(e.srcElement).hasClass('button_down') ) {
        clearNewVettingMode();
    } else {
        clearNewVettingMode();
        $(e.srcElement).toggleClass('button_down');
        new_vet_draw_polygon_control.activate();
    }
    updateHint();
}

function handleModifyPolygonClick(e) {
    e.preventDefault();

    if ( $(e.srcElement).hasClass('button_down') ) {
        clearNewVettingMode();
    } else {
        clearNewVettingMode();
        $(e.srcElement).toggleClass('button_down');
        new_vet_modify_polygon_control.activate();
    }
    updateHint();
}

function handleClearPolygonClick(e) {
    e.preventDefault();

    clearNewVettingMode();

    new_vet_vectors.removeAllFeatures();

    updateHint();
}

// Sets the vetting hint to a random hint
function updateHint() {
    var drawPolygonHints = [
        ''
    ];
    var modifyPolygonHints = [
        '
Press Delete while over a vertice to delete it
'
    ];

    if (new_vet_modify_polygon_control.active) {
        var hint = modifyPolygonHints[Math.floor(Math.random()*modifyPolygonHints.length)]
        $('#vethint').html(hint);
    } else if (new_vet_draw_polygon_control) {
        var hint = drawPolygonHints[Math.floor(Math.random()*drawPolygonHints.length)]
        $('#vethint').html(hint);
    } else {
        $('#vethint').html('');
    }
}

function initVetting() {
    console.log("Starting to init vetting");

    // DecLat, DecLng
    var geographic_proj = new OpenLayers.Projection("EPSG:4326");

    var wkt_in_options = {
         'internalProjection': Edgar.map.baseLayer.projection,
         'externalProjection': geographic_proj
    };
    wkt = new OpenLayers.Format.WKT(wkt_in_options);

// NOTE: Due to OpenLayers Bug.. can't do this.
//       The modify feature control draws points onto the vector layer
//       to show vertice drag points.. these drag points fail the geometryType
//       test.
    var new_vet_vectors_options = {
//       'geometryType': OpenLayers.Geometry.Polygon
    };
    new_vet_vectors = new OpenLayers.Layer.Vector("New Vetting Layer", new_vet_vectors_options);

    new_vet_draw_polygon_control = new OpenLayers.Control.DrawFeature(
        new_vet_vectors,
        OpenLayers.Handler.Polygon
    );

    new_vet_modify_polygon_control = new OpenLayers.Control.ModifyFeature(new_vet_vectors);

    // Specify the modify mode as re-shape
    new_vet_modify_polygon_control.mode = OpenLayers.Control.ModifyFeature.RESHAPE;

    // handle draw polygon press
    $('#newvet_draw_polygon_button').click( function(e) {
        handleDrawPolygonClick(e);
    });

    // handle modify polygon press
    $('#newvet_modify_polygon_button').click( function(e) {
        handleModifyPolygonClick(e);
    });

    // handle clear polygon press
    $('#newvet_clear_polygon_button').click( function(e) {
        handleClearPolygonClick(e);
    });

    Edgar.map.addLayers([new_vet_vectors]);
    Edgar.map.addControl(new_vet_draw_polygon_control)
    Edgar.map.addControl(new_vet_modify_polygon_control)

    console.log("Finished init vetting");
}

function createNewVetting() {
    console.log("Processing create new vetting");
    // Get features from the vector layer (which are all known to be polygons)
    var new_vet_polygon_features = new_vet_vectors.features;

    if (new_vet_polygon_features.length === 0) {
        alert("No polygons provided");
        return false;
    }

    // Now convert our array of features into an array of geometries.
    var new_vet_polygon_geoms = [];
    for (var i = 0; i < new_vet_polygon_features.length; i++) {
        var i_feature = new_vet_polygon_features[i];
        var i_geom = i_feature.geometry;
        new_vet_polygon_geoms.push(i_geom);
    }

    // Create a MultiPolygon from our polygons.
    var new_vet_multipolygon = new OpenLayers.Geometry.MultiPolygon(new_vet_polygon_geoms);
    console.log("WKT");
    console.log(new_vet_multipolygon);

    // Get WKT (well known text) for the multipolygon
    var layer_wkt_str = wkt.extractGeometry(new_vet_multipolygon);
    // At this point, we have our WKT
    console.log(layer_wkt_str);

    var species_id = Edgar.mapdata.species.id;
    var new_vet_data = {
        area: layer_wkt_str,
        species_id: species_id,
        comment: $("#vetcomment").val(),
        classification: $("#vetclassification").val()
    };

    // At this point, we have filled out our submit form
    console.log("Post Data:");
    console.log(new_vet_data);
    var vet_data_as_json_str = JSON.stringify(new_vet_data);
    console.log(vet_data_as_json_str);
    var url = Edgar.baseUrl + "species/insert_vetting/" + species_id + ".json";

    // Send the new vet to the back-end
    $.post(url, vet_data_as_json_str, function(data, text_status, jqXHR) {
        console.log("New Vet Response", data, text_status, jqXHR);
        alert("New Vet Response: " + data);
    }, 'json');

    return true;
}

$(function() {

    var vetpanel = $('#newvet');
    var vetform = $('#vetform');

    $('#vet_submit').click( function(e) {
        e.preventDefault();

        // Drop out of any editing mode.
        clearNewVettingMode();

        alert('Cylon says: Create New Vetting Pressed');

        // Submit the vetting
        createNewVetting();

    });

    initVetting();

});
<|endoftext|>


<commit_before>/*
 *  DenonAVR.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-01-31
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use struct";

var iotdb = require('iotdb')
var _ = iotdb.helpers;
var net = require('net');

var mdns = require('mdns');

var bunyan = require('bunyan');
var logger = bunyan.createLogger({
    name: 'iotdb',
    module: 'DenonAVRBridge',
});

/**
 *  EXEMPLAR and INSTANCE
 *

 *  No subclassing needed! The following functions are
 *  injected _after_ this is created, and before .discover and .connect
 *

 *
discovered - tell IOTDB that we're talking to a new Thing
 *
pulled - got new data
 *
connected - this is connected to a Thing
 *
disconnnected - this has been disconnected from a Thing
 *

 */
var DenonAVRBridge = function(initd, native) {
    var self = this;

    self.initd = _.defaults(initd, {
        name: "Denon AVR",
        poll: 30,
        retry: 15,
        port: 23,
        host: null,
        mdns: true,
    });
    self.native = native;
    self.stated = {};
    self.max_volume = 98;
};

/* --- lifecycle --- */

/**
 *  EXEMPLAR.
 *  Discover one or more Things.
 *

 *
look for Things (using self.bridge data to initialize)
 *
find / create a paramd that does the talking
 *
create an DenonAVRBridge(paramd)
 *
call self.discovered(bridge) with it
 */
DenonAVRBridge.prototype.discover = function() {
    var self = this;

    if (self.initd.host) {
        self._discover_host(self.initd);
    } else if (self.initd.mdns) {
        var browser = mdns.createBrowser(mdns.tcp('http'));
        browser.on('serviceUp', function(service) {
            if (service.port !== 80) {
                return;
            } else if (!service.addresses) {
                return;
            } else if (service.addresses.length === 0) {
                return;
            }

            self._discover_host(_.defaults({
                host: service.addresses[0],
                name: service.name,
                probe: true,
            }, self.initd));
        });
        browser.start();
    }
};

/**
 *  INTERNAL EXEMPLAR
 *  Connect to a particular host
 */
DenonAVRBridge.prototype._discover_host = function(discoverd) {
    var self = this;
    var client = null;
    var is_discovered = false;
    var is_probed_and_discarded = false;
    var interval = null;

    var _destroy = function() {
        if (client) {
            client.removeListener('data', _on_data);
            client.removeListener('end', _on_end);
            client.removeListener('error', _on_error);
            client.destroy();
        }

        client = null;
        is_discovered = false;
    };

    var _not_a_denon = function() {
        logger.info({
            method: "_discover_host/_not_a_denon",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "not a Denon");

        is_probed_and_discarded = true;
        _destroy();

        if (interval) {
            clearInterval(interval);
            interval = null;
        }
    };

    var _on_connect = function() {
        logger.info({
            method: "_discover_host/_on_connect",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "connected - now checking MV command");

        client.write("MV?\r");
    };

    var _on_error = function(error) {
        logger.error({
            method: "_discover_host/_on_error",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
            error: error,
        }, "error");

        if (discoverd.probe && !is_discovered) {
            _not_a_denon();
        }

        _destroy();

    };

    var _on_data = function(data) {
        if (is_discovered) {
            return;
        }

        var data$ = data.toString();
        if (data$.indexOf('MV') === -1) {
            if (discoverd.probe) {
                _not_a_denon();
            }
            return;
        }

        logger.info({
            method: "_discover_host/_on_data",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "checks out - will use this device");

        var bridge = new DenonAVRBridge(discoverd, client);

        self.discovered(bridge);
        is_discovered = true;
    };

    var _on_end = function() {
        logger.info({
            method: "_discover_host/_on_end",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "client disconnected");

        client = null;
        is_discovered = false;
    };

    var _discover = function() {
        if (client) {
            if (is_discovered) {
                return;
            }

            logger.info({
                method: "_discover_host/_on_error",
                unique_id: self.unique_id,
                host: discoverd.host,
                port: discoverd.port,
            }, "throwing away a client that didn't return MV and will try again");

            self._destroy();
        }

        logger.info({
            method: "_discover_host/_discover",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "looking for Denon");

        client = net.connect(discoverd.port, discoverd.host, _on_connect);
        client.on('error', _on_error);
        client.on('data', _on_data);
        client.on('end', _on_end);
    };

    if (self.initd.retry > 0) {
        interval = setInterval(function() {
            _discover();
        }, self.initd.retry * 1000);
    }

    _discover();
};

/**
 *  INSTANCE
 *  Call when ready to be used as an instance
 */
DenonAVRBridge.prototype.connect = function() {
    var self = this;
    if (!self.native) {
        return;
    }

    self._setup_events();
    self._setup_polling();

    self.pull();
};

DenonAVRBridge.prototype._setup_events = function() {
    var self = this;

    var _on_data = function(data) {
        var parts = data.toString().split('\r');
        for (var pi in parts) {
            self._received(parts[pi]);
        }
    };

    var _on_error = function(error) {
        _disconnected();

        logger.info({
            method: "connect/_on_error",
            unique_id: self.unique_id,
            host: self.initd.host,
            port: self.initd.port,
            error: error,
        }, "called");
    };

    var _on_end = function() {
        _disconnected();

        logger.info({
            method: "connect/_on_end",
            unique_id: self.unique_id,
            host: self.initd.host,
            port: self.initd.port,
        }, "called");
    };

    var _disconnected = function() {
        if (!self.native) {
            return;
        }

        self.native.removeListener('data', self._on_data);
        self.native.removeListener('end', self._on_end);
        self.native.removeListener('error', self._on_error);
        self.native = null;

        // disconnection is a metadata change
        self.pulled();
    };

    self.native.on('data', _on_data);
    self.native.on('end', _on_end);
    self.native.on('error', _on_error);

};

DenonAVRBridge.prototype._setup_polling = function() {
    var self = this;
    if (!self.initd.poll) {
        return;
    }

    var timer = setInterval(function() {
        if (!self.native) {
            clearInterval(timer);
            return;
        }

        self.pull();
    }, self.initd.poll * 1000);
};

DenonAVRBridge.prototype._received = function(message) {
    var self = this;
    if (!message.length) {
        return;
    }

    message = message.replace(/^(SI|PW|DC|SV|MV(?=\d))/, "$1 ");
    var parts = message.split(" ", 2);
    var key = parts[0];
    var value = parts[1];

    if (key === "SI") {
        key = "band-value";
    } else if (key == "MV") {
        key = "volume-value";
        value = parseInt(value);
        if (value >= 100) {
            value = value / 10;
        }
        value = value / self.max_volume;
        value = Math.round(value * 1000);
        value = value / 1000.0;
    } else if (key == "PW") {
        key = "on-value";
        if (value === "ON") {
            value = true;
        } else {
            value = false;
        }
    } else if (key == "MVMAX") {
        self.max_volume = parseInt(value);
        return;
    } else {
        return;
    }

    if (self.stated[key] === value) {
        return;
    }

    self.stated[key] = value;
    self.pulled(self.stated);
};

/**
 *  INSTANCE and EXEMPLAR (during shutdown).
 *  This is called when the Bridge is no longer needed. When
 */
DenonAVRBridge.prototype.disconnect = function() {
    var self = this;
    if (!self.initd || !self.native) {
        return;
    }

    self.native = null;
    self.pulled();
};

/* --- data --- */

/**
 *  INSTANCE.
 *  Send data to whatever you're taking to.
 */
DenonAVRBridge.prototype.push = function(pushd) {
    var self = this;
    if (!self.native) {
        return;
    }

    if (pushd.volume !== undefined) {
        pushd.on = true;

        var volume = Math.min(Math.max(0, Math.round(pushd.volume * self.max_volume)), self.max_volume);
        if (volume < 10) {
            self.native.write("\rMV0" + volume + "\r");
        } else {
            self.native.write("\rMV" + volume + "\r");
        }
    }

    if (pushd.band !== undefined) {
        pushd.on = true;
        self.native.write("\rSI" + pushd.band.toUpperCase() + "\r");
    }

    if (pushd.on !== undefined) {
        if (pushd.on) {
            self.native.write("\rPWON\r");
        } else {
            self.native.write("\rPWSTANDBY\r");
        }
    }

    logger.info({
        method: "push",
        unique_id: self.unique_id,
        host: self.initd.host,
        port: self.initd.port,
        pushd: pushd,
    }, "pushed");
};

/**
 *  INSTANCE.
 *  Pull data from whatever we're talking to. You don't
 *  have to implement this if it doesn't make sense
 */
DenonAVRBridge.prototype.pull = function() {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "pull",
        unique_id: self.unique_id,
        host: self.initd.host,
        port: self.initd.port,
    }, "polling Denon AVR for current state");

    self.native.write("MV?\rSI?\rPW?\rMU?\n");
};

/* --- state --- */

/**
 *  INSTANCE.
 *  Return the metadata - compact form can be used.
 *

 *  Really really useful things are:
 *

 *
iot:thing required - a unique ID
 *
iot:device suggested if linking multiple things together
 *
iot:name
 *
iot:number
 *
schema:manufacturer
 *
schema:model
 */
DenonAVRBridge.prototype.meta = function() {
    var self = this;

    return {
        "iot:thing": _.id.thing_urn.network_unique("DenonAVR", self.initd.name || "DenonAVR"),
        "iot:name": self.initd.name || "DenonAVR",
        "schema:manufacturer": "http://www.denon.com/",
    };
};

/**
 *  INSTANCE.
 *  Return True if this is reachable. You
 *  do not need to worry about connect / disconnect /
 *  shutdown states, they will be always checked first.
 */
DenonAVRBridge.prototype.reachable = function() {
    return this.native !== null;
};

/**
 *  INSTANCE.
 *  Return True if this is configured. Things
 *  that are not configured are always not reachable.
 *  If not defined, "true" is returned
 */
DenonAVRBridge.prototype.configured = function() {
    return true;
};

/* --- injected: THIS CODE WILL BE REMOVED AT RUNTIME, DO NOT MODIFY  --- */
DenonAVRBridge.prototype.discovered = function(bridge) {
    throw new Error("DenonAVRBridge.discovered not implemented");
};

DenonAVRBridge.prototype.pulled = function(pulld) {
    throw new Error("DenonAVRBridge.pulled not implemented");
};

/*
 *  API
 */
exports.Bridge = DenonAVRBridge;
<commit_msg>add connect(conncted)<commit_after>/*
 *  DenonAVR.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-01-31
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use struct";

var iotdb = require('iotdb')
var _ = iotdb.helpers;
var net = require('net');

var mdns = require('mdns');

var bunyan = require('bunyan');
var logger = bunyan.createLogger({
    name: 'iotdb',
    module: 'DenonAVRBridge',
});

/**
 *  EXEMPLAR and INSTANCE
 *

 *  No subclassing needed! The following functions are
 *  injected _after_ this is created, and before .discover and .connect
 *

 *
discovered - tell IOTDB that we're talking to a new Thing
 *
pulled - got new data
 *
connected - this is connected to a Thing
 *
disconnnected - this has been disconnected from a Thing
 *

 */
var DenonAVRBridge = function(initd, native) {
    var self = this;

    self.initd = _.defaults(initd, {
        name: "Denon AVR",
        poll: 30,
        retry: 15,
        port: 23,
        host: null,
        mdns: true,
    });
    self.native = native;
    self.stated = {};
    self.max_volume = 98;
};

/* --- lifecycle --- */

/**
 *  EXEMPLAR.
 *  Discover one or more Things.
 *

 *
look for Things (using self.bridge data to initialize)
 *
find / create a paramd that does the talking
 *
create an DenonAVRBridge(paramd)
 *
call self.discovered(bridge) with it
 */
DenonAVRBridge.prototype.discover = function() {
    var self = this;

    if (self.initd.host) {
        self._discover_host(self.initd);
    } else if (self.initd.mdns) {
        var browser = mdns.createBrowser(mdns.tcp('http'));
        browser.on('serviceUp', function(service) {
            if (service.port !== 80) {
                return;
            } else if (!service.addresses) {
                return;
            } else if (service.addresses.length === 0) {
                return;
            }

            self._discover_host(_.defaults({
                host: service.addresses[0],
                name: service.name,
                probe: true,
            }, self.initd));
        });
        browser.start();
    }
};

/**
 *  INTERNAL EXEMPLAR
 *  Connect to a particular host
 */
DenonAVRBridge.prototype._discover_host = function(discoverd) {
    var self = this;
    var client = null;
    var is_discovered = false;
    var is_probed_and_discarded = false;
    var interval = null;

    var _destroy = function() {
        if (client) {
            client.removeListener('data', _on_data);
            client.removeListener('end', _on_end);
            client.removeListener('error', _on_error);
            client.destroy();
        }

        client = null;
        is_discovered = false;
    };

    var _not_a_denon = function() {
        logger.info({
            method: "_discover_host/_not_a_denon",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "not a Denon");

        is_probed_and_discarded = true;
        _destroy();

        if (interval) {
            clearInterval(interval);
            interval = null;
        }
    };

    var _on_connect = function() {
        logger.info({
            method: "_discover_host/_on_connect",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "connected - now checking MV command");

        client.write("MV?\r");
    };

    var _on_error = function(error) {
        logger.error({
            method: "_discover_host/_on_error",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
            error: error,
        }, "error");

        if (discoverd.probe && !is_discovered) {
            _not_a_denon();
        }

        _destroy();

    };

    var _on_data = function(data) {
        if (is_discovered) {
            return;
        }

        var data$ = data.toString();
        if (data$.indexOf('MV') === -1) {
            if (discoverd.probe) {
                _not_a_denon();
            }
            return;
        }

        logger.info({
            method: "_discover_host/_on_data",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "checks out - will use this device");

        var bridge = new DenonAVRBridge(discoverd, client);

        self.discovered(bridge);
        is_discovered = true;
    };

    var _on_end = function() {
        logger.info({
            method: "_discover_host/_on_end",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "client disconnected");

        client = null;
        is_discovered = false;
    };

    var _discover = function() {
        if (client) {
            if (is_discovered) {
                return;
            }

            logger.info({
                method: "_discover_host/_on_error",
                unique_id: self.unique_id,
                host: discoverd.host,
                port: discoverd.port,
            }, "throwing away a client that didn't return MV and will try again");

            self._destroy();
        }

        logger.info({
            method: "_discover_host/_discover",
            unique_id: self.unique_id,
            host: discoverd.host,
            port: discoverd.port,
        }, "looking for Denon");

        client = net.connect(discoverd.port, discoverd.host, _on_connect);
        client.on('error', _on_error);
        client.on('data', _on_data);
        client.on('end', _on_end);
    };

    if (self.initd.retry > 0) {
        interval = setInterval(function() {
            _discover();
        }, self.initd.retry * 1000);
    }

    _discover();
};

/**
 *  INSTANCE
 *  Call when ready to be used as an instance
 */
DenonAVRBridge.prototype.connect = function(connectd) {
    var self = this;
    if (!self.native) {
        return;
    }

    self._setup_events();
    self._setup_polling();

    self.pull();
};

DenonAVRBridge.prototype._setup_events = function() {
    var self = this;

    var _on_data = function(data) {
        var parts = data.toString().split('\r');
        for (var pi in parts) {
            self._received(parts[pi]);
        }
    };

    var _on_error = function(error) {
        _disconnected();

        logger.info({
            method: "connect/_on_error",
            unique_id: self.unique_id,
            host: self.initd.host,
            port: self.initd.port,
            error: error,
        }, "called");
    };

    var _on_end = function() {
        _disconnected();

        logger.info({
            method: "connect/_on_end",
            unique_id: self.unique_id,
            host: self.initd.host,
            port: self.initd.port,
        }, "called");
    };

    var _disconnected = function() {
        if (!self.native) {
            return;
        }

        self.native.removeListener('data', self._on_data);
        self.native.removeListener('end', self._on_end);
        self.native.removeListener('error', self._on_error);
        self.native = null;

        // disconnection is a metadata change
        self.pulled();
    };

    self.native.on('data', _on_data);
    self.native.on('end', _on_end);
    self.native.on('error', _on_error);

};

DenonAVRBridge.prototype._setup_polling = function() {
    var self = this;
    if (!self.initd.poll) {
        return;
    }

    var timer = setInterval(function() {
        if (!self.native) {
            clearInterval(timer);
            return;
        }

        self.pull();
    }, self.initd.poll * 1000);
};

DenonAVRBridge.prototype._received = function(message) {
    var self = this;
    if (!message.length) {
        return;
    }

    message = message.replace(/^(SI|PW|DC|SV|MV(?=\d))/, "$1 ");
    var parts = message.split(" ", 2);
    var key = parts[0];
    var value = parts[1];

    if (key === "SI") {
        key = "band-value";
    } else if (key == "MV") {
        key = "volume-value";
        value = parseInt(value);
        if (value >= 100) {
            value = value / 10;
        }
        value = value / self.max_volume;
        value = Math.round(value * 1000);
        value = value / 1000.0;
    } else if (key == "PW") {
        key = "on-value";
        if (value === "ON") {
            value = true;
        } else {
            value = false;
        }
    } else if (key == "MVMAX") {
        self.max_volume = parseInt(value);
        return;
    } else {
        return;
    }

    if (self.stated[key] === value) {
        return;
    }

    self.stated[key] = value;
    self.pulled(self.stated);
};

/**
 *  INSTANCE and EXEMPLAR (during shutdown).
 *  This is called when the Bridge is no longer needed. When
 */
DenonAVRBridge.prototype.disconnect = function() {
    var self = this;
    if (!self.initd || !self.native) {
        return;
    }

    self.native = null;
    self.pulled();
};

/* --- data --- */

/**
 *  INSTANCE.
 *  Send data to whatever you're taking to.
 */
DenonAVRBridge.prototype.push = function(pushd) {
    var self = this;
    if (!self.native) {
        return;
    }

    if (pushd.volume !== undefined) {
        pushd.on = true;

        var volume = Math.min(Math.max(0, Math.round(pushd.volume * self.max_volume)), self.max_volume);
        if (volume < 10) {
            self.native.write("\rMV0" + volume + "\r");
        } else {
            self.native.write("\rMV" + volume + "\r");
        }
    }

    if (pushd.band !== undefined) {
        pushd.on = true;
        self.native.write("\rSI" + pushd.band.toUpperCase() + "\r");
    }

    if (pushd.on !== undefined) {
        if (pushd.on) {
            self.native.write("\rPWON\r");
        } else {
            self.native.write("\rPWSTANDBY\r");
        }
    }

    logger.info({
        method: "push",
        unique_id: self.unique_id,
        host: self.initd.host,
        port: self.initd.port,
        pushd: pushd,
    }, "pushed");
};

/**
 *  INSTANCE.
 *  Pull data from whatever we're talking to. You don't
 *  have to implement this if it doesn't make sense
 */
DenonAVRBridge.prototype.pull = function() {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "pull",
        unique_id: self.unique_id,
        host: self.initd.host,
        port: self.initd.port,
    }, "polling Denon AVR for current state");

    self.native.write("MV?\rSI?\rPW?\rMU?\n");
};

/* --- state --- */

/**
 *  INSTANCE.
 *  Return the metadata - compact form can be used.
 *

 *  Really really useful things are:
 *

 *
iot:thing required - a unique ID
 *
iot:device suggested if linking multiple things together
 *
iot:name
 *
iot:number
 *
schema:manufacturer
 *
schema:model
 */
DenonAVRBridge.prototype.meta = function() {
    var self = this;

    return {
        "iot:thing": _.id.thing_urn.network_unique("DenonAVR", self.initd.name || "DenonAVR"),
        "iot:name": self.initd.name || "DenonAVR",
        "schema:manufacturer": "http://www.denon.com/",
    };
};

/**
 *  INSTANCE.
 *  Return True if this is reachable. You
 *  do not need to worry about connect / disconnect /
 *  shutdown states, they will be always checked first.
 */
DenonAVRBridge.prototype.reachable = function() {
    return this.native !== null;
};

/**
 *  INSTANCE.
 *  Return True if this is configured. Things
 *  that are not configured are always not reachable.
 *  If not defined, "true" is returned
 */
DenonAVRBridge.prototype.configured = function() {
    return true;
};

/* --- injected: THIS CODE WILL BE REMOVED AT RUNTIME, DO NOT MODIFY  --- */
DenonAVRBridge.prototype.discovered = function(bridge) {
    throw new Error("DenonAVRBridge.discovered not implemented");
};

DenonAVRBridge.prototype.pulled = function(pulld) {
    throw new Error("DenonAVRBridge.pulled not implemented");
};

/*
 *  API
 */
exports.Bridge = DenonAVRBridge;
<|endoftext|>


<commit_before>;(function($) {

    $.fn.overflow = function(opts) {

        var defaults = {
            limit: 150,
            counterFormat: '{{ count }} of {{ limit }}'
        };

        var options = $.extend(defaults, opts);

        return this.each(function() {
            $(this).after(generateCounter());

            bindEvents(this);
            checkCount(this);
        });

        function generateCounter()
        {
            return '';
        }

        function bindEvents(el)
        {
            $(el).bind('keyup', function() {
                checkCount(el);
            });

            $(el).bind('paste', function() {
                var self = this;
                setTimeout(function() {
                    checkCount(self);
                }, 0);
            });
        }

        function checkCount(el)
        {
            var $el = $(el);
            var $counter = $el.next('.overflowCounter');
            var count = countCharacters($el.val());

            if (count > options.limit) {
                $counter.addClass('overflowed');
            } else {
                $counter.removeClass('overflowed');
            }

            $counter.html(renderCounter(count, options.limit));
        }

        /**
         * Counts the number of characters in the given string. Line-breaks
         * are counted as two characters, as per the HTML spec.
         *
         * @param string val
         *
         * @return int
         */
        function countCharacters(val)
        {
            var linebreaks = val.match(/(\r\n|\n|\r)/g);
            var extras = linebreaks ? linebreaks.length : 0;

            return val.length + extras;
        }

        function renderCounter(count, limit)
        {
            return parseString(options.counterFormat, {
                count: count,
                limit: limit,
                remaining: limit - count
            });
        }

        function parseString(template, templateVars)
        {
            var val, needle;
            var haystack = template;

            for (var key in templateVars) {
                if ( ! templateVars.hasOwnProperty(key)) {
                    continue;
                }

                val = templateVars[key];
                needle = '{{ ' + key + ' }}';
                haystack = haystack.replace(needle, val);
            }

            return haystack;
        }
    };

})(jQuery);
<commit_msg>Add some docblocks.<commit_after>;(function($) {

    $.fn.overflow = function(opts) {

        var defaults = {
            limit: 150,
            counterFormat: '{{ count }} of {{ limit }}'
        };

        var options = $.extend(defaults, opts);

        return this.each(function() {
            $(this).after(generateCounter());

            bindEvents(this);
            checkCount(this);
        });

        function generateCounter()
        {
            return '';
        }

        function bindEvents(el)
        {
            $(el).bind('keyup', function() {
                checkCount(el);
            });

            $(el).bind('paste', function() {
                var self = this;
                setTimeout(function() {
                    checkCount(self);
                }, 0);
            });
        }

        /**
         * Update the counter.
         *
         * @param object el
         *
         * @return void
         */
        function checkCount(el)
        {
            var $el = $(el);
            var $counter = $el.next('.overflowCounter');
            var count = countCharacters($el.val());

            if (count > options.limit) {
                $counter.addClass('overflowed');
            } else {
                $counter.removeClass('overflowed');
            }

            $counter.html(renderCounter(count, options.limit));
        }

        /**
         * Counts the number of characters in the given string. Line-breaks
         * are counted as two characters, as per the HTML spec.
         *
         * @param string val
         *
         * @return int
         */
        function countCharacters(val)
        {
            var linebreaks = val.match(/(\r\n|\n|\r)/g);
            var extras = linebreaks ? linebreaks.length : 0;

            return val.length + extras;
        }

        /**
         * Generate the counter text.
         *
         * @param int count
         * @param int limit
         *
         * @return string
         */
        function renderCounter(count, limit)
        {
            return parseString(options.counterFormat, {
                count: count,
                limit: limit,
                remaining: limit - count
            });
        }

        /**
         * Replace template placeholders with the given template variables.
         *
         * @param string template
         * @param object templateVars
         *
         * @return string
         */
        function parseString(template, templateVars)
        {
            var val, needle;
            var haystack = template;

            for (var key in templateVars) {
                if ( ! templateVars.hasOwnProperty(key)) {
                    continue;
                }

                val = templateVars[key];
                needle = '{{ ' + key + ' }}';
                haystack = haystack.replace(needle, val);
            }

            return haystack;
        }
    };

})(jQuery);
<|endoftext|>


<commit_before>Package.describe({
  name: 'bojicas:bootstrap-alerts',
  summary: 'Display application alerts',
  version: '1.0.0',
  git: 'https://github.com/bojicas/bootstrap-alerts'
});

Package.onUse(function(api) {
  api.versionsFrom('1.0.2.1');

  api.use('mongo');
  api.use([
    'twbs:bootstrap',
    'templating'
  ], 'client');

  api.addFiles([
    'bojicas:bootstrap-alerts.css',
    'bojicas:bootstrap-alerts.html',
    'bojicas:bootstrap-alerts.js'
  ], 'client');

  if (api.export) {
    api.export('Alerts');
  }
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('bojicas:bootstrap-alerts');
  api.addFiles('bojicas:bootstrap-alerts-tests.js');
});
<commit_msg>Specify min version of bootstrap as dependency<commit_after>Package.describe({
  name: 'bojicas:bootstrap-alerts',
  summary: 'Display application alerts',
  version: '1.0.0',
  git: 'https://github.com/bojicas/bootstrap-alerts'
});

Package.onUse(function(api) {
  api.versionsFrom('1.0.2.1');

  api.use('mongo');
  api.use([
    'twbs:bootstrap@3.3.1_2',
    'templating'
  ], 'client');

  api.addFiles([
    'bojicas:bootstrap-alerts.css',
    'bojicas:bootstrap-alerts.html',
    'bojicas:bootstrap-alerts.js'
  ], 'client');

  if (api.export) {
    api.export('Alerts');
  }
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('bojicas:bootstrap-alerts');
  api.addFiles('bojicas:bootstrap-alerts-tests.js');
});
<|endoftext|>


<commit_before>(function() {
  var table = document.getElementById("itemTable").children[0];
  var goBtn = document.getElementById("go");

  var direction = ["Top","Right","Bottom","Left"];

  var itemNow = {
    item: getItem(5,5),
    Dir: 1,
    X: 5,
    Y: 5,
  }

  function getItem(x, y){
    return table.childNodes.item(y*2).childNodes.item(x*2+1);
  }

  function setDirection(item, D){
    item.className = D;
  }

  function itemSetter(item){
    setDirection(item, direction[itemNow.Dir]);
    setDirection(itemNow.item,"");
    itemNow.item = item;
  }

  function calDirection(x){
      var d = (itemNow.Dir + x >= 0 ? itemNow.Dir + x : 3) % 4;
      itemNow.Dir = d;
      setDirection(itemNow.item, direction[d]);
  }

  function itemGo(dir, action, color){
    switch(dir){
      case "Left":
        if(itemNow.X > 1) {
          var newX = itemNow.X - 1;
          var item = getItem(newX, itemNow.Y);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.X--;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal");
          }
        }
        break;
      case "Top":
        if(itemNow.Y > 1) {
          var newY = itemNow.Y - 1;
          var item = getItem(itemNow.X, newY);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.Y--;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal")
          }
        }
        break;
      case "Right":
        if(itemNow.X < 10){
          var newX = itemNow.X + 1;
          var item = getItem(newX, itemNow.Y);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.X++;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal")
          }
        }
        break;
      case "Bottom":
        if(itemNow.Y < 10){
          var newY = itemNow.Y + 1;
          var item = getItem(itemNow.X, newY);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.Y++;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal")
          }
        }
        break;
    }
  }

  function itemMove(inputs) {
    var cmd = inputs.toLocaleUpperCase();
    console.log(cmd);
    switch(cmd) {
      case "GO":
        itemGo(itemNow.item.className, "move");
        break;
      case "TUN LEF":
        calDirection(-1);
        break;
      case "TUN RIG":
        calDirection(1);
        break;
      case "TUN BAC":
        calDirection(2);
        break;
      case "TRA LEF":
        itemGo("Left", "move");
        break;
      case "TRA TOP":
        itemGo("Top", "move");
        break;
      case "TRA RIG":
        itemGo("Right", "move");
        break;
      case "TRA BOT":
        itemGo("Bottom", "move");
        break;
      case "MOV LEF":
        setDirection(itemNow.item,"Left");
        itemNow.Dir = 3;
        itemGo(itemNow.item.className, "move");
        break;
      case "MOV TOP":
        setDirection(itemNow.item,"Top");
        itemNow.Dir = 0;
        itemGo(itemNow.item.className, "move");
        break;
      case "MOV RIG":
        setDirection(itemNow.item,"Right");
        itemNow.Dir = 1;
        itemGo(itemNow.item.className, "move");
        break;
      case "MOV BOT":
        setDirection(itemNow.item,"Bottom");
        itemNow.Dir = 2;
        itemGo(itemNow.item.className, "move");
        break;
      case "BUILD":
        itemGo(itemNow.item.className, "build");
        break;
      default:
        if(/^BRU /.test(cmd)) {
          var color = cmd.split(" ")[1];
          if(checkColor(color)) {
            itemGo(itemNow.item.className, "bru", color);
          } else {
            console.log("Input color error");
          }
        } else if (/^MOV TO /.test(cmd)) {
          var toX = cmd.split(" ")[2].split(",")[0];
          var toY = cmd.split(" ")[2].split(",")[1];
          goPath(toX, toY);
        } else {
          console.log("Input error");
        }
    }
  }

  function checkColor(color)
  {
    var pattern = /^#[0-9a-fA-F]{6}$/
    if(color.match(pattern) == null) {
      return false;
    } else {
      return true;
    }
  }

  function goPath(toX, toY) {
    var arr = [];
    for(var m = 1 ; m <= 10; m++) {
      arr[m-1] = [];
      for(var n = 1 ; n <= 10; n++) {
        if(getItem(n, m).className == "Wall"){
          arr[m-1][n-1] = 1;
        } else {
          arr[m-1][n-1] = 0;
        }
      }
    }

    var map = Maze(arr);
    var parent = map.findPath(Point(itemNow.X, itemNow.Y), Point(toX, toY), false);
    if(parent) {
      var path = [];
      while (parent != null)
      {
        path.push(parent);
        parent = parent.parentPoint;
      }
      path.reverse();
      console.log(path);
    } else {
      console.log("Can not find a path");
    }
    delete map;
  }

  setDirection(itemNow.item, direction[itemNow.Dir]);

  var inputs = document.getElementById("cmd-area");
  var rstBtn = document.getElementById("reset");
  var rowId = document.getElementById("row-id");
  var randBtn = document.getElementById("rand");

  inputs.addEventListener('keyup', function() {
    rowHasChange();
  });

  inputs.addEventListener('scroll', function() {
    var top = inputs.scrollTop;
    rowId.scrollTop = top;
  })

  function random(min, max) {
    var range = max - min;
    var rand = Math.random();
    return(min + Math.round(rand*range))
  }

  function randomWall() {
    var randX = random(1,10);
    var randY = random(1,10);
    if(!((randX == itemNow.X)&&(randY == itemNow.Y))){
      if(getItem(randX, randY).className != "Wall") {
        getItem(randX, randY).className = "Wall";
      }
    } else {
      console.log("This position is hold by Item.")
    }
  }

  function rowHasChange() {
    var value = inputs.value;
    var rows = value.split("\n");
    var arr = [];
    var top = inputs.scrollTop;
    for (var i = 0; i < rows.length; i++) {
      arr.push("
" + (i + 1) + "
");
    }
    rowId.innerHTML = arr.join("");
    rowId.scrollTop = top;
  }

  rstBtn.addEventListener("click", function(){
    inputs.value="";
    rowId.innerHTML = ""
  })

  goBtn.addEventListener('click', cmdCheck);

  randBtn.addEventListener('click', randomWall);

  function cmdCheck() {
    var value = inputs.value;
    var arr = value.split("\n");
    var i = 1;
    command(arr[0], 0);
    var timer = setInterval(function(){
      if(i<arr.length){
        command(arr[i], i);
        ++i;
      } else {
        clearInterval(timer)
      }
    }, 1000)
  }

  function command(cmd, i) {
    var arr = cmd.split(" ");
    var steps = arr[arr.length-1];
    if(!isNaN(steps)){ //һλ
      arr.pop();
      var currentCmd = arr.join(" ");
    } else {
      var currentCmd = arr.join(" ");
      steps = 1;
    }

    var n = 0;
    var actions = setInterval(function() {
      if(n < steps) {
        itemMove(currentCmd);
        ++n;
      } else {
        clearInterval(actions);
      }
    }, 500)
  }
})()
<commit_msg>Add actions when find a path<commit_after>(function() {
  var table = document.getElementById("itemTable").children[0];
  var goBtn = document.getElementById("go");

  var direction = ["Top","Right","Bottom","Left"];

  var itemNow = {
    item: getItem(5,5),
    Dir: 1,
    X: 5,
    Y: 5,
  }

  function getItem(x, y){
    return table.childNodes.item(y*2).childNodes.item(x*2+1);
  }

  function setDirection(item, D){
    item.className = D;
  }

  function itemSetter(item){
    setDirection(item, direction[itemNow.Dir]);
    setDirection(itemNow.item,"");
    itemNow.item = item;
  }

  function calDirection(x){
      var d = (itemNow.Dir + x >= 0 ? itemNow.Dir + x : 3) % 4;
      itemNow.Dir = d;
      setDirection(itemNow.item, direction[d]);
  }

  function itemGo(dir, action, color){
    switch(dir){
      case "Left":
        if(itemNow.X > 1) {
          var newX = itemNow.X - 1;
          var item = getItem(newX, itemNow.Y);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.X--;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal");
          }
        }
        break;
      case "Top":
        if(itemNow.Y > 1) {
          var newY = itemNow.Y - 1;
          var item = getItem(itemNow.X, newY);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.Y--;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal")
          }
        }
        break;
      case "Right":
        if(itemNow.X < 10){
          var newX = itemNow.X + 1;
          var item = getItem(newX, itemNow.Y);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.X++;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal")
          }
        }
        break;
      case "Bottom":
        if(itemNow.Y < 10){
          var newY = itemNow.Y + 1;
          var item = getItem(itemNow.X, newY);
          if(action == "move") {
            if(item.className != "Wall") {
              itemNow.Y++;
              itemSetter(item);
            } else {
              console.log("Can not go through wall");
            }
          } else if (action == "build") {
            item.className = "Wall";
          } else if (action == "bru") {
            if(item.className == "Wall") {
              item.style.backgroundColor = color;
            } else {
              console.log("Not Wall");
            }
          } else {
            console.log("Action illegal")
          }
        }
        break;
    }
  }

  function itemMove(inputs) {
    var cmd = inputs.toLocaleUpperCase();
    console.log(cmd);
    switch(cmd) {
      case "GO":
        itemGo(itemNow.item.className, "move");
        break;
      case "TUN LEF":
        calDirection(-1);
        break;
      case "TUN RIG":
        calDirection(1);
        break;
      case "TUN BAC":
        calDirection(2);
        break;
      case "TRA LEF":
        itemGo("Left", "move");
        break;
      case "TRA TOP":
        itemGo("Top", "move");
        break;
      case "TRA RIG":
        itemGo("Right", "move");
        break;
      case "TRA BOT":
        itemGo("Bottom", "move");
        break;
      case "MOV LEF":
        setDirection(itemNow.item,"Left");
        itemNow.Dir = 3;
        itemGo(itemNow.item.className, "move");
        break;
      case "MOV TOP":
        setDirection(itemNow.item,"Top");
        itemNow.Dir = 0;
        itemGo(itemNow.item.className, "move");
        break;
      case "MOV RIG":
        setDirection(itemNow.item,"Right");
        itemNow.Dir = 1;
        itemGo(itemNow.item.className, "move");
        break;
      case "MOV BOT":
        setDirection(itemNow.item,"Bottom");
        itemNow.Dir = 2;
        itemGo(itemNow.item.className, "move");
        break;
      case "BUILD":
        itemGo(itemNow.item.className, "build");
        break;
      default:
        if(/^BRU /.test(cmd)) {
          var color = cmd.split(" ")[1];
          if(checkColor(color)) {
            itemGo(itemNow.item.className, "bru", color);
          } else {
            console.log("Input color error");
          }
        } else if (/^MOV TO /.test(cmd)) {
          var toX = cmd.split(" ")[2].split(",")[0];
          var toY = cmd.split(" ")[2].split(",")[1];
          goPath(toX, toY);
        } else {
          console.log("Input error");
        }
    }
  }

  function checkColor(color)
  {
    var pattern = /^#[0-9a-fA-F]{6}$/
    if(color.match(pattern) == null) {
      return false;
    } else {
      return true;
    }
  }

  function goPath(toX, toY) {
    var arr = [];
    for(var m = 1 ; m <= 10; m++) {
      arr[m-1] = [];
      for(var n = 1 ; n <= 10; n++) {
        if(getItem(n, m).className == "Wall"){
          arr[m-1][n-1] = 1;
        } else {
          arr[m-1][n-1] = 0;
        }
      }
    }

    var map = Maze(arr);
    var parent = map.findPath(Point(itemNow.X, itemNow.Y), Point(toX, toY), false);
    if(parent) {
      var path = [];
      while (parent != null)
      {
        path.push(parent);
        parent = parent.parentPoint;
      }
      path.reverse();

      var i = 1,
          len = path.length;
      var actions = setInterval(function() {
        if(i < len) {
          if(path[i].y == (itemNow.Y + 1)) {
            itemMove("MOV BOT");
          } else if(path[i].y == (itemNow.Y - 1)) {
            itemMove("MOV TOP");
          } else if(path[i].x == (itemNow.X + 1)) {
            itemMove("MOV RIG");
          } else if(path[i].x == (itemNow.X - 1)) {
            itemMove("MOV LEF");
          }
          ++i;
        } else {
          clearInterval(actions);
        }
      }, 500)
    } else {
      console.log("Can not find a path");
    }
    delete map;
  }

  setDirection(itemNow.item, direction[itemNow.Dir]);

  var inputs = document.getElementById("cmd-area");
  var rstBtn = document.getElementById("reset");
  var rowId = document.getElementById("row-id");
  var randBtn = document.getElementById("rand");

  inputs.addEventListener('keyup', function() {
    rowHasChange();
  });

  inputs.addEventListener('scroll', function() {
    var top = inputs.scrollTop;
    rowId.scrollTop = top;
  })

  function random(min, max) {
    var range = max - min;
    var rand = Math.random();
    return(min + Math.round(rand*range))
  }

  function randomWall() {
    var randX = random(1,10);
    var randY = random(1,10);
    if(!((randX == itemNow.X)&&(randY == itemNow.Y))){
      if(getItem(randX, randY).className != "Wall") {
        getItem(randX, randY).className = "Wall";
      }
    } else {
      console.log("This position is hold by Item.")
    }
  }

  function rowHasChange() {
    var value = inputs.value;
    var rows = value.split("\n");
    var arr = [];
    var top = inputs.scrollTop;
    for (var i = 0; i < rows.length; i++) {
      arr.push("
" + (i + 1) + "
");
    }
    rowId.innerHTML = arr.join("");
    rowId.scrollTop = top;
  }

  rstBtn.addEventListener("click", function(){
    inputs.value="";
    rowId.innerHTML = ""
  })

  goBtn.addEventListener('click', cmdCheck);

  randBtn.addEventListener('click', randomWall);

  function cmdCheck() {
    var value = inputs.value;
    var arr = value.split("\n");
    var i = 1;
    command(arr[0], 0);
    var timer = setInterval(function(){
      if(i<arr.length){
        command(arr[i], i);
        ++i;
      } else {
        clearInterval(timer)
      }
    }, 1000)
  }

  function command(cmd, i) {
    var arr = cmd.split(" ");
    var steps = arr[arr.length-1];
    if(!isNaN(steps)){ //最后一位是数字
      arr.pop();
      var currentCmd = arr.join(" ");
    } else {
      var currentCmd = arr.join(" ");
      steps = 1;
    }

    var n = 0;
    var actions = setInterval(function() {
      if(n < steps) {
        itemMove(currentCmd);
        ++n;
      } else {
        clearInterval(actions);
      }
    }, 500)
  }
})()
<|endoftext|>


<commit_before>'use strict';
var ko = require('knockout');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var Raven = require('raven-js');
var Markdown = require('pagedown-ace-converter');
Markdown.getSanitizingConverter = require('pagedown-ace-sanitizer').getSanitizingConverter;
require('imports?Markdown=pagedown-ace-converter!pagedown-ace-editor');

var waterbutler = require('js/waterbutler');

/**
 * Binding handler that instantiates an ACE editor.
 * The value accessor must be a ko.observable.
 * Example:

 */
var editor;
ko.bindingHandlers.ace = {
    init: function (element, valueAccessor) {
        editor = ace.edit(element.id);  // jshint ignore: line
        editor.renderer.setShowGutter(true);
        editor.renderer.setOption('showLineNumbers', true);

        editor.getPosition = function(x, y) {

            var config = editor.renderer.$markerFront.config;
            var height = config.lineHeight;
            var width = config.characterWidth;
            var row = Math.floor(y/height) < editor.session.getScreenLength() ? Math.floor(y/height) : editor.session.getScreenLength() - 1;
            var column = Math.floor(x/width) < editor.session.getScreenLastRowColumn(row) ? Math.floor(x/width) : editor.session.getScreenLastRowColumn(row);
            return {row: row, column: column}

        };
        // Updates the view model based on changes to the editor
        editor.getSession().on('change', function () {
            valueAccessor()(editor.getValue());
        });

        editor.marker = {};
        editor.marker.cursor = {};
        editor.marker.active = false;
        editor.marker.update = function(html, markerLayer, session, config) {
            var height = config.lineHeight;
            var width = config.characterWidth;
            var top = markerLayer.$getTop(this.cursor.row, config);
            var left = markerLayer.$padding + this.cursor.column * width;
            html.push(
                '

'
            );
        };

        editor.marker.redraw = function() {
            this.session._signal("changeFrontMarker");
        };

        element.addEventListener('dragenter', function(event) {
            event.preventDefault();
            event.stopPropagation();
        }, false);

        element.addEventListener('dragover', function(event) {
            event.preventDefault();
            event.stopPropagation();
            if (!editor.marker.active) {
                editor.marker.active = true;
                editor.marker.session = editor.session;
                editor.marker.session.addDynamicMarker(editor.marker, true);
            }
            editor.marker.cursor = editor.getPosition(event.offsetX, event.offsetY);
            editor.marker.redraw();
            var effect;
                try {
                  effect = event.dataTransfer.effectAllowed;
                } catch (_error) {}
                event.dataTransfer.dropEffect = 'move' === effect || 'linkMove' === effect ? 'move' : 'copy';
        }, false);

        element.addEventListener('drop', function(event) {
            event.preventDefault();
            event.stopPropagation();
            var re = /(?:\.([^.]+))?$/;
            var extensions = ['jpg', 'png', 'gif'];
            var ext;
            var position = editor.session.screenToDocumentPosition(editor.marker.cursor.row, editor.marker.cursor.column);
            var url = event.dataTransfer.getData('text/html');
            if (!!url) {
                var getImage = /(src=")(.*?)(")/;
                var imgURL = getImage.exec(url)[2];
                if (imgURL.substring(0,10) === 'data:image') {
                    imgURL = event.dataTransfer.getData('URL');
                    var exp = /(imgurl=)(.*?)(&)/;
                    imgURL = exp.exec(imgURL)[2];

                }
                else {
                    ext = re.exec(imgURL)[1];
                    if (extensions.indexOf(ext) <= -1) {
                        $osf.growl('Error', 'File type not supported', 'danger');
                        imgURL = undefined;
                    }
                }
                if (!!imgURL) {
                    var refOut = editor.marker.addLinkDef('[999]: ' + imgURL);
                    editor.session.insert(position, '![enter image description here][' + refOut + ']');
                }
            }
            else {
                var file = event.dataTransfer.files[0];
                ext = re.exec(file.name)[1];
                if (extensions.indexOf(ext) <= -1) {
                    $osf.growl('Error', 'File type not supported', 'danger');
                }
                else {
                    var waterbutler_url = waterbutler.buildUploadUrl('/', 'osfstorage', window.contextVars.node.id, file);
                    $.ajax({
                        url: waterbutler_url,
                        type: 'PUT',
                        processData: false,
                        contentType: false,
                        beforeSend: $osf.setXHRAuthorization,
                        data: file
                    }).done(function(data) {
                        url = window.contextVars.waterbutlerURL + 'v1/resources/' + window.contextVars.node.id + '/providers/' + data.provider + data.path + '?mode=render';
                        var refOut = editor.marker.addLinkDef('[999]: ' + url);
                        editor.session.insert(position, '![enter image description here][' + refOut + ']');
                    }).fail(function(data) {
                        $osf.growl('Error', 'File not uploaded. Please refresh the page and try ' +
                        'again or contact support@cos.io ' +
                        'if the problem persists.', 'danger');
                    });
                }
            }
            editor.marker.session.removeMarker(editor.marker.id);
            editor.marker.redraw();
            editor.marker.active = false;
        }, false);

        element.addEventListener('dragleave', function(event) {
            event.preventDefault();
            event.stopPropagation();
            editor.marker.session.removeMarker(editor.marker.id);
            editor.marker.redraw();
            editor.marker.active = false;
        });

        editor.marker.addLinkDef = function(linkDef) {
            var Range = ace.require('ace/range').Range;
            var before = editor.session.getTextRange(new Range(0, 0, this.cursor.row, this.cursor.column));
            var after = editor.session.getTextRange(new Range(this.cursor.row, this.cursor.column, Number.MAX_VALUE, Number.MAX_VALUE));
            var refNumber = 0; // The current reference number
            var defsToAdd = {}; //
            // Start with a clean slate by removing all previous link definitions.
            before = this.stripLinkDefs(before, defsToAdd);
            after = this.stripLinkDefs(after, defsToAdd);

            var defs = "";
            var regex = /(\[)((?:\[[^\]]*\]|[^\[\]])*)(\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;

            var addDefNumber = function (def) {
                refNumber++;
                def = def.replace(/^[ ]{0,3}\[(\d+)\]:/, "  [" + refNumber + "]:");
                defs += "\n" + def;
            };

            // note that
            // a) the recursive call to getLink cannot go infinite, because by definition
            //    of regex, inner is always a proper substring of wholeMatch, and
            // b) more than one level of nesting is neither supported by the regex
            //    nor making a lot of sense (the only use case for nesting is a linked image)
            var getLink = function (wholeMatch, before, inner, afterInner, id, end) {
                inner = inner.replace(regex, getLink);
                if (defsToAdd[id]) {
                    addDefNumber(defsToAdd[id]);
                    return before + inner + afterInner + refNumber + end;
                }
                return wholeMatch;
            };

            before = before.replace(regex, getLink);

            if (linkDef) {
                addDefNumber(linkDef);
                var refOut = refNumber;
            }

            after = after.replace(regex, getLink);

            if (after) {
                after = after.replace(/\n*$/, "");
            }

            after += "\n\n" + defs;

            editor.setValue(before + after);

            return refOut;
        };

        editor.marker.stripLinkDefs = function (text, defsToAdd) {

            text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,
                function (totalMatch, id, link, newlines, title) {
                    defsToAdd[id] = totalMatch.replace(/\s*$/, "");
                    if (newlines) {
                        // Strip the title and return that separately.
                        defsToAdd[id] = totalMatch.replace(/["(](.+?)[")]$/, "");
                        return newlines + title;
                    }
                    return "";
                });

            return text
        }
    },

    update: function (element, valueAccessor) {
        var content = editor.getValue();        // Content of ace editor
        var value = ko.unwrap(valueAccessor()); // Value from view model

        // Updates the editor based on changes to the view model
        if (value !== undefined && content !== value) {
            var cursorPosition = editor.getCursorPosition();
            editor.setValue(value);
            editor.gotoLine(cursorPosition.row + 1, cursorPosition.column);
        }
    }
};

function ViewModel(url, viewText) {
    var self = this;

    self.initText = ko.observable('');
    self.currentText = viewText; //from wikiPage's VM
    self.activeUsers = ko.observableArray([]);
    self.status = ko.observable('connecting');
    self.throttledStatus = ko.observable(self.status());

    self.displayCollaborators = ko.computed(function() {
       return self.activeUsers().length > 1;
    });

    // Throttle the display when updating status.
    self.updateStatus = function() {
        self.throttledStatus(self.status());
    };

    self.throttledUpdateStatus = $osf.throttle(self.updateStatus, 4000, {leading: false});

    self.status.subscribe(function (newValue) {
        if (newValue !== 'connecting') {
            self.updateStatus();
        }

        self.throttledUpdateStatus();
    });

    self.statusDisplay = ko.computed(function() {
        switch(self.throttledStatus()) {
            case 'connected':
                return 'Live editing mode';
            case 'connecting':
                return 'Attempting to connect';
            case 'unsupported':
                return 'Unsupported browser';
            default:
                return 'Unavailable: Live editing';
        }
    });

    self.progressBar = ko.computed(function() {
        switch(self.throttledStatus()) {
            case 'connected':
                return {
                    class: 'progress-bar progress-bar-success',
                    style: 'width: 100%'
                };

            case 'connecting':
                return {
                    class: 'progress-bar progress-bar-warning progress-bar-striped active',
                    style: 'width: 100%'
                };
            default:
                return {
                    class: 'progress-bar progress-bar-danger',
                    style: 'width: 100%'
                };
        }
    });

    self.modalTarget = ko.computed(function() {
        switch(self.throttledStatus()) {
            case 'connected':
                return '#connectedModal';
            case 'connecting':
                return '#connectingModal';
            case 'unsupported':
                return '#unsupportedModal';
            default:
                return '#disconnectedModal';
        }
    });

    self.wikisDiffer = function(wiki1, wiki2) {
        // Handle inconsistencies in newline notation
        var clean1 = typeof wiki1 === 'string' ?

            wiki1.replace(/(\r\n|\n|\r)/gm, '\n') : '';

var clean2 = typeof wiki2 === 'string' ?

            wiki2.replace(/(\r\n|\n|\r)/gm, '\n') : '';

        return clean1 !== clean2;
    };

    self.changed = function() {
        return self.wikisDiffer(self.initText(), self.currentText());
    };

    // Fetch initial wiki text
    self.fetchData = function() {
        var request = $.ajax({
            type: 'GET',
            url: url,
            dataType: 'json'
        });
        request.done(function (response) {
            // Most recent version, whether saved or in mongo
            self.initText(response.wiki_draft);
        });
        request.fail(function (xhr, textStatus, error) {
            $osf.growl('Error','The wiki content could not be loaded.');
            Raven.captureMessage('Could not GET wiki contents.', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
        return request;
    };

    // Revert to last saved version, even if draft is more recent
    self.revertChanges = function() {
        return self.fetchData().then(function(response) {
            // Dirty check now covers last saved version
            self.initText(response.wiki_content);
            self.currentText(response.wiki_content);
        });
    };

    $(window).on('beforeunload', function() {
        if (self.changed() && self.status() !== 'connected') {
            return 'There are unsaved changes to your wiki. If you exit ' +
                'the page now, those changes may be lost.';
        }
    });

}

function WikiEditor(url, viewText, editor) {
    this.viewModel = new ViewModel(url, viewText);
    var mdConverter = Markdown.getSanitizingConverter();
    var mdEditor = new Markdown.Editor(mdConverter);
    mdEditor.run(editor);

}

module.exports = WikiEditor;
<commit_msg>Added .bmp support<commit_after>'use strict';
var ko = require('knockout');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var Raven = require('raven-js');
var Markdown = require('pagedown-ace-converter');
Markdown.getSanitizingConverter = require('pagedown-ace-sanitizer').getSanitizingConverter;
require('imports?Markdown=pagedown-ace-converter!pagedown-ace-editor');

var waterbutler = require('js/waterbutler');

/**
 * Binding handler that instantiates an ACE editor.
 * The value accessor must be a ko.observable.
 * Example:

 */
var editor;
ko.bindingHandlers.ace = {
    init: function (element, valueAccessor) {
        editor = ace.edit(element.id);  // jshint ignore: line
        editor.renderer.setShowGutter(true);
        editor.renderer.setOption('showLineNumbers', true);

        editor.getPosition = function(x, y) {

            var config = editor.renderer.$markerFront.config;
            var height = config.lineHeight;
            var width = config.characterWidth;
            var row = Math.floor(y/height) < editor.session.getScreenLength() ? Math.floor(y/height) : editor.session.getScreenLength() - 1;
            var column = Math.floor(x/width) < editor.session.getScreenLastRowColumn(row) ? Math.floor(x/width) : editor.session.getScreenLastRowColumn(row);
            return {row: row, column: column}

        };
        // Updates the view model based on changes to the editor
        editor.getSession().on('change', function () {
            valueAccessor()(editor.getValue());
        });

        editor.marker = {};
        editor.marker.cursor = {};
        editor.marker.active = false;
        editor.marker.update = function(html, markerLayer, session, config) {
            var height = config.lineHeight;
            var width = config.characterWidth;
            var top = markerLayer.$getTop(this.cursor.row, config);
            var left = markerLayer.$padding + this.cursor.column * width;
            html.push(
                '

'
            );
        };

        editor.marker.redraw = function() {
            this.session._signal("changeFrontMarker");
        };

        element.addEventListener('dragenter', function(event) {
            event.preventDefault();
            event.stopPropagation();
        }, false);

        element.addEventListener('dragover', function(event) {
            event.preventDefault();
            event.stopPropagation();
            if (!editor.marker.active) {
                editor.marker.active = true;
                editor.marker.session = editor.session;
                editor.marker.session.addDynamicMarker(editor.marker, true);
            }
            editor.marker.cursor = editor.getPosition(event.offsetX, event.offsetY);
            editor.marker.redraw();
            var effect;
                try {
                  effect = event.dataTransfer.effectAllowed;
                } catch (_error) {}
                event.dataTransfer.dropEffect = 'move' === effect || 'linkMove' === effect ? 'move' : 'copy';
        }, false);

        element.addEventListener('drop', function(event) {
            event.preventDefault();
            event.stopPropagation();
            var re = /(?:\.([^.]+))?$/;
            var extensions = ['jpg', 'png', 'gif', 'bmp'];
            var ext;
            var position = editor.session.screenToDocumentPosition(editor.marker.cursor.row, editor.marker.cursor.column);
            var url = event.dataTransfer.getData('text/html');
            if (!!url) {
                var getImage = /(src=")(.*?)(")/;
                var imgURL = getImage.exec(url)[2];
                if (imgURL.substring(0,10) === 'data:image') {
                    imgURL = event.dataTransfer.getData('URL');
                    var exp = /(imgurl=)(.*?)(&)/;
                    imgURL = exp.exec(imgURL)[2];

                }
                else {
                    ext = re.exec(imgURL)[1];
                    if (extensions.indexOf(ext) <= -1) {
                        $osf.growl('Error', 'File type not supported', 'danger');
                        imgURL = undefined;
                    }
                }
                if (!!imgURL) {
                    var refOut = editor.marker.addLinkDef('[999]: ' + imgURL);
                    editor.session.insert(position, '![enter image description here][' + refOut + ']');
                }
            }
            else {
                var file = event.dataTransfer.files[0];
                ext = re.exec(file.name)[1];
                if (extensions.indexOf(ext) <= -1) {
                    $osf.growl('Error', 'File type not supported', 'danger');
                }
                else {
                    var waterbutler_url = waterbutler.buildUploadUrl('/', 'osfstorage', window.contextVars.node.id, file);
                    $.ajax({
                        url: waterbutler_url,
                        type: 'PUT',
                        processData: false,
                        contentType: false,
                        beforeSend: $osf.setXHRAuthorization,
                        data: file
                    }).done(function(data) {
                        url = window.contextVars.waterbutlerURL + 'v1/resources/' + window.contextVars.node.id + '/providers/' + data.provider + data.path + '?mode=render';
                        var refOut = editor.marker.addLinkDef('[999]: ' + url);
                        editor.session.insert(position, '![enter image description here][' + refOut + ']');
                    }).fail(function(data) {
                        $osf.growl('Error', 'File not uploaded. Please refresh the page and try ' +
                        'again or contact support@cos.io ' +
                        'if the problem persists.', 'danger');
                    });
                }
            }
            editor.marker.session.removeMarker(editor.marker.id);
            editor.marker.redraw();
            editor.marker.active = false;
        }, false);

        element.addEventListener('dragleave', function(event) {
            event.preventDefault();
            event.stopPropagation();
            editor.marker.session.removeMarker(editor.marker.id);
            editor.marker.redraw();
            editor.marker.active = false;
        });

        editor.marker.addLinkDef = function(linkDef) {
            var Range = ace.require('ace/range').Range;
            var before = editor.session.getTextRange(new Range(0, 0, this.cursor.row, this.cursor.column));
            var after = editor.session.getTextRange(new Range(this.cursor.row, this.cursor.column, Number.MAX_VALUE, Number.MAX_VALUE));
            var refNumber = 0; // The current reference number
            var defsToAdd = {}; //
            // Start with a clean slate by removing all previous link definitions.
            before = this.stripLinkDefs(before, defsToAdd);
            after = this.stripLinkDefs(after, defsToAdd);

            var defs = "";
            var regex = /(\[)((?:\[[^\]]*\]|[^\[\]])*)(\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;

            var addDefNumber = function (def) {
                refNumber++;
                def = def.replace(/^[ ]{0,3}\[(\d+)\]:/, "  [" + refNumber + "]:");
                defs += "\n" + def;
            };

            // note that
            // a) the recursive call to getLink cannot go infinite, because by definition
            //    of regex, inner is always a proper substring of wholeMatch, and
            // b) more than one level of nesting is neither supported by the regex
            //    nor making a lot of sense (the only use case for nesting is a linked image)
            var getLink = function (wholeMatch, before, inner, afterInner, id, end) {
                inner = inner.replace(regex, getLink);
                if (defsToAdd[id]) {
                    addDefNumber(defsToAdd[id]);
                    return before + inner + afterInner + refNumber + end;
                }
                return wholeMatch;
            };

            before = before.replace(regex, getLink);

            if (linkDef) {
                addDefNumber(linkDef);
                var refOut = refNumber;
            }

            after = after.replace(regex, getLink);

            if (after) {
                after = after.replace(/\n*$/, "");
            }

            after += "\n\n" + defs;

            editor.setValue(before + after);

            return refOut;
        };

        editor.marker.stripLinkDefs = function (text, defsToAdd) {

            text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,
                function (totalMatch, id, link, newlines, title) {
                    defsToAdd[id] = totalMatch.replace(/\s*$/, "");
                    if (newlines) {
                        // Strip the title and return that separately.
                        defsToAdd[id] = totalMatch.replace(/["(](.+?)[")]$/, "");
                        return newlines + title;
                    }
                    return "";
                });

            return text
        }
    },

    update: function (element, valueAccessor) {
        var content = editor.getValue();        // Content of ace editor
        var value = ko.unwrap(valueAccessor()); // Value from view model

        // Updates the editor based on changes to the view model
        if (value !== undefined && content !== value) {
            var cursorPosition = editor.getCursorPosition();
            editor.setValue(value);
            editor.gotoLine(cursorPosition.row + 1, cursorPosition.column);
        }
    }
};

function ViewModel(url, viewText) {
    var self = this;

    self.initText = ko.observable('');
    self.currentText = viewText; //from wikiPage's VM
    self.activeUsers = ko.observableArray([]);
    self.status = ko.observable('connecting');
    self.throttledStatus = ko.observable(self.status());

    self.displayCollaborators = ko.computed(function() {
       return self.activeUsers().length > 1;
    });

    // Throttle the display when updating status.
    self.updateStatus = function() {
        self.throttledStatus(self.status());
    };

    self.throttledUpdateStatus = $osf.throttle(self.updateStatus, 4000, {leading: false});

    self.status.subscribe(function (newValue) {
        if (newValue !== 'connecting') {
            self.updateStatus();
        }

        self.throttledUpdateStatus();
    });

    self.statusDisplay = ko.computed(function() {
        switch(self.throttledStatus()) {
            case 'connected':
                return 'Live editing mode';
            case 'connecting':
                return 'Attempting to connect';
            case 'unsupported':
                return 'Unsupported browser';
            default:
                return 'Unavailable: Live editing';
        }
    });

    self.progressBar = ko.computed(function() {
        switch(self.throttledStatus()) {
            case 'connected':
                return {
                    class: 'progress-bar progress-bar-success',
                    style: 'width: 100%'
                };

            case 'connecting':
                return {
                    class: 'progress-bar progress-bar-warning progress-bar-striped active',
                    style: 'width: 100%'
                };
            default:
                return {
                    class: 'progress-bar progress-bar-danger',
                    style: 'width: 100%'
                };
        }
    });

    self.modalTarget = ko.computed(function() {
        switch(self.throttledStatus()) {
            case 'connected':
                return '#connectedModal';
            case 'connecting':
                return '#connectingModal';
            case 'unsupported':
                return '#unsupportedModal';
            default:
                return '#disconnectedModal';
        }
    });

    self.wikisDiffer = function(wiki1, wiki2) {
        // Handle inconsistencies in newline notation
        var clean1 = typeof wiki1 === 'string' ?

            wiki1.replace(/(\r\n|\n|\r)/gm, '\n') : '';

var clean2 = typeof wiki2 === 'string' ?

            wiki2.replace(/(\r\n|\n|\r)/gm, '\n') : '';

        return clean1 !== clean2;
    };

    self.changed = function() {
        return self.wikisDiffer(self.initText(), self.currentText());
    };

    // Fetch initial wiki text
    self.fetchData = function() {
        var request = $.ajax({
            type: 'GET',
            url: url,
            dataType: 'json'
        });
        request.done(function (response) {
            // Most recent version, whether saved or in mongo
            self.initText(response.wiki_draft);
        });
        request.fail(function (xhr, textStatus, error) {
            $osf.growl('Error','The wiki content could not be loaded.');
            Raven.captureMessage('Could not GET wiki contents.', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
        return request;
    };

    // Revert to last saved version, even if draft is more recent
    self.revertChanges = function() {
        return self.fetchData().then(function(response) {
            // Dirty check now covers last saved version
            self.initText(response.wiki_content);
            self.currentText(response.wiki_content);
        });
    };

    $(window).on('beforeunload', function() {
        if (self.changed() && self.status() !== 'connected') {
            return 'There are unsaved changes to your wiki. If you exit ' +
                'the page now, those changes may be lost.';
        }
    });

}

function WikiEditor(url, viewText, editor) {
    this.viewModel = new ViewModel(url, viewText);
    var mdConverter = Markdown.getSanitizingConverter();
    var mdEditor = new Markdown.Editor(mdConverter);
    mdEditor.run(editor);

}

module.exports = WikiEditor;
<|endoftext|>


<commit_before>'use strict';

var $ = require('../gulp.config.js');
var gulp = require('gulp');
var angularFilesort = require('gulp-angular-filesort');
var concat = require('gulp-concat');

/**
 * Optimize angular files
 * Move to dist folder
 *
 * @return {Stream}
 */
module.exports = function () {
    $.log('Optimizing angular files');

    return gulp
        .src([$.dev_path + $.module.name + '/**/*.js'])
        .pipe(angularFilesort())
        .pipe(concat($.module.name + '.js'))
        .pipe(gulp.dest($.dist_path));
};<commit_msg>Ignores spec files when optimizing angular files<commit_after>'use strict';

var $ = require('../gulp.config.js');
var gulp = require('gulp');
var angularFilesort = require('gulp-angular-filesort');
var concat = require('gulp-concat');

/**
 * Optimize angular files
 * Move to dist folder
 *
 * @return {Stream}
 */
module.exports = function () {
    $.log('Optimizing angular files');

    return gulp
        .src([
            $.dev_path + $.module.name + '/**/*.js',
            '!' + $.dev_path + $.module.name + '/**/*.spec.js'
        ])
        .pipe(angularFilesort())
        .pipe(concat($.module.name + '.js'))
        .pipe(gulp.dest($.dist_path));
};<|endoftext|>