<commit_before>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @class
 * @constructor
 * @description An identify tool
 */
Ext.define("viewer.viewercontroller.openlayers.tools.OpenLayersIdentifyTool",{
    extend: "viewer.viewercontroller.openlayers.OpenLayersTool",
    map: null,
    deactivatedControls: null,
    wmsGetFeatureInfoControl:null,
    wmsGetFeatureInfoFormat: "application/vnd.ogc.gml",
    useWMSGetFeatureInfo:null,
    active: false,
    layersToAdd:null,
    config: {
        maxFeatures: 1000
    },
    /**
     * Constructor
     * @param conf the configuration object
     * @param frameworkTool the openlayers control
     * @param map the viewer.viewercontroller.openlayers.OpenLayersMap
     */
    constructor : function (conf){
        this.useWMSGetFeatureInfo=true;
        //this.wmsGetFeatureInfoFormat="text/plain";

        var frameworkOptions = {
            displayClass: "olControlIdentify",
            type: OpenLayers.Control.TYPE_TOOL,
            title: conf.tooltip
        };
        var frameworkTool= new OpenLayers.Control(frameworkOptions);
        viewer.viewercontroller.openlayers.tools.OpenLayersIdentifyTool.superclass.constructor.call(this,conf,frameworkTool);
        this.map=this.viewerController.mapComponent.getMap();

        this.mapClick=new viewer.viewercontroller.openlayers.ToolMapClick({
            id: "mapclick_"+this.id,
            viewerController: this.viewerController,
            handler: {
                    fn: this.handleClick,
                    scope: this
            },
            handlerOptions: {
                'stopSingle': true
            }
        });
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_ADDED,this.onAddLayer,this);
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_REMOVED,this.onRemoveLayer,this);

        this.setUseWMSGetFeatureInfo(this.useWMSGetFeatureInfo);
        // activate/deactivate
        this.getFrameworkTool().events.register("activate",this,this.activate);
        this.getFrameworkTool().events.register("deactivate",this,this.deactivate);
        return this;
    },
    setUseWMSGetFeatureInfo: function (val){
        this.useWMSGetFeatureInfo=val;
        if (this.useWMSGetFeatureInfo){
            if (this.wmsGetFeatureInfoControl==null){
                // add wms get featureInfo
                if (this.layersToAdd==null){
                    this.layersToAdd=[];
                }
                this.wmsGetFeatureInfoControl = new OpenLayers.Control.WMSGetFeatureInfo({
                        drillDown: true,
                        queryVisible: true,
                        infoFormat: this.wmsGetFeatureInfoFormat,
                        layers : this.layersToAdd,
                        maxFeatures: this.getMaxFeatures()
                    });

                this.wmsGetFeatureInfoControl.handleResponse = handleResponse;
                this.wmsGetFeatureInfoControl.buildWMSOptions = buildWMSOptions;
                this.wmsGetFeatureInfoControl.request = requestWmsGFI;
                this.wmsGetFeatureInfoControl.events.register("getfeatureinfo",this,this.raiseOnDataEvent);
                //deegree handler:
                this.wmsGetFeatureInfoControl.format.read_FeatureCollection = this.readFeatureCollection;
                this.map.getFrameworkMap().addControl(this.wmsGetFeatureInfoControl);

                //set proxy for getFeatureInfoRequests:
                OpenLayers.ProxyHost = contextPath+"/action/proxy/wms?url=";
            }
            if (this.active){
                this.wmsGetFeatureInfoControl.activate();
            }else{
                this.wmsGetFeatureInfoControl.deactivate();
            }
        }else{
            if (this.wmsGetFeatureInfoControl!=null){
                this.wmsGetFeatureInfoControl.deactivate();
            }
        }
    },
    /**
     * Called when a layer is added
     */
    onAddLayer: function(map,options){
        var mapLayer=options.layer;
        if (mapLayer==null || !(mapLayer instanceof viewer.viewercontroller.controller.WMSLayer)){
            return;
        }
        var details = mapLayer.getDetails();
        //something to show?
        if (details !=undefined &&
            (!Ext.isEmpty(details["summary.description"]) ||
                !Ext.isEmpty(details["summary.image"]) ||
                !Ext.isEmpty(details["summary.link"]) ||
                !Ext.isEmpty(details["summary.title"]))){
            var doClientWms=true;
            if (mapLayer.appLayerId){
                var appLayer=this.viewerController.app.appLayers[mapLayer.appLayerId];
                var confServiceLayer = this.viewerController.app.services[appLayer.serviceId].layers[appLayer.layerName];
                //do server side getFeature.
                if (confServiceLayer.hasFeatureType){
                    doClientWms=false;
                }
            }
            if (doClientWms){
                this.addWmsClientLayer(mapLayer);
            }

        }
    },
    /**
     * Called when a layer is removed
     */
    onRemoveLayer: function(map,options) {
        var mapLayer=options.layer;
        if (mapLayer==null
                || !(mapLayer instanceof viewer.viewercontroller.controller.WMSLayer)){
            return;
        }
        this.removeWmsClientLayer(mapLayer);

    },
    addWmsClientLayer: function(mapLayer){
        var layer = mapLayer.getFrameworkLayer();
        if (this.wmsGetFeatureInfoControl != null){
            if (this.wmsGetFeatureInfoControl.layers==null){
                this.wmsGetFeatureInfoControl.layers=[];
            }
            this.wmsGetFeatureInfoControl.layers.push(layer);
        }else{
            if (this.layersToAdd ==null){
                this.layersToAdd=[];
            }
            this.layersToAdd.push(layer);
        }
    },
    removeWmsClientLayer: function(mapLayer){
        var layer = mapLayer.getFrameworkLayer();
        if (this.wmsGetFeatureInfoControl != null){
            if (this.wmsGetFeatureInfoControl.layers!=null){
                this.wmsGetFeatureInfoControl.layers= Ext.Array.remove(this.wmsGetFeatureInfoControl.layers,layer);
            }
        }else if (this.layersToAdd!=null){
            this.layersToAdd=Ext.Array.remove(this.layersToAdd,layer);
        }
    },
    activate: function(){
        //if mobile: disable the navigation control. To make sure the click can be handled
        //Click won't be handled if there is a navigation controller enabled (for mobile)
        if (MobileManager.isMobile()){
            if (this.deactivatedControls==null){
                this.deactivatedControls=[];
            }
            var navigationTools= this.map.getFrameworkMap().getControlsByClass("OpenLayers.Control.Navigation");
            for (var i=0; i < navigationTools.length; i++){
                if (navigationTools[i].active){
                    this.deactivatedControls.push(navigationTools[i]);
                    navigationTools[i].deactivate();
                }
            }
        }
        this.active=true;
        //set dragPan.activate();
        //this.map.getFrameworkMap().events.register("click", this, this.handleClick);
        this.mapClick.activateTool();
        if (this.wmsGetFeatureInfoControl!=null){
            this.wmsGetFeatureInfoControl.activate();
        }
    },
    deactivate: function(){
        //if mobile: enable the disactivated controls again
        if (MobileManager.isMobile()){
            while (!Ext.isEmpty(this.deactivatedControls)){
                var disCont = this.deactivatedControls.pop();
                disCont.activate();
            }
        }
        this.active=false;
        //this.map.getFrameworkMap().events.unregister("click", this, this.handleClick);
        this.mapClick.deactivateTool();
        //
        if (this.wmsGetFeatureInfoControl!=null){
            this.wmsGetFeatureInfoControl.deactivate();
        }
    },
    handleClick: function(tool,options){
        this.map.fire(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,options);
    },
    //called when wms layers return data.
    raiseOnDataEvent: function(evt){
        var options = new Object();
        options.x = evt.xy.x;
        options.y = evt.xy.y;
        var coord = new Object();
        var c = this.map.pixelToCoordinate(options.x,options.y);
        coord.x = c.x;
        coord.y = c.y;
        options.coord=coord;
        var data=[];
        var featuresByLayer = new Object();
        for (var i=0; i< evt.features.length; i++){

            var feature = evt.features[i];
            var layerName = feature.type? feature.type : feature.layer;
            var appLayer = this.getAppLayerByOpenLayersLayer(feature.url,feature.layerNames);
            if (!featuresByLayer.hasOwnProperty(appLayer.id)) {
                featuresByLayer[appLayer.id] = new Object();
                featuresByLayer[appLayer.id].appLayerObj = appLayer;
            }
            if (!featuresByLayer[appLayer.id].hasOwnProperty(layerName)){
                featuresByLayer[appLayer.id][layerName] = new Object();
                featuresByLayer[appLayer.id][layerName].features = new Array();
            }
            featuresByLayer[appLayer.id][layerName].features.push(feature.attributes);
        }
        options.data = [];
        for(var applayer in featuresByLayer){
            var groupedLayers = featuresByLayer[applayer];
            for (var lName in groupedLayers){
                var features = groupedLayers[lName].features;
                var response = {
                    request: {
                        appLayer: appLayer.id,
                        serviceLayer: lName
                    },
                    features: features,
                    appLayer: appLayer
                }
                options.data.push(response);
            }
            featuresByLayer[applayer].appLayerObj.fire(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO_DATA, options);
        }

    },
    getAppLayerByOpenLayersLayer : function(url, layerNames){
        var layers = this.map.layers;
        for (var i = 0; i < layers.length; i++) {
            var layer = layers[i];
            if (layer.url === url) {
                var mapLayers= layer.getLayers();
                if (!(mapLayers instanceof Array)){
                    var array = [];
                    array.push(mapLayers);
                    mapLayers = array;
                }
                if (mapLayers.length === layerNames.length){
                    var allFound = true;
                    for (var j = 0; j < layerNames.length; j++) {
                        var found=false;
                        for (var l=0; l < mapLayers.length; l++){
                            if (mapLayers[l]=== layerNames[j]) {
                                found=true;
                                break;
                            }
                        }
                        if (!found){
                            allFound=false;
                            break;
                        }
                    }
                    if (allFound){
                        return layer;
                    }
                }
            }
        }
        return null;
    },

    /**
     * Is called by the .format from the OpenLayers GetFeatureInfoControl to parse the xml
     * This parses the deegree
     * @param {DOMElement} Root DOM element
     */
    readFeatureCollection: function (data){
        var featureIdentifier = "featureMember";
        var layerNodes = this.getSiblingNodesByTagCriteria(data,
            featureIdentifier);
        var response = [];
        if (layerNodes) {
            for (var i=0, len=layerNodes.length; i<len; ++i) {
                var featureNode = layerNodes[i].firstElementChild;
                var attributes = this.parseAttributes(featureNode);
                var geomAttr = this.parseGeometry(featureNode);
                var feature = new OpenLayers.Feature.Vector(geomAttr.geometry,
                    attributes,null);
                feature.type = featureNode.localName;
                response.push(feature);
            }
        }
        return response;
    }
});<commit_msg>Correct parsing of features from event. Prepare rethrowing of event correctly: appLayer was not the correct variable, and set the appLayerObj correct<commit_after>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @class
 * @constructor
 * @description An identify tool
 */
Ext.define("viewer.viewercontroller.openlayers.tools.OpenLayersIdentifyTool",{
    extend: "viewer.viewercontroller.openlayers.OpenLayersTool",
    map: null,
    deactivatedControls: null,
    wmsGetFeatureInfoControl:null,
    wmsGetFeatureInfoFormat: "application/vnd.ogc.gml",
    useWMSGetFeatureInfo:null,
    active: false,
    layersToAdd:null,
    config: {
        maxFeatures: 1000
    },
    /**
     * Constructor
     * @param conf the configuration object
     * @param frameworkTool the openlayers control
     * @param map the viewer.viewercontroller.openlayers.OpenLayersMap
     */
    constructor : function (conf){
        this.useWMSGetFeatureInfo=true;
        //this.wmsGetFeatureInfoFormat="text/plain";

        var frameworkOptions = {
            displayClass: "olControlIdentify",
            type: OpenLayers.Control.TYPE_TOOL,
            title: conf.tooltip
        };
        var frameworkTool= new OpenLayers.Control(frameworkOptions);
        viewer.viewercontroller.openlayers.tools.OpenLayersIdentifyTool.superclass.constructor.call(this,conf,frameworkTool);
        this.map=this.viewerController.mapComponent.getMap();

        this.mapClick=new viewer.viewercontroller.openlayers.ToolMapClick({
            id: "mapclick_"+this.id,
            viewerController: this.viewerController,
            handler: {
                    fn: this.handleClick,
                    scope: this
            },
            handlerOptions: {
                'stopSingle': true
            }
        });
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_ADDED,this.onAddLayer,this);
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_REMOVED,this.onRemoveLayer,this);

        this.setUseWMSGetFeatureInfo(this.useWMSGetFeatureInfo);
        // activate/deactivate
        this.getFrameworkTool().events.register("activate",this,this.activate);
        this.getFrameworkTool().events.register("deactivate",this,this.deactivate);
        return this;
    },
    setUseWMSGetFeatureInfo: function (val){
        this.useWMSGetFeatureInfo=val;
        if (this.useWMSGetFeatureInfo){
            if (this.wmsGetFeatureInfoControl==null){
                // add wms get featureInfo
                if (this.layersToAdd==null){
                    this.layersToAdd=[];
                }
                this.wmsGetFeatureInfoControl = new OpenLayers.Control.WMSGetFeatureInfo({
                        drillDown: true,
                        queryVisible: true,
                        infoFormat: this.wmsGetFeatureInfoFormat,
                        layers : this.layersToAdd,
                        maxFeatures: this.getMaxFeatures()
                    });

                this.wmsGetFeatureInfoControl.handleResponse = handleResponse;
                this.wmsGetFeatureInfoControl.buildWMSOptions = buildWMSOptions;
                this.wmsGetFeatureInfoControl.request = requestWmsGFI;
                this.wmsGetFeatureInfoControl.events.register("getfeatureinfo",this,this.raiseOnDataEvent);
                //deegree handler:
                this.wmsGetFeatureInfoControl.format.read_FeatureCollection = this.readFeatureCollection;
                this.map.getFrameworkMap().addControl(this.wmsGetFeatureInfoControl);

                //set proxy for getFeatureInfoRequests:
                OpenLayers.ProxyHost = contextPath+"/action/proxy/wms?url=";
            }
            if (this.active){
                this.wmsGetFeatureInfoControl.activate();
            }else{
                this.wmsGetFeatureInfoControl.deactivate();
            }
        }else{
            if (this.wmsGetFeatureInfoControl!=null){
                this.wmsGetFeatureInfoControl.deactivate();
            }
        }
    },
    /**
     * Called when a layer is added
     */
    onAddLayer: function(map,options){
        var mapLayer=options.layer;
        if (mapLayer==null || !(mapLayer instanceof viewer.viewercontroller.controller.WMSLayer)){
            return;
        }
        var details = mapLayer.getDetails();
        //something to show?
        if (details !=undefined &&
            (!Ext.isEmpty(details["summary.description"]) ||
                !Ext.isEmpty(details["summary.image"]) ||
                !Ext.isEmpty(details["summary.link"]) ||
                !Ext.isEmpty(details["summary.title"]))){
            var doClientWms=true;
            if (mapLayer.appLayerId){
                var appLayer=this.viewerController.app.appLayers[mapLayer.appLayerId];
                var confServiceLayer = this.viewerController.app.services[appLayer.serviceId].layers[appLayer.layerName];
                //do server side getFeature.
                if (confServiceLayer.hasFeatureType){
                    doClientWms=false;
                }
            }
            if (doClientWms){
                this.addWmsClientLayer(mapLayer);
            }

        }
    },
    /**
     * Called when a layer is removed
     */
    onRemoveLayer: function(map,options) {
        var mapLayer=options.layer;
        if (mapLayer==null
                || !(mapLayer instanceof viewer.viewercontroller.controller.WMSLayer)){
            return;
        }
        this.removeWmsClientLayer(mapLayer);

    },
    addWmsClientLayer: function(mapLayer){
        var layer = mapLayer.getFrameworkLayer();
        if (this.wmsGetFeatureInfoControl != null){
            if (this.wmsGetFeatureInfoControl.layers==null){
                this.wmsGetFeatureInfoControl.layers=[];
            }
            this.wmsGetFeatureInfoControl.layers.push(layer);
        }else{
            if (this.layersToAdd ==null){
                this.layersToAdd=[];
            }
            this.layersToAdd.push(layer);
        }
    },
    removeWmsClientLayer: function(mapLayer){
        var layer = mapLayer.getFrameworkLayer();
        if (this.wmsGetFeatureInfoControl != null){
            if (this.wmsGetFeatureInfoControl.layers!=null){
                this.wmsGetFeatureInfoControl.layers= Ext.Array.remove(this.wmsGetFeatureInfoControl.layers,layer);
            }
        }else if (this.layersToAdd!=null){
            this.layersToAdd=Ext.Array.remove(this.layersToAdd,layer);
        }
    },
    activate: function(){
        //if mobile: disable the navigation control. To make sure the click can be handled
        //Click won't be handled if there is a navigation controller enabled (for mobile)
        if (MobileManager.isMobile()){
            if (this.deactivatedControls==null){
                this.deactivatedControls=[];
            }
            var navigationTools= this.map.getFrameworkMap().getControlsByClass("OpenLayers.Control.Navigation");
            for (var i=0; i < navigationTools.length; i++){
                if (navigationTools[i].active){
                    this.deactivatedControls.push(navigationTools[i]);
                    navigationTools[i].deactivate();
                }
            }
        }
        this.active=true;
        //set dragPan.activate();
        //this.map.getFrameworkMap().events.register("click", this, this.handleClick);
        this.mapClick.activateTool();
        if (this.wmsGetFeatureInfoControl!=null){
            this.wmsGetFeatureInfoControl.activate();
        }
    },
    deactivate: function(){
        //if mobile: enable the disactivated controls again
        if (MobileManager.isMobile()){
            while (!Ext.isEmpty(this.deactivatedControls)){
                var disCont = this.deactivatedControls.pop();
                disCont.activate();
            }
        }
        this.active=false;
        //this.map.getFrameworkMap().events.unregister("click", this, this.handleClick);
        this.mapClick.deactivateTool();
        //
        if (this.wmsGetFeatureInfoControl!=null){
            this.wmsGetFeatureInfoControl.deactivate();
        }
    },
    handleClick: function(tool,options){
        this.map.fire(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,options);
    },
    //called when wms layers return data.
    raiseOnDataEvent: function(evt){
        var options = new Object();
        options.x = evt.xy.x;
        options.y = evt.xy.y;
        var coord = new Object();
        var c = this.map.pixelToCoordinate(options.x,options.y);
        coord.x = c.x;
        coord.y = c.y;
        options.coord=coord;
        var featuresByLayer = new Object();
        for (var i=0; i< evt.features.length; i++){

            var feature = evt.features[i];
            var layerName = feature.type? feature.type : feature.layerNames;
            var appLayer = this.getAppLayerByOpenLayersLayer(feature.url,layerName);
            if (!featuresByLayer.hasOwnProperty(appLayer.id)) {
                featuresByLayer[appLayer.id] = new Object();
                featuresByLayer[appLayer.id].appLayerObj = appLayer;
            }
            if (!featuresByLayer[appLayer.id].hasOwnProperty(layerName)){
                featuresByLayer[appLayer.id][layerName] = new Object();
                featuresByLayer[appLayer.id][layerName].features = new Array();
            }
            featuresByLayer[appLayer.id][layerName].features.push(feature.attributes);
        }
        for(var applayer in featuresByLayer){
            options.data = [];
            var groupedLayers = featuresByLayer[applayer];
            for (var lName in groupedLayers){
                var features = groupedLayers[lName].features;
                var response = {
                    request: {
                        appLayer: applayer,
                        serviceLayer: lName
                    },
                    features: features,
                    appLayer: groupedLayers.applayerObj
                }
                options.data.push(response);
            }
            featuresByLayer[applayer].appLayerObj.fire(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO_DATA, options);
        }

    },
    getAppLayerByOpenLayersLayer : function(url, layerNames){
        var layers = this.map.layers;
        for (var i = 0; i < layers.length; i++) {
            var layer = layers[i];
            if (layer.url === url) {
                var mapLayers= layer.getLayers();
                if (!(mapLayers instanceof Array)){
                    var array = [];
                    array.push(mapLayers);
                    mapLayers = array;
                }
                if (mapLayers.length === layerNames.length){
                    var allFound = true;
                    for (var j = 0; j < layerNames.length; j++) {
                        var found=false;
                        for (var l=0; l < mapLayers.length; l++){
                            if (mapLayers[l]=== layerNames[j]) {
                                found=true;
                                break;
                            }
                        }
                        if (!found){
                            allFound=false;
                            break;
                        }
                    }
                    if (allFound){
                        return layer;
                    }
                }
            }
        }
        return null;
    },

    /**
     * Is called by the .format from the OpenLayers GetFeatureInfoControl to parse the xml
     * This parses the deegree
     * @param {DOMElement} Root DOM element
     */
    readFeatureCollection: function (data){
        var featureIdentifier = "featureMember";
        var layerNodes = this.getSiblingNodesByTagCriteria(data,
            featureIdentifier);
        var response = [];
        if (layerNodes) {
            for (var i=0, len=layerNodes.length; i<len; ++i) {
                var featureNode = layerNodes[i].firstElementChild;
                var attributes = this.parseAttributes(featureNode);
                var geomAttr = this.parseGeometry(featureNode);
                var feature = new OpenLayers.Feature.Vector(geomAttr.geometry,
                    attributes,null);
                feature.type = featureNode.localName;
                response.push(feature);
            }
        }
        return response;
    }
});<|endoftext|>


<commit_before>var frisby = require('frisby');
var fs = require('fs');
var path = require('path');
var FormData = require('form-data');

var base_url = 'http://localhost:1337';

// Set up an HTML5 file posting
var create_form = function(filePath, format) {
	var html5Path = path.resolve(__dirname, filePath);
	var form = new FormData();
	form.append('outputFormat', format);
	form.append('html5', fs.createReadStream(html5Path), {
		// we need to set the knownLength so we can call  form.getLengthSync()
		knownLength: fs.statSync(html5Path).size
	});
    return form;
};

describe("MathML Cloud Error Responses", function() {
	// Global setup for all tests
	frisby.globalSetup({
	  request: {
	    headers:{'Accept': 'application/json', 'Content-Type': 'json'},
	    inspectOnFailure: true,
        baseUri: base_url
	  }
	});

    //---- Invalid file upload
	var invalid_form = create_form('./data/sample-math.zip', 'svg');

	frisby.create("Invalid file upload type")
		.post('/html5',
			invalid_form,
			{
			    json: false,
			    headers: {
			      'content-type': 'multipart/form-data; boundary=' + invalid_form.getBoundary(),
			      'content-length': invalid_form.getLengthSync()
			    },
			}
		)
		.expectStatus(400)
		.expectHeaderContains("content-type", "application/json")
		.expectJSON({
			errorCode: "24",
			message: "Only HTML5 files are supported."
		})
		.toss();

    //---- Requesting response in something other than JSON
	frisby.create("Set up equation for test")
		.post('/equation', {
			mathType : 'AsciiMath',
			math : 'a^2+b^2=c^2',
			svg : 'true'
		})
        .afterJSON(function(json) {
            frisby.create("Unsupported media type")
                .get('/equation/' + json.id, {
                    headers: {
                        "Accept": "application/xml"
                    }
                })
                .expectStatus(415)
                .expectJSON({
                    errorCode: "41",
                    message: "Unsupported media type request. Only JSON is supported."
                })
                .toss();
        })
		.toss();

    //---- Using an unsupported HTTP method
	frisby.create("HTTP method not supported")
		.put('/equation', {
			mathType : 'AsciiMath',
			math : 'a^2+b^2=c^2',
			description : 'true',
			svg : 'true'
		})
        .expectStatus(400)
        .expectJSON({
            errorCode: "40",
            message: "HTTP method not supported. See 'Allows' header for possible values."
        })
        .expectHeader('Allows', 'GET')
		.toss();

    //---- Using an unsupported math input type
	frisby.create("Unsupported math type")
		.post('/equation', {
			mathType : 'English',
			math : 'a^2+b^2=c^2',
			description : 'true',
			svg : 'true'
		})
        .expectStatus(400)
        .expectJSON({
            error: "E_VALIDATION",
        })
		.toss();

    //---- Asking for an unknown equation
	frisby.create("Equation ID not found")
        .get('/equation/12345')
        .expectStatus(404)
        .expectJSON({
            errorCode: "30",
            message: "Equation not found: 12345"
        })
		.toss();

    //---- Uploading a file with bad HTML
    var invalid_html = create_form('./data/invalid-html-math.html', 'svg');

    frisby.create("Invalid HTML")
        .post('/html5',
            invalid_html,
            {
                json: false,
                headers: {
                  'content-type': 'multipart/form-data; boundary=' + invalid_html.getBoundary(),
                  'content-length': invalid_html.getLengthSync()
                },
            }
        )
        .expectStatus(400)
        .expectHeaderContains("content-type", "application/json")
        .expectJSON({
            errorCode: "23",
            message: "Invalid HTML."
        })
        .toss();

    //---- Uploading a file encoded other than UTF-8
    var invalid_encoding = create_form('./data/invalid-encoding-math.html', 'svg');

    frisby.create("Unsupported encoding")
        .post('/html5',
            invalid_encoding,
            {
                json: false,
                headers: {
                  'content-type': 'multipart/form-data; boundary=' + invalid_encoding.getBoundary(),
                  'content-length': invalid_encoding.getLengthSync()
                },
            }
        )
        .expectStatus(400)
        .expectHeaderContains("content-type", "application/json")
        .expectJSON({
            errorCode: "22",
            message: "Unsupported text encoding. Must be UTF-8."
        })
        .toss();

    //---- Asking for an unsupported output format
    var invalid_output = create_form('./data/sample-math.html', 'jpg');

    frisby.create("Unsupported output format")
        .post('/html5',
            invalid_output,
            {
                json: false,
                headers: {
                  'content-type': 'multipart/form-data; boundary=' + invalid_output.getBoundary(),
                  'content-length': invalid_output.getLengthSync()
                },
            }
        )
        .expectStatus(400)
        .expectHeaderContains("content-type", "application/json")
        .expectJSON({
            error: "E_VALIDATION",
        })
        .toss();

});
<commit_msg>MMLC-91: Change test to match reality.<commit_after>var frisby = require('frisby');
var fs = require('fs');
var path = require('path');
var FormData = require('form-data');

var base_url = 'http://localhost:1337';

// Set up an HTML5 file posting
var create_form = function(filePath, format) {
	var html5Path = path.resolve(__dirname, filePath);
	var form = new FormData();
	form.append('outputFormat', format);
	form.append('html5', fs.createReadStream(html5Path), {
		// we need to set the knownLength so we can call  form.getLengthSync()
		knownLength: fs.statSync(html5Path).size
	});
    return form;
};

describe("MathML Cloud Error Responses", function() {
	// Global setup for all tests
	frisby.globalSetup({
	  request: {
	    headers:{'Accept': 'application/json', 'Content-Type': 'json'},
	    inspectOnFailure: true,
        baseUri: base_url
	  }
	});

    //---- Invalid file upload
	var invalid_form = create_form('./data/sample-math.zip', 'svg');

	frisby.create("Invalid file upload type")
		.post('/html5',
			invalid_form,
			{
			    json: false,
			    headers: {
			      'content-type': 'multipart/form-data; boundary=' + invalid_form.getBoundary(),
			      'content-length': invalid_form.getLengthSync()
			    },
			}
		)
		.expectStatus(400)
		.expectHeaderContains("content-type", "application/json")
		.expectJSON({
			errorCode: "24",
			message: "Only HTML5 files are supported."
		})
		.toss();

    //---- Requesting response in something other than JSON
	frisby.create("Set up equation for test")
		.post('/equation', {
			mathType : 'AsciiMath',
			math : 'a^2+b^2=c^2',
			svg : 'true'
		})
        .afterJSON(function(json) {
            frisby.create("Unsupported media type")
                .get('/equation/' + json.id, {
                    headers: {
                        "Accept": "application/xml"
                    }
                })
                .expectStatus(415)
                .expectJSON({
                    errorCode: "41",
                    message: "Unsupported media type request. Only JSON is supported."
                })
                .toss();
        })
		.toss();

    //---- Using an unsupported HTTP method
    // Sails doesn't provide an easy way to detect these, and just returns
    // a 404 when a match isn't found in routes.js
	frisby.create("HTTP method not supported")
		.put('/equation', {
			mathType : 'AsciiMath',
			math : 'a^2+b^2=c^2',
			description : 'true',
			svg : 'true'
		})
        .expectStatus(404)
		.toss();

    //---- Using an unsupported math input type
	frisby.create("Unsupported math type")
		.post('/equation', {
			mathType : 'English',
			math : 'a^2+b^2=c^2',
			description : 'true',
			svg : 'true'
		})
        .expectStatus(400)
        .expectJSON({
            error: "E_VALIDATION",
        })
		.toss();

    //---- Asking for an unknown equation
	frisby.create("Equation ID not found")
        .get('/equation/12345')
        .expectStatus(404)
        .expectJSON({
            errorCode: "30",
            message: "Equation not found: 12345"
        })
		.toss();

    //---- Uploading a file with bad HTML
    var invalid_html = create_form('./data/invalid-html-math.html', 'svg');

    frisby.create("Invalid HTML")
        .post('/html5',
            invalid_html,
            {
                json: false,
                headers: {
                  'content-type': 'multipart/form-data; boundary=' + invalid_html.getBoundary(),
                  'content-length': invalid_html.getLengthSync()
                },
            }
        )
        .expectStatus(400)
        .expectHeaderContains("content-type", "application/json")
        .expectJSON({
            errorCode: "23",
            message: "Invalid HTML."
        })
        .toss();

    //---- Uploading a file encoded other than UTF-8
    var invalid_encoding = create_form('./data/invalid-encoding-math.html', 'svg');

    frisby.create("Unsupported encoding")
        .post('/html5',
            invalid_encoding,
            {
                json: false,
                headers: {
                  'content-type': 'multipart/form-data; boundary=' + invalid_encoding.getBoundary(),
                  'content-length': invalid_encoding.getLengthSync()
                },
            }
        )
        .expectStatus(400)
        .expectHeaderContains("content-type", "application/json")
        .expectJSON({
            errorCode: "22",
            message: "Unsupported text encoding. Must be UTF-8."
        })
        .toss();

    //---- Asking for an unsupported output format
    var invalid_output = create_form('./data/sample-math.html', 'jpg');

    frisby.create("Unsupported output format")
        .post('/html5',
            invalid_output,
            {
                json: false,
                headers: {
                  'content-type': 'multipart/form-data; boundary=' + invalid_output.getBoundary(),
                  'content-length': invalid_output.getLengthSync()
                },
            }
        )
        .expectStatus(400)
        .expectHeaderContains("content-type", "application/json")
        .expectJSON({
            error: "E_VALIDATION",
        })
        .toss();

});
<|endoftext|>


<commit_before>/*!
    Copyright (C) 2013 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: brad@reciprocitylabs.com
    Maintained By: brad@reciprocitylabs.com
*/

(function(can, $) {

can.Model.Cacheable("can.Model.Join", {
  join_keys : null
  , setup : function() {
    this._super.apply(this, arguments);
  }
  , init : function() {
    this._super && this._super.apply(this, arguments);
    function reinit(ev, instance) {
      if (instance instanceof can.Model.Join) {
        instance.reinit();
        var refresh_queue = new RefreshQueue();
        can.each(instance.constructor.join_keys, function(cls, key) {
          var obj;
          if (instance[key]) {
            if(instance[key].reify && instance[key].reify().refresh) {
              obj = instance[key].reify();
            } else {
              obj = cls.findInCacheById(instance[key].id);
            }
          }
          if (obj) {
            refresh_queue.enqueue(obj);

          }
        });
        refresh_queue.trigger();
      }
    }
    if (this === can.Model.Join) {
      this.bind("created", reinit);
      this.bind("destroyed", reinit);
    }
  }
}, {
    init: function() {
      this._super.apply(this, arguments);
      var that = this;
      can.each(this.constructor.join_keys, function(cls, key) {
        that.bind(key + ".stub_destroyed", function() {
          // Trigger `destroyed` on self, since it was destroyed on the server
          that.destroyed();
        });
      });
    }

  , reinit : function() {
      this.init_join_objects();
    }

  , init_join_object_with_type: function(attr) {
      if(this[attr] instanceof can.Model) {
        return;
      }

      var object_id = this[attr + "_id"] || (this[attr] || {}).id
        , object_type = this[attr + "_type"] || (this[attr] || {}).type
        ;

      if (object_id && object_type && typeof object_type === "string") {
        this.attr(attr, CMS.Models.get_instance(
              object_type
            , object_id
            , this[attr]
            ) || this[attr]);
      } else if(object_id) {
        this.attr(attr, CMS.Models.get_instance(this[attr]));
      }
    }

  , init_join_object: function(attr, model_name) {
      var object_id = this[attr + "_id"] || (this[attr] || {}).id;

      if (object_id)
        this.attr(attr, CMS.Models.get_instance(
              model_name
            , object_id
            , this[attr]
            ).stub() || this[attr]);
    }

  , init_join_objects: function() {
      var that = this
        ;

      can.each(this.constructor.join_keys, function(model, attr) {
        if (model === can.Model.Cacheable)
          that.init_join_object_with_type(attr);
        else
          that.init_join_object(attr, model.shortName);
      });
    }
});

can.Model.Join("CMS.Models.Relationship", {
    root_object: "relationship"
  , root_collection: "relationships"
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , source : "CMS.Models.get_stub"
    , destination : "CMS.Models.get_stub"
  }
  , join_keys : {
    source : can.Model.Cacheable
    , destination : can.Model.Cacheable
  }
  , defaults : {
      source : null
    , destination : null
  }
  , findAll: "GET /api/relationships"
  , create: "POST /api/relationships"
  , destroy: "DELETE /api/relationships/{id}"
}, {
  reinit: function() {
    var that = this;

    this.attr("source", CMS.Models.get_instance(
      this.source_type
        || (this.source
            && (this.source.constructor
                && this.source.constructor.shortName
                || (!this.source.selfLink && this.source.type)))
      , this.source_id || (this.source && this.source.id)
      , this.source) || this.source);
    this.attr("destination", CMS.Models.get_instance(
      this.destination_type
        || (this.destination
            && (this.destination.constructor
                && this.destination.constructor.shortName
                || (!this.source.selfLink && this.destination.type)))
      , this.destination_id || (this.destination && this.destination.id)
      , this.destination) || this.destination);
  }
});

can.Model.Join("CMS.Models.UserRole", {
  root_object : "user_role"
  , root_collection : "user_roles"
  , findAll : "GET /api/user_roles"
  , update : "PUT /api/user_roles/{id}"
  , create : "POST /api/user_roles"
  , destroy : "DELETE /api/user_roles/{id}"
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , person : "CMS.Models.Person.stub"
    , role : "CMS.Models.Role.stub"
  }
  , join_keys : {
      person : CMS.Models.Person
    , role : CMS.Models.Role
  }
}, {
  save: function() {
    var roles,
        _super =  this._super;
    if(!this.role && this.role_name) {
      roles = can.map(
        CMS.Models.Role.cache,
        function(role) { if(role.name === this.role_name) return role; }.bind(this)
      );
      if(roles.length > 0) {
        this.attr("role", roles[0].stub());
        return _super.apply(this, arguments);
      } else {
        return CMS.Models.Role.findAll({ name__in : this.role_name }).then(function(roles) {
          if(roles.length < 1) {
            return new $.Deferred().reject("Role not found");
          }
          this.attr("role", roles[0].stub());
          return _super.apply(this, arguments);
        }.bind(this));
      }
    } else {
      return _super.apply(this, arguments);
    }
  }
});

can.Model.Join("CMS.Models.ObjectPerson", {
  root_object : "object_person"
  , root_collection : "object_people"
  , findAll: "GET /api/object_people"
  , create : "POST /api/object_people"
  , update : "PUT /api/object_people/{id}"
  , destroy : "DELETE /api/object_people/{id}"
  , join_keys : {
    personable : can.Model.Cacheable
    , person : CMS.Models.Person
  }
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , person : "CMS.Models.Person.stub"
    , personable : "CMS.Models.get_stub"
  }

}, {});

can.Model.Join("CMS.Models.ObjectOwner", {
  root_object : "object_owner"
  , root_collection : "object_owners"
  , findAll: "GET /api/object_owners"
  , create : "POST /api/object_owners"
  , update : "PUT /api/object_owners/{id}"
  , destroy : "DELETE /api/object_owners/{id}"
  , join_keys : {
    ownable : can.Model.Cacheable
    , person : CMS.Models.Person
  }
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , person : "CMS.Models.Person.stub"
    , ownable : "CMS.Models.get_stub"
  }

}, {});

can.Model.Join("CMS.Models.ObjectDocument", {
  root_object : "object_document"
  , root_collection : "object_documents"
  , findAll: "GET /api/object_documents"
  , create: "POST /api/object_documents"
  , destroy : "DELETE /api/object_documents/{id}"
  , join_keys : {
    documentable : can.Model.Cacheable
    , document : CMS.Models.Document
  }
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , document : "CMS.Models.Document.stub"
    , documentable : "CMS.Models.get_stub"
  }
}, {});

can.Model.Join("CMS.Models.MultitypeSearchJoin", {
  join_keys: {}
}, {});

can.Model.Join("CMS.Models.AuditObject", {
  root_object : "audit_object",
  root_collection : "audit_objects",
  findAll: "GET /api/audit_objects",
  create: "POST /api/audit_objects",
  destroy : "DELETE /api/audit_objects/{id}",
  join_keys : {
    auditable : can.Model.Cacheable,
    audit : CMS.Models.Audit
  },
  attributes : {
    context : "CMS.Models.Context.stub",
    modified_by : "CMS.Models.Person.stub",
    audit : "CMS.Models.Audit.stub",
    auditable : "CMS.Models.get_stub"
  }
}, {});

})(this.can, this.can.$);
<commit_msg>Fix updates on Relationship<commit_after>/*!
    Copyright (C) 2013 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: brad@reciprocitylabs.com
    Maintained By: brad@reciprocitylabs.com
*/

(function(can, $) {

can.Model.Cacheable("can.Model.Join", {
  join_keys : null
  , setup : function() {
    this._super.apply(this, arguments);
  }
  , init : function() {
    this._super && this._super.apply(this, arguments);
    function reinit(ev, instance) {
      if (instance instanceof can.Model.Join) {
        instance.reinit();
        var refresh_queue = new RefreshQueue();
        can.each(instance.constructor.join_keys, function(cls, key) {
          var obj;
          if (instance[key]) {
            if(instance[key].reify && instance[key].reify().refresh) {
              obj = instance[key].reify();
            } else {
              obj = cls.findInCacheById(instance[key].id);
            }
          }
          if (obj) {
            refresh_queue.enqueue(obj);

          }
        });
        refresh_queue.trigger();
      }
    }
    if (this === can.Model.Join) {
      this.bind("created", reinit);
      this.bind("destroyed", reinit);
    }
  }
}, {
    init: function() {
      this._super.apply(this, arguments);
      var that = this;
      can.each(this.constructor.join_keys, function(cls, key) {
        that.bind(key + ".stub_destroyed", function() {
          // Trigger `destroyed` on self, since it was destroyed on the server
          that.destroyed();
        });
      });
    }

  , reinit : function() {
      this.init_join_objects();
    }

  , init_join_object_with_type: function(attr) {
      if(this[attr] instanceof can.Model) {
        return;
      }

      var object_id = this[attr + "_id"] || (this[attr] || {}).id
        , object_type = this[attr + "_type"] || (this[attr] || {}).type
        ;

      if (object_id && object_type && typeof object_type === "string") {
        this.attr(attr, CMS.Models.get_instance(
              object_type
            , object_id
            , this[attr]
            ) || this[attr]);
      } else if(object_id) {
        this.attr(attr, CMS.Models.get_instance(this[attr]));
      }
    }

  , init_join_object: function(attr, model_name) {
      var object_id = this[attr + "_id"] || (this[attr] || {}).id;

      if (object_id)
        this.attr(attr, CMS.Models.get_instance(
              model_name
            , object_id
            , this[attr]
            ).stub() || this[attr]);
    }

  , init_join_objects: function() {
      var that = this
        ;

      can.each(this.constructor.join_keys, function(model, attr) {
        if (model === can.Model.Cacheable)
          that.init_join_object_with_type(attr);
        else
          that.init_join_object(attr, model.shortName);
      });
    }
});

can.Model.Join("CMS.Models.Relationship", {
    root_object: "relationship"
  , root_collection: "relationships"
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , source : "CMS.Models.get_stub"
    , destination : "CMS.Models.get_stub"
  }
  , join_keys : {
    source : can.Model.Cacheable
    , destination : can.Model.Cacheable
  }
  , defaults : {
      source : null
    , destination : null
  }
  , findAll: "GET /api/relationships"
  , create: "POST /api/relationships"
  , update: "PUT /api/relationships/{id}"
  , destroy: "DELETE /api/relationships/{id}"
}, {
  reinit: function() {
    var that = this;

    this.attr("source", CMS.Models.get_instance(
      this.source_type
        || (this.source
            && (this.source.constructor
                && this.source.constructor.shortName
                || (!this.source.selfLink && this.source.type)))
      , this.source_id || (this.source && this.source.id)
      , this.source) || this.source);
    this.attr("destination", CMS.Models.get_instance(
      this.destination_type
        || (this.destination
            && (this.destination.constructor
                && this.destination.constructor.shortName
                || (!this.source.selfLink && this.destination.type)))
      , this.destination_id || (this.destination && this.destination.id)
      , this.destination) || this.destination);
  }
});

can.Model.Join("CMS.Models.UserRole", {
  root_object : "user_role"
  , root_collection : "user_roles"
  , findAll : "GET /api/user_roles"
  , update : "PUT /api/user_roles/{id}"
  , create : "POST /api/user_roles"
  , destroy : "DELETE /api/user_roles/{id}"
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , person : "CMS.Models.Person.stub"
    , role : "CMS.Models.Role.stub"
  }
  , join_keys : {
      person : CMS.Models.Person
    , role : CMS.Models.Role
  }
}, {
  save: function() {
    var roles,
        _super =  this._super;
    if(!this.role && this.role_name) {
      roles = can.map(
        CMS.Models.Role.cache,
        function(role) { if(role.name === this.role_name) return role; }.bind(this)
      );
      if(roles.length > 0) {
        this.attr("role", roles[0].stub());
        return _super.apply(this, arguments);
      } else {
        return CMS.Models.Role.findAll({ name__in : this.role_name }).then(function(roles) {
          if(roles.length < 1) {
            return new $.Deferred().reject("Role not found");
          }
          this.attr("role", roles[0].stub());
          return _super.apply(this, arguments);
        }.bind(this));
      }
    } else {
      return _super.apply(this, arguments);
    }
  }
});

can.Model.Join("CMS.Models.ObjectPerson", {
  root_object : "object_person"
  , root_collection : "object_people"
  , findAll: "GET /api/object_people"
  , create : "POST /api/object_people"
  , update : "PUT /api/object_people/{id}"
  , destroy : "DELETE /api/object_people/{id}"
  , join_keys : {
    personable : can.Model.Cacheable
    , person : CMS.Models.Person
  }
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , person : "CMS.Models.Person.stub"
    , personable : "CMS.Models.get_stub"
  }

}, {});

can.Model.Join("CMS.Models.ObjectOwner", {
  root_object : "object_owner"
  , root_collection : "object_owners"
  , findAll: "GET /api/object_owners"
  , create : "POST /api/object_owners"
  , update : "PUT /api/object_owners/{id}"
  , destroy : "DELETE /api/object_owners/{id}"
  , join_keys : {
    ownable : can.Model.Cacheable
    , person : CMS.Models.Person
  }
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , person : "CMS.Models.Person.stub"
    , ownable : "CMS.Models.get_stub"
  }

}, {});

can.Model.Join("CMS.Models.ObjectDocument", {
  root_object : "object_document"
  , root_collection : "object_documents"
  , findAll: "GET /api/object_documents"
  , create: "POST /api/object_documents"
  , destroy : "DELETE /api/object_documents/{id}"
  , join_keys : {
    documentable : can.Model.Cacheable
    , document : CMS.Models.Document
  }
  , attributes : {
      context : "CMS.Models.Context.stub"
    , modified_by : "CMS.Models.Person.stub"
    , document : "CMS.Models.Document.stub"
    , documentable : "CMS.Models.get_stub"
  }
}, {});

can.Model.Join("CMS.Models.MultitypeSearchJoin", {
  join_keys: {}
}, {});

can.Model.Join("CMS.Models.AuditObject", {
  root_object : "audit_object",
  root_collection : "audit_objects",
  findAll: "GET /api/audit_objects",
  create: "POST /api/audit_objects",
  destroy : "DELETE /api/audit_objects/{id}",
  join_keys : {
    auditable : can.Model.Cacheable,
    audit : CMS.Models.Audit
  },
  attributes : {
    context : "CMS.Models.Context.stub",
    modified_by : "CMS.Models.Person.stub",
    audit : "CMS.Models.Audit.stub",
    auditable : "CMS.Models.get_stub"
  }
}, {});

})(this.can, this.can.$);
<|endoftext|>


<commit_before>import loggerCreator from "app/utils/logger";
//noinspection JSUnresolvedVariable
var moduleLogger = loggerCreator("Sidebar");

import React, { Component } from "react";
import { Image, StyleSheet, Text, View, Animated, PanResponder } from "react-native";
import { observer } from "mobx-react";
import { colors } from "app/styles/styles";

const SCRUB_WIDTH = 30;

const styles = StyleSheet.create({
  container: {
    position: "absolute",
    top: 54,
    bottom: -1,
    flexDirection: "row",
  },
  scrub: {
    width: SCRUB_WIDTH,
    backgroundColor: "transparent",
  },
  sidebar: {
    borderWidth: 1,
    borderColor: colors.CYAN_BRIGHT,
    borderStyle: "solid",
    backgroundColor: colors.CONTAINER_BACKGROUND_NORMAL,
  },
});

@observer
export default class Sidebar extends Component {
  componentWillMount() {
    this.openPosition = -2 - SCRUB_WIDTH;
    this.closePosition = this.openPosition - this.props.width;
    this.state = { positionAnimation: new Animated.Value(this.targetAnimatedPosition(this.props.isOpen)) };

    this.panResponder = PanResponder.create({
      onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder,
      onPanResponderGrant: this.onPanResponderGrant,
      onPanResponderMove: this.onPanResponderMove,
      onPanResponderRelease: this.onPanResponderRelease,
    });
  }

  componentWillReceiveProps(nextProps) {
    loggerCreator("componentWillReceiveProps", moduleLogger);
    this.slideSidebar(nextProps.isOpen);
  }

  adjustMovementBySide(value) {
    return this.props.fromLeft ? value : -value;
  }

  targetAnimatedPosition(isOpen) {
    return isOpen ? this.openPosition : this.closePosition;
  }

  onMoveShouldSetPanResponder = (evt, gestureState) => {
    return gestureState.numberActiveTouches > 0 && Math.abs(gestureState.dx) > 1;
  };

  onPanResponderGrant = () => {
    loggerCreator("onPanResponderGrant", moduleLogger);
    this.state.positionAnimation.setOffset(this.state.positionAnimation._value);
    this.state.positionAnimation.setValue(0);
  };

  onPanResponderMove = (evt, gestureState) => {
    const movedX = this.props.fromLeft ? gestureState.dx : -gestureState.dx;
    this.state.positionAnimation.setValue(this.adjustMovementBySide(gestureState.dx));
  };

  onPanResponderRelease = (evt, gestureState) => {
    loggerCreator("onPanResponderRelease", moduleLogger);

    this.state.positionAnimation.flattenOffset();

    let toOpen = this.adjustMovementBySide(gestureState.vx) > 0;
    if (this.props.isOpen !== toOpen) {
      this.props.onChangeOpen(toOpen);
    } else {
      this.slideSidebar(toOpen);
    }
  };

  slideSidebar(isOpen) {
    Animated.timing(this.state.positionAnimation, {
      toValue: this.targetAnimatedPosition(isOpen),
      duration: 200,
    }).start();
  }

  render() {
    const targetSide = this.props.fromLeft ? "left" : "right";
    const targetRoundedCorner = this.props.fromLeft ? "borderTopRightRadius" : "borderTopLeftRadius";

    return (
      <Animated.View
        style={[
          styles.container,
          {
            [targetSide]: this.state.positionAnimation.interpolate({
              inputRange: [this.closePosition, this.openPosition],
              outputRange: [this.closePosition, this.openPosition],
              extrapolate: "clamp",
            }),
          },
        ]}
        {...this.panResponder.panHandlers}>
        <View style={styles.scrub} />
        <View
          style={[
            styles.sidebar,
            {
              width: this.props.width,
              [targetRoundedCorner]: 5,
            },
          ]}>
          {this.props.children}
        </View>
        <View style={styles.scrub} />
      </Animated.View>
    );
  }
}

Sidebar.propTypes = {
  width: React.PropTypes.number.isRequired,
  fromLeft: React.PropTypes.bool.isRequired,

  isOpen: React.PropTypes.bool.isRequired,
  onChangeOpen: React.PropTypes.func.isRequired,
};
<commit_msg>fix - correctly open/close sidebar based on touch speed<commit_after>import loggerCreator from "app/utils/logger";
//noinspection JSUnresolvedVariable
var moduleLogger = loggerCreator("Sidebar");

import React, { Component } from "react";
import { Image, StyleSheet, Text, View, Animated, PanResponder } from "react-native";
import { observer } from "mobx-react";
import { colors } from "app/styles/styles";

const SCRUB_WIDTH = 30;
const MIN_SPEED_TO_TOGGLE_SIDEBAR = 0.1;

const styles = StyleSheet.create({
  container: {
    position: "absolute",
    top: 54,
    bottom: -1,
    flexDirection: "row",
  },
  scrub: {
    width: SCRUB_WIDTH,
    backgroundColor: "transparent",
  },
  sidebar: {
    borderWidth: 1,
    borderColor: colors.CYAN_BRIGHT,
    borderStyle: "solid",
    backgroundColor: colors.CONTAINER_BACKGROUND_NORMAL,
  },
});

@observer
export default class Sidebar extends Component {
  componentWillMount() {
    this.openPosition = -2 - SCRUB_WIDTH;
    this.closePosition = this.openPosition - this.props.width;
    this.state = { positionAnimation: new Animated.Value(this.targetAnimatedPosition(this.props.isOpen)) };

    this.panResponder = PanResponder.create({
      onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder,
      onPanResponderGrant: this.onPanResponderGrant,
      onPanResponderMove: this.onPanResponderMove,
      onPanResponderRelease: this.onPanResponderRelease,
    });
  }

  componentWillReceiveProps(nextProps) {
    loggerCreator("componentWillReceiveProps", moduleLogger);
    this.slideSidebar(nextProps.isOpen);
  }

  adjustMovementBySide(value) {
    return this.props.fromLeft ? value : -value;
  }

  targetAnimatedPosition(isOpen) {
    return isOpen ? this.openPosition : this.closePosition;
  }

  onMoveShouldSetPanResponder = (evt, gestureState) => {
    return gestureState.numberActiveTouches > 0 && Math.abs(gestureState.dx) > 1;
  };

  onPanResponderGrant = () => {
    loggerCreator("onPanResponderGrant", moduleLogger);
    this.state.positionAnimation.setOffset(this.state.positionAnimation._value);
    this.state.positionAnimation.setValue(0);
  };

  onPanResponderMove = (evt, gestureState) => {
    this.state.positionAnimation.setValue(this.adjustMovementBySide(gestureState.dx));
  };

  onPanResponderRelease = (evt, gestureState) => {
    let logger = loggerCreator("onPanResponderRelease", moduleLogger);

    this.state.positionAnimation.flattenOffset();

    let toOpen = null;
    if (Math.abs(gestureState.vx) > MIN_SPEED_TO_TOGGLE_SIDEBAR) {
      toOpen = this.adjustMovementBySide(gestureState.vx) > MIN_SPEED_TO_TOGGLE_SIDEBAR;
    } else {
      toOpen = !this.props.isOpen;
    }

    if (this.props.isOpen !== toOpen) {
      this.props.onChangeOpen(toOpen);
    } else {
      this.slideSidebar(toOpen);
    }
  };

  slideSidebar(isOpen) {
    Animated.timing(this.state.positionAnimation, {
      toValue: this.targetAnimatedPosition(isOpen),
      duration: 200,
    }).start();
  }

  render() {
    const targetSide = this.props.fromLeft ? "left" : "right";
    const targetRoundedCorner = this.props.fromLeft ? "borderTopRightRadius" : "borderTopLeftRadius";

    return (
      <Animated.View
        style={[
          styles.container,
          {
            [targetSide]: this.state.positionAnimation.interpolate({
              inputRange: [this.closePosition, this.openPosition],
              outputRange: [this.closePosition, this.openPosition],
              extrapolate: "clamp",
            }),
          },
        ]}
        {...this.panResponder.panHandlers}>
        <View style={styles.scrub} />
        <View
          style={[
            styles.sidebar,
            {
              width: this.props.width,
              [targetRoundedCorner]: 5,
            },
          ]}>
          {this.props.children}
        </View>
        <View style={styles.scrub} />
      </Animated.View>
    );
  }
}

Sidebar.propTypes = {
  width: React.PropTypes.number.isRequired,
  fromLeft: React.PropTypes.bool.isRequired,

  isOpen: React.PropTypes.bool.isRequired,
  onChangeOpen: React.PropTypes.func.isRequired,
};
<|endoftext|>


<commit_before>/******************************************************************************
*                                                                             *
* promfacts -- Jetpack feature for prometheus Facts                           *
*                                                                             *
* Copyright (C) 2009 Jens Wille                                               *
*                                                                             *
* promfacts is free software; you can redistribute it and/or modify it under  *
* the terms of the GNU General Public License as published by the Free        *
* Software Foundation; either version 3 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* promfacts is distributed in the hope that it will be useful, but WITHOUT    *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESSFOR A PARTICULAR PURPOSE. See the GNU General Public License for     *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with promfacts. If not, see <http://www.gnu.org/licenses/>.                 *
*                                                                             *
* @title       prometheus Facts                                               *
* @description Jetpack feature for prometheus Facts                           *
* @author      Jens Wille <jens.wille@uni-koeln.de>                           *
* @license     GPL                                                            *
* @version     0.0.1                                                          *
* @url         http://wiki.github.com/blackwinter/jetpacks/promfacts          *
* @update      http://github.com/blackwinter/jetpacks/raw/master/promfacts.js *
*                                                                             *
******************************************************************************/

const prefs = Components.classes['@mozilla.org/preferences-service;1']
                        .getService(Components.interfaces.nsIPrefService)
                        .getBranch('jetpacks.promfacts.');

var Prom = {};

Prom.url  = 'http://prometheus-bildarchiv.de';
Prom.icon = Prom.url + '/fileadmin/layout/favicon.ico';
Prom.lang = prefs.getPrefType('lang') == prefs.PREF_STRING ? prefs.getCharPref('lang') : '1';

Prom.tr = {};

switch (Prom.lang) {
  case '0':  // de
    Prom.tr.title = 'prometheus in Zahlen';
    Prom.tr.none  = 'Keine gefunden';
    break;

  default:   // en
    Prom.tr.title = 'prometheus Facts';
    Prom.tr.none  = 'None found';
    break;
};

Prom.facts = function(callback) {
  jQuery.get(Prom.url + '/?L=' + Prom.lang, function(data) {
    var facts;

    //facts = $(data).find('#facts')
    jQuery.each(jQuery.makeArray($(data)), function() {
      if (this.id == 'facts') {
        facts = $(this);
        return false;
      }
    });

    if (callback) {
      callback(facts);
    }

    return facts;
  });
};

jetpack.statusBar.append({
  html:  '',
  width: 18,

  onReady: function(widget) {
    $('img', widget).css({
      'padding-top': 3,
      cursor: 'pointer'
    });

    $(widget).click(function() {
      Prom.facts(function(facts) {
        jetpack.notifications.show({
          title: Prom.tr.title,
          body:  facts ? jQuery.trim(facts.text()).replace(/\n\s*/g, ', ') : Prom.tr.none + ' :-(',
          icon:  Prom.icon
        });
      });
    });
  }
});
<commit_msg>Fixed "context.createElement is not a function" as of Jetpack 0.6 (bundled with jQuery 1.3). v0.0.2<commit_after>/******************************************************************************
*                                                                             *
* promfacts -- Jetpack feature for prometheus Facts                           *
*                                                                             *
* Copyright (C) 2009 Jens Wille                                               *
*                                                                             *
* promfacts is free software; you can redistribute it and/or modify it under  *
* the terms of the GNU General Public License as published by the Free        *
* Software Foundation; either version 3 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* promfacts is distributed in the hope that it will be useful, but WITHOUT    *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESSFOR A PARTICULAR PURPOSE. See the GNU General Public License for     *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with promfacts. If not, see <http://www.gnu.org/licenses/>.                 *
*                                                                             *
* @title       prometheus Facts                                               *
* @description Jetpack feature for prometheus Facts                           *
* @author      Jens Wille <jens.wille@uni-koeln.de>                           *
* @license     GPL                                                            *
* @version     0.0.2                                                          *
* @url         http://wiki.github.com/blackwinter/jetpacks/promfacts          *
* @update      http://github.com/blackwinter/jetpacks/raw/master/promfacts.js *
*                                                                             *
******************************************************************************/

const prefs = Components.classes['@mozilla.org/preferences-service;1']
                        .getService(Components.interfaces.nsIPrefService)
                        .getBranch('jetpacks.promfacts.');

var Prom = {};

Prom.url  = 'http://prometheus-bildarchiv.de';
Prom.icon = Prom.url + '/fileadmin/layout/favicon.ico';
Prom.lang = prefs.getPrefType('lang') == prefs.PREF_STRING ? prefs.getCharPref('lang') : '1';

Prom.tr = {};

switch (Prom.lang) {
  case '0':  // de
    Prom.tr.title = 'prometheus in Zahlen';
    Prom.tr.none  = 'Keine gefunden';
    break;

  default:   // en
    Prom.tr.title = 'prometheus Facts';
    Prom.tr.none  = 'None found';
    break;
};

Prom.facts = function(callback) {
  jQuery.get(Prom.url + '/?L=' + Prom.lang, function(data) {
    data = jQuery(data, jetpack.tabs.focused.contentDocument);
    var facts;

    data.each(function() {
      if (this.id == 'facts') {
        facts = $(this);
        return false;
      }
    });

    if (callback) {
      callback(facts);
    }

    return facts;
  });
};

jetpack.statusBar.append({
  html:  '',
  width: 18,

  onReady: function(widget) {
    $('img', widget).css({
      'padding-top': 3,
      cursor: 'pointer'
    });

    $(widget).click(function() {
      Prom.facts(function(facts) {
        jetpack.notifications.show({
          title: Prom.tr.title,
          body:  facts ? jQuery.trim(facts.text()).replace(/\n\s*/g, ', ') : Prom.tr.none + ' :-(',
          icon:  Prom.icon
        });
      });
    });
  }
});
<|endoftext|>


<commit_before>////
//// A full take on a production live search for GOlr.
//// It ends up being a light wrapping around the search_pane widget.
////

//
function LiveSearchGOlrInit(){

    // Logger.
    var logger = new bbop.logger();
    logger.DEBUG = true;
    function ll(str){ logger.kvetch('LS: ' + str); }

    // Start messages.
    ll('');
    ll('LiveSearchGOlr.js');
    ll('LiveSearchGOlrInit start...');

    // Aliases.
    var each = bbop.core.each;
    var is_array = bbop.core.is_array;
    var first_split = bbop.core.first_split;

    ///
    /// A description of the active buttons and what to do when they
    /// are clicked. Very likely the only thing that you'd have to
    /// change on this page.
    ///

    function _establish_buttons(personality, manager){
	ll('Using _establish_buttons');
	if( personality == 'annotation' ){
	    manager.clear_buttons();
	    // Only add matrix button for labs for now.
	    if( sd.beta() && sd.beta() == '1' ){
		manager.add_button(facet_matrix_button);
	    }
	    manager.add_button(gaf_download_button);
	    manager.add_button(ann_flex_download_button);
	    //manager.add_button(gaf_galaxy_button);
	    manager.add_button(bookmark_button);
	}else if( personality == 'ontology' ){
	    manager.clear_buttons();
	    //manager.add_button(id_label_download_button);
	    manager.add_button(ont_flex_download_button);
	    //manager.add_button(id_term_label_galaxy_button);
	    manager.add_button(bookmark_button);
	}else if( personality == 'bioentity' ){
	    manager.clear_buttons();
	    //manager.add_button(id_download_button);
	    manager.add_button(bio_flex_download_button);
	    //manager.add_button(id_symbol_galaxy_button);
	    manager.add_button(bookmark_button);
	}else if( personality == 'complex_annotation' ){
	    manager.clear_buttons();
	//}else if( personality == 'bbop_ann_ev_agg' ){
	}else{
	    manager.clear_buttons();
	}
    }

    var active_classes = {
    	'annotation': function(manager){
    	    manager.add_query_filter('document_category',
    				     'annotation', ['*']);
    	    _establish_buttons('annotation', manager);
    	},
    	'ontology': function(manager){
    	    manager.add_query_filter('document_category',
    				     'ontology_class', ['*']);
    	    _establish_buttons('ontology', manager);
    	},
    	'bioentity': function(manager){
    	    manager.add_query_filter('document_category',
    				     'bioentity', ['*']);
    	    _establish_buttons('bioentity', manager);
    	},
    	'complex_annotation': function(manager){
    	    manager.add_query_filter('document_category',
    				     'complex_annotation', ['*']);
    	    //_establish_buttons('annotation', manager);
    	},
    	'family': function(manager){
    	    manager.add_query_filter('document_category',
    				     'family', ['*']);
    	    _establish_buttons('family', manager);
    	},
    	'general': function(manager){
    	    manager.add_query_filter('document_category',
    				     'general', ['*']);
    	    _establish_buttons('general', manager);
	},
    	'bbop_term_ac': function(manager){
    	    manager.add_query_filter('document_category',
    				     'ontology_class', ['*']);
    	    _establish_buttons('bbop_term_ac', manager);
    	// },
    	// 'bbop_ann_ev_agg': function(manager){
    	//     manager.add_query_filter('document_category',
    	// 			     'annotation_evidence_aggregate',['*']);
    	//     _establish_buttons('bbop_ann_ev_agg', manager);
    	}
    };

    ///
    /// Ready the configuration that we'll use.
    ///

    var gconf = new bbop.golr.conf(amigo.data.golr);
    var sd = new amigo.data.server();
    var defs = new amigo.data.definitions();
    var linker = new amigo.linker();
    var solr_server = sd.golr_base();
    var div_id = 'display-general-search';

    ///
    /// Defined some useful buttons.
    ///

    // Download limit.
    var dlimit = defs.download_limit();

    // Global download properties.
    var _dl_props = {
	'entity_list': null,
	'rows': dlimit
    };

    // Define the rows that we'll use to create a psuedo-GAF.
    var _gaf_fl = defs.gaf_from_golr_fields();

    // Create button templates to use from our library.
    var btmpl = bbop.widget.display.button_templates;

    var id_download_button =
	btmpl.field_download('Download IDs (up to ' +
			     dlimit + ')',
			     dlimit, ['id']);
    var id_label_download_button =
	btmpl.field_download('Download IDs and labels (up to ' +
			     dlimit + ')',
			     dlimit, ['annotation_class',
				      'annotation_class_label']);
    var gaf_download_button =
	btmpl.field_download('GAF chunk download (up to ' +
			     dlimit + ')',
			     dlimit, _gaf_fl);
    // Flexible download buttons.
    var ont_flex_download_button =
	btmpl.flexible_download('Flex download (up to ' + dlimit + ')',
				dlimit,
				['annotation_class', 'annotation_class_label'],
				'ontology',
				gconf);
    var bio_flex_download_button =
	btmpl.flexible_download('Flex download (up to ' + dlimit + ')',
				dlimit,
				['bioentity', 'bioentity_label'],
				'bioentity',
				gconf);
    var ann_flex_download_button =
	btmpl.flexible_download('Flex download (up to ' + dlimit + ')',
				dlimit,
				defs.gaf_from_golr_fields(),
				'annotation',
				gconf);
    //var bookmark_button = btmpl.bookmark(linker);
    var bookmark_button = btmpl.restmark(linker);
    var facet_matrix_button = btmpl.open_facet_matrix(gconf, sd);
    // var gaf_galaxy_button =
    // 	btmpl.send_fields_to_galaxy('Send GAF chunk to Galaxy (up to ' +
    // 				    dlimit + ')',
    // 				    dlimit, _gaf_fl, global_galaxy_url);
    // var id_term_label_galaxy_button =
    // 	btmpl.send_fields_to_galaxy('Send IDs and names to Galaxy (up to ' +
    // 				    dlimit + ')',
    // 				    dlimit, ['annotation_class',
    // 					   'annotation_class_label'],
    // 				    global_galaxy_url);
    // var id_symbol_galaxy_button =
    // 	btmpl.send_fields_to_galaxy('Send IDs and symbols to Galaxy ' +
    // 				    '(up to ' + dlimit + ')',
    // 				    dlimit,['bioentity', 'bioentity_label'],
    // 				    global_galaxy_url);

    ///
    /// Ready widget.
    ///

    var handler = new amigo.handler();
    var hargs = {
	'linker': linker,
	'handler': handler,
	'base_icon_url' : null,
    	'image_type' : 'gif',
    	'layout_type' : 'two-column',
    	'show_global_reset_p' : true,
    	'show_searchbox_p' : true,
    	'show_filterbox_p' : true,
    	'show_pager_p' : true,
    	'show_checkboxes_p' : true,
    	//'show_checkboxes_p' : false,
    	//'spinner_search_source' : '',
    	'spinner_search_source' : sd.image_base() + '/waiting_ajax.gif',
    	//'spinner_shield_source' : sd.image_base() + '/waiting_poll.gif'
    	'spinner_shield_message' : 'Loading and using this widget may take a long time on some large filter sets. If it takes too long, please close it and further narrow your results using other facets or the text search.
Waiting...',
    	'spinner_shield_source' : sd.image_base() + '/waiting_ajax.gif'
	//
    	//'icon_clear_label' : _button_wrapper('X', 'Clear text from query'),
    	//'icon_clear_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png',
    	//'icon_reset_label' : ' [reset all user filters]',
    	//'icon_remove_label' : _button_wrapper('X', 'Remove filter from query'),
    	//'icon_remove_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png',
    	//'icon_positive_label' : _button_wrapper('+', 'Add positive filter'),
    	//'icon_positive_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png',
    	//'icon_negative_label' : _button_wrapper('-', 'Add negative filter')
    	//'icon_negative_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png'
    };
    var search = new bbop.widget.search_pane(solr_server, gconf, div_id, hargs);
    // We like highlights; they should be included automatically
    // through the widget.
    search.include_highlighting(true);

    ///
    /// Handle setup:
    ///  1) We /need/ to have a personality defined. If not, it is an error--
    ///     we no longer do the (confusing) tabbed-switch approach.
    ///  2) Process incoming queries/filters (into manager).
    ///  3) Process incoming bookmarks (into manager).
    ///  4) Render manager state to display.
    ///

    // 1) Check for incoming personality.
    // A little handling if we came in on a personality dispatch.
    if( ! global_live_search_personality ||
	global_live_search_personality == ''){
	ll('ERROR: No personality defined, cannot continue.');
	alert('ERROR: No personality defined, cannot continue.');
    }else{
	ll("Detected dispatch argument (can progress): " +
	   global_live_search_personality);

	// _on_search_select(global_live_search_personality);
	search.set_personality(global_live_search_personality);
	search.lite(true);

	// 2) Process incoming queries, pins, and filters (into
	// manager)--the RESTy bookmarking API.
	// Check to see if we have an incoming query (likely the landing page).
	if( global_live_search_query ){ // has incoming query
    	    ll("Try and use incoming query (set default): " +
	       global_live_search_query);
    	    search.set_comfy_query(global_live_search_query);
	    //var def_comfy = search.set_comfy_query(global_live_search_query);
    	    //search.set_default_query(def_comfy);
    	    //search.set_query(def_comfy);
	}
	if( is_array(global_live_search_filters) ){ // has incoming filters
	    each(global_live_search_filters,
		 function(filter){
		     search.add_query_filter_as_string(filter, ['$']);
		 });
	}
	if( is_array(global_live_search_pins) ){ // has incoming pins
	    each(global_live_search_pins,
		 function(pin){
		     search.add_query_filter_as_string(pin, ['*']);
		 });
	}

	// 3) Process incoming bookmarks (into manager).
	// Check to see if we have a bookmark or not. If we have one, run
	// it.
	if( global_live_search_bookmark ){ // has bookmark
	    ll("Try and use bookmark in establishment.");

	    // Load it and see what happens.
	    var parm_list =
		bbop.core.url_parameters(global_live_search_bookmark);
	    //alert(bbop.core.dump(parm_list));
	    var bookmark_probe = bbop.core.hashify(parm_list);
	    //alert(bbop.core.dump(bookmark_probe));

	    // Sanity check.
	    if( ! bookmark_probe['personality'] || // bookmark is bad
		bookmark_probe['json.nl'] != 'arrarr' ||
		bookmark_probe['wt'] != 'json' ){ //||
			//! bookmark_probe['document_category'] ){

		    ll("Bookmark lacks sanity.");
		    alert('ERROR: Bookmark did not include a personality, ' +
			  'and sanity. ' +
			  'Please remove the bookmark parameter from the URL.');
	    }else{ // probably good bookmark
		ll("Bookmark has a personality: " + search.get_personality());

		// Load bookmark.
		ll("Pre bookmark: " + search.get_query_url());
		ll(global_live_search_bookmark);
		ll("Pre-bookmark personality: " + search.get_personality());
		search.load_url(global_live_search_bookmark);
		ll("Post-bookmark personality: " + search.get_personality());
		ll("Post bookmark: " + search.get_query_url());
	    }
	}else{ // no bookmark
	    ll("No bookmark in establishment.");
	}

	// 4) Render manager state to display.
	// Run through our pre-defined activation functions
	var activation_function = active_classes[search.get_personality()];
	activation_function(search);
	// Establish the display with what we have.
    	search.establish_display();
	search.search();
	//ll("Post establish: " + search.get_query_url());

	// Make sure the text query is there and proper.
	// Remember, we don't refresh it off of search like the others
	// because it needs persistance for the UI.
	ll("Post query: " + search.get_query());
	ll("Post default query: " + search.get_default_query());
	if( search.get_query() == search.get_default_query() ){
	    // The default is the same as nothing at all since it is
	    // default.
	    search.set_query_field_text('');
	}else{
	    // Wild cards are set after the fact in comfy, so just
	    // remove the wildcard if it is sitting there at the end.
	    var gq = search.get_query();
	    if( '*' == gq.charAt(gq.length - 1) ){
		gq = gq.substring(0, gq.length - 1);
	    }
	    search.set_query_field_text(gq);
	}

	// Destroy the bookmark so we don't keep hitting it.
	global_live_search_bookmark = null;

    }

    // Done message.
    ll('LiveSearchGOlrInit done.');

    // DEBUGGING: A temporary external hook to help with dev and
    // debugging.
    s = search;
}
var s;
<commit_msg>add necessary bits to get model_annotation search exposed as general item; better syntax checker<commit_after>////
//// A full take on a production live search for GOlr.
//// It ends up being a light wrapping around the search_pane widget.
////

// Let jshint pass over over our external globals (browserify takes
// care of it all).
/* global jQuery */
/* global bbop */
/* global amigo */
/* global global_live_search_bookmark */
/* global global_live_search_pins */
/* global global_live_search_query */
/* global global_live_search_personality */
/* global global_live_search_filters */
/* global global_live_search_bookmark */

//
function LiveSearchGOlrInit(){

    // Logger.
    var logger = new bbop.logger();
    logger.DEBUG = true;
    function ll(str){ logger.kvetch('LS: ' + str); }

    // Start messages.
    ll('');
    ll('LiveSearchGOlr.js');
    ll('LiveSearchGOlrInit start...');

    // Aliases.
    var each = bbop.core.each;
    var is_array = bbop.core.is_array;
    var first_split = bbop.core.first_split;

    ///
    /// A description of the active buttons and what to do when they
    /// are clicked. Very likely the only thing that you'd have to
    /// change on this page.
    ///

    function _establish_buttons(personality, manager){
	ll('Using _establish_buttons');
	if( personality === 'annotation' ){
	    manager.clear_buttons();
	    // Only add matrix button for labs for now.
	    if( sd.beta() && sd.beta() === '1' ){
		manager.add_button(facet_matrix_button);
	    }
	    manager.add_button(gaf_download_button);
	    manager.add_button(ann_flex_download_button);
	    //manager.add_button(gaf_galaxy_button);
	    manager.add_button(bookmark_button);
	}else if( personality === 'ontology' ){
	    manager.clear_buttons();
	    //manager.add_button(id_label_download_button);
	    manager.add_button(ont_flex_download_button);
	    //manager.add_button(id_term_label_galaxy_button);
	    manager.add_button(bookmark_button);
	}else if( personality === 'bioentity' ){
	    manager.clear_buttons();
	    //manager.add_button(id_download_button);
	    manager.add_button(bio_flex_download_button);
	    //manager.add_button(id_symbol_galaxy_button);
	    manager.add_button(bookmark_button);
	// }else if( personality === 'complex_annotation' ){
	//     manager.clear_buttons();
	}else if( personality === 'model_annotation' ){
	    manager.clear_buttons();
	//}else if( personality === 'bbop_ann_ev_agg' ){
	}else{
	    manager.clear_buttons();
	}
    }

    var active_classes = {
    	'annotation': function(manager){
    	    manager.add_query_filter('document_category',
    				     'annotation', ['*']);
    	    _establish_buttons('annotation', manager);
    	},
    	'ontology': function(manager){
    	    manager.add_query_filter('document_category',
    				     'ontology_class', ['*']);
    	    _establish_buttons('ontology', manager);
    	},
    	'bioentity': function(manager){
    	    manager.add_query_filter('document_category',
    				     'bioentity', ['*']);
    	    _establish_buttons('bioentity', manager);
    	},
    	// 'complex_annotation': function(manager){
    	//     manager.add_query_filter('document_category',
    	// 			     'complex_annotation', ['*']);
    	//     //_establish_buttons('annotation', manager);
    	'model_annotation': function(manager){
    	    manager.add_query_filter('document_category',
    				     'model_annotation', ['*']);
    	    //_establish_buttons('annotation', manager);
    	},
    	'family': function(manager){
    	    manager.add_query_filter('document_category',
    				     'family', ['*']);
    	    _establish_buttons('family', manager);
    	},
    	'general': function(manager){
    	    manager.add_query_filter('document_category',
    				     'general', ['*']);
    	    _establish_buttons('general', manager);
	},
    	'bbop_term_ac': function(manager){
    	    manager.add_query_filter('document_category',
    				     'ontology_class', ['*']);
    	    _establish_buttons('bbop_term_ac', manager);
    	// },
    	// 'bbop_ann_ev_agg': function(manager){
    	//     manager.add_query_filter('document_category',
    	// 			     'annotation_evidence_aggregate',['*']);
    	//     _establish_buttons('bbop_ann_ev_agg', manager);
    	}
    };

    ///
    /// Ready the configuration that we'll use.
    ///

    var gconf = new bbop.golr.conf(amigo.data.golr);
    var sd = new amigo.data.server();
    var defs = new amigo.data.definitions();
    var linker = new amigo.linker();
    var solr_server = sd.golr_base();
    var div_id = 'display-general-search';

    ///
    /// Defined some useful buttons.
    ///

    // Download limit.
    var dlimit = defs.download_limit();

    // Global download properties.
    var _dl_props = {
	'entity_list': null,
	'rows': dlimit
    };

    // Define the rows that we'll use to create a psuedo-GAF.
    var _gaf_fl = defs.gaf_from_golr_fields();

    // Create button templates to use from our library.
    var btmpl = bbop.widget.display.button_templates;

    var id_download_button =
	btmpl.field_download('Download IDs (up to ' +
			     dlimit + ')',
			     dlimit, ['id']);
    var id_label_download_button =
	btmpl.field_download('Download IDs and labels (up to ' +
			     dlimit + ')',
			     dlimit, ['annotation_class',
				      'annotation_class_label']);
    var gaf_download_button =
	btmpl.field_download('GAF chunk download (up to ' +
			     dlimit + ')',
			     dlimit, _gaf_fl);
    // Flexible download buttons.
    var ont_flex_download_button =
	btmpl.flexible_download('Flex download (up to ' + dlimit + ')',
				dlimit,
				['annotation_class', 'annotation_class_label'],
				'ontology',
				gconf);
    var bio_flex_download_button =
	btmpl.flexible_download('Flex download (up to ' + dlimit + ')',
				dlimit,
				['bioentity', 'bioentity_label'],
				'bioentity',
				gconf);
    var ann_flex_download_button =
	btmpl.flexible_download('Flex download (up to ' + dlimit + ')',
				dlimit,
				defs.gaf_from_golr_fields(),
				'annotation',
				gconf);
    //var bookmark_button = btmpl.bookmark(linker);
    var bookmark_button = btmpl.restmark(linker);
    var facet_matrix_button = btmpl.open_facet_matrix(gconf, sd);
    // var gaf_galaxy_button =
    // 	btmpl.send_fields_to_galaxy('Send GAF chunk to Galaxy (up to ' +
    // 				    dlimit + ')',
    // 				    dlimit, _gaf_fl, global_galaxy_url);
    // var id_term_label_galaxy_button =
    // 	btmpl.send_fields_to_galaxy('Send IDs and names to Galaxy (up to ' +
    // 				    dlimit + ')',
    // 				    dlimit, ['annotation_class',
    // 					   'annotation_class_label'],
    // 				    global_galaxy_url);
    // var id_symbol_galaxy_button =
    // 	btmpl.send_fields_to_galaxy('Send IDs and symbols to Galaxy ' +
    // 				    '(up to ' + dlimit + ')',
    // 				    dlimit,['bioentity', 'bioentity_label'],
    // 				    global_galaxy_url);

    ///
    /// Ready widget.
    ///

    var handler = new amigo.handler();
    var hargs = {
	'linker': linker,
	'handler': handler,
	'base_icon_url' : null,
    	'image_type' : 'gif',
    	'layout_type' : 'two-column',
    	'show_global_reset_p' : true,
    	'show_searchbox_p' : true,
    	'show_filterbox_p' : true,
    	'show_pager_p' : true,
    	'show_checkboxes_p' : true,
    	//'show_checkboxes_p' : false,
    	//'spinner_search_source' : '',
    	'spinner_search_source' : sd.image_base() + '/waiting_ajax.gif',
    	//'spinner_shield_source' : sd.image_base() + '/waiting_poll.gif'
    	'spinner_shield_message' : 'Loading and using this widget may take a long time on some large filter sets. If it takes too long, please close it and further narrow your results using other facets or the text search.
Waiting...',
    	'spinner_shield_source' : sd.image_base() + '/waiting_ajax.gif'
	//
    	//'icon_clear_label' : _button_wrapper('X', 'Clear text from query'),
    	//'icon_clear_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png',
    	//'icon_reset_label' : ' [reset all user filters]',
    	//'icon_remove_label' : _button_wrapper('X', 'Remove filter from query'),
    	//'icon_remove_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png',
    	//'icon_positive_label' : _button_wrapper('+', 'Add positive filter'),
    	//'icon_positive_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png',
    	//'icon_negative_label' : _button_wrapper('-', 'Add negative filter')
    	//'icon_negative_source' : 'http://amigo2.berkeleybop.org/amigo2/images/warning.png'
    };
    var search = new bbop.widget.search_pane(solr_server, gconf, div_id, hargs);
    // We like highlights; they should be included automatically
    // through the widget.
    search.include_highlighting(true);

    ///
    /// Handle setup:
    ///  1) We /need/ to have a personality defined. If not, it is an error--
    ///     we no longer do the (confusing) tabbed-switch approach.
    ///  2) Process incoming queries/filters (into manager).
    ///  3) Process incoming bookmarks (into manager).
    ///  4) Render manager state to display.
    ///

    // 1) Check for incoming personality.
    // A little handling if we came in on a personality dispatch.
    if( ! global_live_search_personality ||
	global_live_search_personality === ''){
	ll('ERROR: No personality defined, cannot continue.');
	alert('ERROR: No personality defined, cannot continue.');
    }else{
	ll("Detected dispatch argument (can progress): " +
	   global_live_search_personality);

	// _on_search_select(global_live_search_personality);
	search.set_personality(global_live_search_personality);
	search.lite(true);

	// 2) Process incoming queries, pins, and filters (into
	// manager)--the RESTy bookmarking API.
	// Check to see if we have an incoming query (likely the landing page).
	if( global_live_search_query ){ // has incoming query
    	    ll("Try and use incoming query (set default): " +
	       global_live_search_query);
    	    search.set_comfy_query(global_live_search_query);
	    //var def_comfy = search.set_comfy_query(global_live_search_query);
    	    //search.set_default_query(def_comfy);
    	    //search.set_query(def_comfy);
	}
	if( is_array(global_live_search_filters) ){ // has incoming filters
	    each(global_live_search_filters,
		 function(filter){
		     search.add_query_filter_as_string(filter, ['$']);
		 });
	}
	if( is_array(global_live_search_pins) ){ // has incoming pins
	    each(global_live_search_pins,
		 function(pin){
		     search.add_query_filter_as_string(pin, ['*']);
		 });
	}

	// 3) Process incoming bookmarks (into manager).
	// Check to see if we have a bookmark or not. If we have one, run
	// it.
	if( global_live_search_bookmark ){ // has bookmark
	    ll("Try and use bookmark in establishment.");

	    // Load it and see what happens.
	    var parm_list =
		bbop.core.url_parameters(global_live_search_bookmark);
	    //alert(bbop.core.dump(parm_list));
	    var bookmark_probe = bbop.core.hashify(parm_list);
	    //alert(bbop.core.dump(bookmark_probe));

	    // Sanity check.
	    if( ! bookmark_probe['personality'] || // bookmark is bad
		bookmark_probe['json.nl'] !== 'arrarr' ||
		bookmark_probe['wt'] !== 'json' ){ //||
			//! bookmark_probe['document_category'] ){

		    ll("Bookmark lacks sanity.");
		    alert('ERROR: Bookmark did not include a personality, ' +
			  'and sanity. ' +
			  'Please remove the bookmark parameter from the URL.');
	    }else{ // probably good bookmark
		ll("Bookmark has a personality: " + search.get_personality());

		// Load bookmark.
		ll("Pre bookmark: " + search.get_query_url());
		ll(global_live_search_bookmark);
		ll("Pre-bookmark personality: " + search.get_personality());
		search.load_url(global_live_search_bookmark);
		ll("Post-bookmark personality: " + search.get_personality());
		ll("Post bookmark: " + search.get_query_url());
	    }
	}else{ // no bookmark
	    ll("No bookmark in establishment.");
	}

	// 4) Render manager state to display.
	// Run through our pre-defined activation functions
	var activation_function = active_classes[search.get_personality()];
	activation_function(search);
	// Establish the display with what we have.
    	search.establish_display();
	search.search();
	//ll("Post establish: " + search.get_query_url());

	// Make sure the text query is there and proper.
	// Remember, we don't refresh it off of search like the others
	// because it needs persistance for the UI.
	ll("Post query: " + search.get_query());
	ll("Post default query: " + search.get_default_query());
	if( search.get_query() === search.get_default_query() ){
	    // The default is the same as nothing at all since it is
	    // default.
	    search.set_query_field_text('');
	}else{
	    // Wild cards are set after the fact in comfy, so just
	    // remove the wildcard if it is sitting there at the end.
	    var gq = search.get_query();
	    if( '*' === gq.charAt(gq.length - 1) ){
		gq = gq.substring(0, gq.length - 1);
	    }
	    search.set_query_field_text(gq);
	}

	// Destroy the bookmark so we don't keep hitting it.
	global_live_search_bookmark = null;
    }

    // Done message.
    ll('LiveSearchGOlrInit done.');

    // DEBUGGING: A temporary external hook to help with dev and
    // debugging.
    s = search;
}
var s;
<|endoftext|>