<commit_before>'use strict';

var app = angular.module('translationApp', ['ngTable']);

app.factory('sharedMessage', function () {
    return {
        css: '',
        icon: '',
        content: '',
        set: function (css, icon, content) {
            this.css = css;
            this.icon = icon;
            this.content = content;
        },
        reset: function () {
            this.set('', '', '');
        }
    };
});

app.controller('TranslationCtrl', ['$scope', '$http', '$timeout', 'ngTableParams', 'sharedMessage', function($scope, $http, $timeout, ngTableParams, sharedMessage) {
    $scope.locales = translationCfg.locales;
    $scope.editType = translationCfg.inputType;
    $scope.hideColBtnLabel = translationCfg.label.hideCol;
    $scope.invalidateCacheBtnLabel = translationCfg.label.invalidateCache;
    $scope.saveRowBtnLabel = translationCfg.label.saveRow;
    $scope.saveLabel = translationCfg.label.save;
    $scope.hideColSelector = false;
    $scope.saveMsg = sharedMessage;

    // columns definition
    $scope.columns = [
        { title: 'ID', index: 'id', edit: false, filter: false, sortable: true, visible: true },
        { title: translationCfg.label.domain, index: 'domain', edit: false, filter: {'domain': 'text'}, sortable: true, visible: true },
        { title: translationCfg.label.key, index: 'key', edit: false, filter: {'key': 'text'}, sortable: true, visible: true }
    ];

    for (var key in $scope.locales) {
        var columnDef = { title: $scope.locales[key].toUpperCase(), index: $scope.locales[key], edit: true, filter: {}, sortable: false, visible: true };
        columnDef['filter'][$scope.locales[key]] = 'text';

        $scope.columns.push(columnDef);
    }

    // grid data
    var tableData = {
        total: 0,
        currentSort: {},
        currentFilter: {},
        getData: function($defer, params) {
            var parameters = {};

            if (Object.keys(params.sorting()).length) {
                var keys = Object.keys(params.sorting());
                parameters['sidx'] = keys[0];
                parameters['sord'] = params.sorting()[keys[0]];

                if (!angular.equals(this.currentSort, params.sorting())) {
                    params.page(1);
                    this.currentSort = params.sorting();
                }
            }

            if (Object.keys(params.filter()).length) {
                parameters['_search'] = true;
                for (var key in params.filter()) {
                    parameters[key] = params.filter()[key];
                }

                if (!angular.equals(this.currentFilter, params.filter())) {
                    params.page(1);
                    this.currentFilter = params.filter();
                }
            }

            parameters['page'] = params.page();
            parameters['row'] = params.count();

            $http.get(translationCfg.url.list, {'params': parameters}).success(function (responseData) {
                $timeout(function() {
                    params.total(responseData.total);
                    $defer.resolve(responseData.translations);
                }, 100);
            });
        }
    };

    var defaultOptions = { page: 1, count: 20, filter: {}, sort: {'id': 'asc'} };

    $scope.tableParams = new ngTableParams(defaultOptions, tableData);

    // scope function
    $scope.sortGrid = function (column) {
        if (column.sortable) {
            $scope.tableParams.sorting( column.index, $scope.tableParams.isSortBy(column.index, 'asc') ? 'desc' : 'asc' );
        }
    };

    // invalidate the cache
    $scope.invalidateCache = function () {
        $http.get(translationCfg.url.invalidateCache, {headers: {'X-Requested-With': 'XMLHttpRequest'}})
            .success(function (responseData) {
                sharedMessage.set('text-success', 'ok-circle', responseData.message);
            }
        );
    };
}]);

app.directive('editableRow', ['$http', 'sharedMessage', function ($http, sharedMessage) {
    return {
        restrict: 'A',
        scope: {
            translation: '=translation',
            columns: '=columns',
            editType: '=editType'
        },
        template: $('#editable-row-template').html(),
        link: function ( $scope, element, attrs ) {
            $scope.message = null;
            $scope.edit = false;

            $scope.toggleEdit = function () {
                $scope.edit = !$scope.edit;
                sharedMessage.reset();
            };

            $scope.save = function (event) {
                if (event.which == 27) { // ecsape key
                    $scope.edit = false;

                } else if ( ($scope.editType == 'textarea' && event.type == 'click') || ($scope.editType == 'text' && event.which == 13) ) { // click btn OR return key
                    var url = translationCfg.url.update.replace('-id-', $scope.translation.id);

                    var parameters = [];
                    for (var name in $scope.translation) {
                        parameters.push(name+'='+encodeURIComponent($scope.translation[name]));
                    }

                    // force content type to make SF create a Request with the PUT parameters
                    $http({ 'url': url, 'data': parameters.join('&'), method: 'PUT', headers: {'Content-Type': 'application/x-www-form-urlencoded'} })
                        .success(function (data, status, headers, config) {
                            $scope.edit = false;
                            $scope.translation = data;
                            sharedMessage.set('text-success', 'ok-circle', translationCfg.label.successMsg.replace('%id%', data.id));
                        }).error(function (data, status, headers, config) {
                            sharedMessage.set('text-danger', 'remove-circle', translationCfg.label.errorMsg.replace('%id%', $scope.translation.id));
                        });
                }
            };
        }
    };
}]);
<commit_msg>fixed parameter name<commit_after>'use strict';

var app = angular.module('translationApp', ['ngTable']);

app.factory('sharedMessage', function () {
    return {
        css: '',
        icon: '',
        content: '',
        set: function (css, icon, content) {
            this.css = css;
            this.icon = icon;
            this.content = content;
        },
        reset: function () {
            this.set('', '', '');
        }
    };
});

app.controller('TranslationCtrl', ['$scope', '$http', '$timeout', 'ngTableParams', 'sharedMessage', function($scope, $http, $timeout, ngTableParams, sharedMessage) {
    $scope.locales = translationCfg.locales;
    $scope.editType = translationCfg.inputType;
    $scope.hideColBtnLabel = translationCfg.label.hideCol;
    $scope.invalidateCacheBtnLabel = translationCfg.label.invalidateCache;
    $scope.saveRowBtnLabel = translationCfg.label.saveRow;
    $scope.saveLabel = translationCfg.label.save;
    $scope.hideColSelector = false;
    $scope.saveMsg = sharedMessage;

    // columns definition
    $scope.columns = [
        { title: 'ID', index: 'id', edit: false, filter: false, sortable: true, visible: true },
        { title: translationCfg.label.domain, index: 'domain', edit: false, filter: {'domain': 'text'}, sortable: true, visible: true },
        { title: translationCfg.label.key, index: 'key', edit: false, filter: {'key': 'text'}, sortable: true, visible: true }
    ];

    for (var key in $scope.locales) {
        var columnDef = { title: $scope.locales[key].toUpperCase(), index: $scope.locales[key], edit: true, filter: {}, sortable: false, visible: true };
        columnDef['filter'][$scope.locales[key]] = 'text';

        $scope.columns.push(columnDef);
    }

    // grid data
    var tableData = {
        total: 0,
        currentSort: {},
        currentFilter: {},
        getData: function($defer, params) {
            var parameters = {};

            if (Object.keys(params.sorting()).length) {
                var keys = Object.keys(params.sorting());
                parameters['sidx'] = keys[0];
                parameters['sord'] = params.sorting()[keys[0]];

                if (!angular.equals(this.currentSort, params.sorting())) {
                    params.page(1);
                    this.currentSort = params.sorting();
                }
            }

            if (Object.keys(params.filter()).length) {
                parameters['_search'] = true;
                for (var key in params.filter()) {
                    parameters[key] = params.filter()[key];
                }

                if (!angular.equals(this.currentFilter, params.filter())) {
                    params.page(1);
                    this.currentFilter = params.filter();
                }
            }

            parameters['page'] = params.page();
            parameters['rows'] = params.count();

            $http.get(translationCfg.url.list, {'params': parameters}).success(function (responseData) {
                $timeout(function() {
                    params.total(responseData.total);
                    $defer.resolve(responseData.translations);
                }, 100);
            });
        }
    };

    var defaultOptions = { page: 1, count: 20, filter: {}, sort: {'id': 'asc'} };

    $scope.tableParams = new ngTableParams(defaultOptions, tableData);

    // scope function
    $scope.sortGrid = function (column) {
        if (column.sortable) {
            $scope.tableParams.sorting( column.index, $scope.tableParams.isSortBy(column.index, 'asc') ? 'desc' : 'asc' );
        }
    };

    // invalidate the cache
    $scope.invalidateCache = function () {
        $http.get(translationCfg.url.invalidateCache, {headers: {'X-Requested-With': 'XMLHttpRequest'}})
            .success(function (responseData) {
                sharedMessage.set('text-success', 'ok-circle', responseData.message);
            }
        );
    };
}]);

app.directive('editableRow', ['$http', 'sharedMessage', function ($http, sharedMessage) {
    return {
        restrict: 'A',
        scope: {
            translation: '=translation',
            columns: '=columns',
            editType: '=editType'
        },
        template: $('#editable-row-template').html(),
        link: function ( $scope, element, attrs ) {
            $scope.message = null;
            $scope.edit = false;

            $scope.toggleEdit = function () {
                $scope.edit = !$scope.edit;
                sharedMessage.reset();
            };

            $scope.save = function (event) {
                if (event.which == 27) { // ecsape key
                    $scope.edit = false;

                } else if ( ($scope.editType == 'textarea' && event.type == 'click') || ($scope.editType == 'text' && event.which == 13) ) { // click btn OR return key
                    var url = translationCfg.url.update.replace('-id-', $scope.translation.id);

                    var parameters = [];
                    for (var name in $scope.translation) {
                        parameters.push(name+'='+encodeURIComponent($scope.translation[name]));
                    }

                    // force content type to make SF create a Request with the PUT parameters
                    $http({ 'url': url, 'data': parameters.join('&'), method: 'PUT', headers: {'Content-Type': 'application/x-www-form-urlencoded'} })
                        .success(function (data, status, headers, config) {
                            $scope.edit = false;
                            $scope.translation = data;
                            sharedMessage.set('text-success', 'ok-circle', translationCfg.label.successMsg.replace('%id%', data.id));
                        }).error(function (data, status, headers, config) {
                            sharedMessage.set('text-danger', 'remove-circle', translationCfg.label.errorMsg.replace('%id%', $scope.translation.id));
                        });
                }
            };
        }
    };
}]);
<|endoftext|>


<commit_before>/**
 * This file is part of DrupalCon Mobile.
 *
 * DrupalCon Mobile 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.
 *
 * DrupalCon Mobile 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 DrupalCon Mobile.  If not, see <http://www.gnu.org/licenses/>.
 */

var Twitter = {
  ui: {},
  util: {}
};

(function() {
  var tweetCount = 50;
  var createTwitterTable = function(search) {
  	  return Ti.UI.createTableView({
  	  	  height:'100%',
          width:'100%',
          viewTitle:search
  	  });
  }
  var viewsToLoad = [
    {
  		search:'@appcelerator',
  		url: 'http://api.twitter.com/1/statuses/user_timeline.json?screen_name=appcelerator&count=' + tweetCount,
  		table: createTwitterTable('@appcelerator'),
  		isSearch: false
  	},
  	{
  		search:'@codestrong',
  		url: 'http://api.twitter.com/1/statuses/user_timeline.json?screen_name=codestrong&count=' + tweetCount,
  		table: createTwitterTable('@codestrong'),
  		isSearch: false
  	},
  	{
  		search:'#codestrong',
  		url: 'http://search.twitter.com/search.json?q=%23codestrong&result_type=recent&rpp=' + tweetCount,
  		table: createTwitterTable('#codestrong'),
  		isSearch: true
  	}
  ];
  var loadedViews = [];

  DrupalCon.ui.createTwitterWindow = function(tabGroup) {
    var twitterWindow = Titanium.UI.createWindow({
      id: 'twitterWindow',
      title: 'Twitter News',
      backgroundColor: '#FFF',
      barColor: '#414444',
      tabGroup: tabGroup
    });
    var tabbedBarView = Ti.UI.createView({
    	backgroundColor:'#880000',
    	borderColor: '#000',
    	borderWidth: 1,
    	top:0,
    	height:36
    });
    var tabbedBar = Ti.UI.createView({
    	height:36,
    	width:306,
    	layout:'horizontal'
    });

    for (var index in viewsToLoad) {
    	myEntry = viewsToLoad[index];
  		myEntry.table.addEventListener('click', function(e) {
			var currentTab = isAndroid() ? Titanium.UI.currentTab : twitterWindow.tabGroup.activeTab;
    		currentTab.open(DrupalCon.ui.createTwitterDetailWindow({
      			title: e.rowData.user,
      			text: e.rowData.tweet,
      			name: e.rowData.user,
      			date: e.rowData.date,
      			tabGroup: currentTab
    		}), {animated:true});
		});

		var tabView = Ti.UI.createView({
			top:3,
			backgroundColor: (index == 0) ? '#666' : '#222',
			borderRadius:8,
			borderColor:'#000',
			borderWidth:1,
			height:30,
			width: 100,
			index: index
		});
		var tabLabel = Ti.UI.createLabel({
			text: myEntry.search,
			textAlign:'center',
			color: '#fff',
			height:'auto',
			width:'100%',
			touchEnabled: false,
			font: {
				fontSize:14
			}
		});
		tabView.addEventListener('click', function(e) {
			for (var i = 0; i < viewsToLoad.length; i++) {
				viewsToLoad[i].tabView.backgroundColor = '#222';
				if (e.source.index == i) {
					scrollable.scrollToView(viewsToLoad[i].table);
				}
			}
			e.source.backgroundColor = '#666';
		});

		tabView.add(tabLabel);
		if (index != 0) {
			tabbedBar.add(Ti.UI.createView({width:3}));
		}
        tabbedBar.add(tabView);
        myEntry.tabView = tabView;
    }

    var scrollable = Ti.UI.createScrollableView({
		showPagingControl: true,
		backgroundColor: '#000000',
		top:30,
		views:[
			viewsToLoad[0].table,
			viewsToLoad[1].table,
			viewsToLoad[2].table
		]
	});
	scrollable.addEventListener('scroll', function(e) {
		if (e.view) {
			//twitterWindow.title = e.view.viewTitle;
			viewsToLoad[e.currentPage].tabView.fireEvent('click');
		}
	});

	if (!isAndroid()) {
		Titanium.Gesture.addEventListener('orientationchange', function(e){
	    	scrollable.scrollToView(scrollable.currentPage);
		});
	}
	twitterWindow.add(scrollable);
	tabbedBarView.add(tabbedBar);
	twitterWindow.add(tabbedBarView);

    // Using the parsing method shown https://gist.github.com/819929
    var tweetWebJs = "document.body.addEventListener('touchmove', function(e) { e.preventDefault();}, false);";
    var baseHTMLStart = '',
        baseHTMLEnd = '';

    // set this to true if you are only tracking one user
    var single = true;

    var net = Titanium.Network;
    var up = net.online;

    var getTweets = function(entry) {
      // create table view data object
      var data = [];

      var xhr = Ti.Network.createHTTPClient();
      xhr.timeout = 100000;
      xhr.open("GET", entry.url);

      xhr.onload = function() {
        try {
          var json = eval('('+this.responseText+')');
          var tweets = entry.isSearch ? json.results : json;
          for (var c=0;c<tweets.length;c++) {
            var tweet = tweets[c].text;
            var user = entry.isSearch ? tweets[c].from_user : tweets[c].user.screen_name;
            var avatarWidth = 48;
            var avatar;
            if (single ==  true && !entry.isSearch) {
              avatar = tweets[1].user.profile_image_url;
            }
            else {
              avatar = entry.isSearch ? tweets[c].profile_image_url : tweets[c].user.profile_image_url;

            }
            var created_at = prettyDate(strtotime(tweets[c].created_at));
            var bgcolor = (c % 2) === 0 ? '#fff' : '#eee';

            var row = Ti.UI.createTableViewRow({
              hasChild:true,
              backgroundColor:bgcolor,
              height:'auto',
              date:created_at,
              user:user,
              tweet:tweet
            });

            // Create a vertical layout view to hold all the info labels and images for each tweet
            var post_view = Ti.UI.createView({
              height:15,
              left:64,
              top:10,
              right:5
            });

            var av = Ti.UI.createImageView({
              image:avatar,
              left:10,
              top:10,
              height:48,
              width:avatarWidth
            });
            // Add the avatar image to the view
            row.add(av);

            var user_label = Ti.UI.createLabel({
              text:user,
              left:0,
              width:120,
              top:-3,
              height:20,
              textAlign:'left',
              color:'#444444',
              font:{
                fontFamily:'Trebuchet MS',
                fontSize:14,
                fontWeight:'bold'
              }
            });
            // Add the username to the view
            post_view.add(user_label);

            var date_label = Ti.UI.createLabel({
              text:created_at,
              right:20,
              top:-2,
              height:20,
              textAlign:'right',
              width:110,
              color:'#444444',
              font:{
                fontFamily:'Trebuchet MS',
                fontSize:12
              }
            });
            // Add the date to the view
            post_view.add(date_label);
            // Add the vertical layout view to the row
            row.add(post_view);

            var tweet_text = Ti.UI.createLabel({
              text:tweet,
              left:64,
              top:30,
              right:20,
              color:'#333',
              //width:'auto',
              height:'auto',
              textAlign:'left',
              bottom: 10,
              font:{
                fontSize:14
              }
            });

            // Add the tweet to the view
            row.add(tweet_text);
            data[c] = row;
          }

          Titanium.App.Properties.setString("lastTweet",tweet);

          entry.table.setData(data);
          loadedViews.push(entry.table);
          if (loadedViews.length == viewsToLoad.length) {
			loadedViews = [];
			DrupalCon.ui.activityIndicator.hideModal();
          }
        }
        catch(e) {
          Ti.API.info(e);
        }
      };
      // Get the data
      xhr.send();
    }

	var reloadAllTweets = function() {
		DrupalCon.ui.activityIndicator.showModal('Loading latest tweets...');
	  	for (var i = 0; i < viewsToLoad.length; i++) {
	  		getTweets(viewsToLoad[i]);
	  	}
	  };

    // Get the tweets for 'twitter_name'
    if (up) {
      reloadAllTweets();

      if (Ti.Platform.name == 'android') {
        twitterWindow.activity.onCreateOptionsMenu = function(e) {
          var menu = e.menu;

          var m1 = menu.add({
            title : 'Refresh Tweets'
          });
          m1.addEventListener('click', function(e) {
            reloadAllTweets();
          });
        };
      }
      else {
        //create iphone menu.
        var index = 0;
        var button = Ti.UI.createButton({
          systemButton: Ti.UI.iPhone.SystemButton.REFRESH

        });
        twitterWindow.rightNavButton = button;
        button.addEventListener('click', function(e) {
          reloadAllTweets();
        });
      }
    }
    else {
      Ti.API.info("No active network connection.  Please try again when you are connected.");
    }

    return twitterWindow;
  };

})();

<commit_msg>widened border<commit_after>/**
 * This file is part of DrupalCon Mobile.
 *
 * DrupalCon Mobile 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.
 *
 * DrupalCon Mobile 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 DrupalCon Mobile.  If not, see <http://www.gnu.org/licenses/>.
 */

var Twitter = {
  ui: {},
  util: {}
};

(function() {
  var tweetCount = 50;
  var createTwitterTable = function(search) {
  	  return Ti.UI.createTableView({
  	  	  height:'100%',
          width:'100%',
          viewTitle:search
  	  });
  }
  var viewsToLoad = [
    {
  		search:'@appcelerator',
  		url: 'http://api.twitter.com/1/statuses/user_timeline.json?screen_name=appcelerator&count=' + tweetCount,
  		table: createTwitterTable('@appcelerator'),
  		isSearch: false
  	},
  	{
  		search:'@codestrong',
  		url: 'http://api.twitter.com/1/statuses/user_timeline.json?screen_name=codestrong&count=' + tweetCount,
  		table: createTwitterTable('@codestrong'),
  		isSearch: false
  	},
  	{
  		search:'#codestrong',
  		url: 'http://search.twitter.com/search.json?q=%23codestrong&result_type=recent&rpp=' + tweetCount,
  		table: createTwitterTable('#codestrong'),
  		isSearch: true
  	}
  ];
  var loadedViews = [];

  DrupalCon.ui.createTwitterWindow = function(tabGroup) {
    var twitterWindow = Titanium.UI.createWindow({
      id: 'twitterWindow',
      title: 'Twitter News',
      backgroundColor: '#FFF',
      barColor: '#414444',
      tabGroup: tabGroup
    });
    var tabbedBarView = Ti.UI.createView({
    	backgroundColor:'#880000',
    	borderColor: '#000',
    	borderWidth: 1,
    	top:0,
    	height:36
    });
    var tabbedBar = Ti.UI.createView({
    	height:36,
    	width:306,
    	layout:'horizontal'
    });

    for (var index in viewsToLoad) {
    	myEntry = viewsToLoad[index];
  		myEntry.table.addEventListener('click', function(e) {
			var currentTab = isAndroid() ? Titanium.UI.currentTab : twitterWindow.tabGroup.activeTab;
    		currentTab.open(DrupalCon.ui.createTwitterDetailWindow({
      			title: e.rowData.user,
      			text: e.rowData.tweet,
      			name: e.rowData.user,
      			date: e.rowData.date,
      			tabGroup: currentTab
    		}), {animated:true});
		});

		var tabView = Ti.UI.createView({
			top:3,
			backgroundColor: (index == 0) ? '#666' : '#222',
			borderRadius:8,
			borderColor:'#000',
			borderWidth:2,
			height:30,
			width: 100,
			index: index
		});
		var tabLabel = Ti.UI.createLabel({
			text: myEntry.search,
			textAlign:'center',
			color: '#fff',
			height:'auto',
			width:'100%',
			touchEnabled: false,
			font: {
				fontSize:14
			}
		});
		tabView.addEventListener('click', function(e) {
			for (var i = 0; i < viewsToLoad.length; i++) {
				viewsToLoad[i].tabView.backgroundColor = '#222';
				if (e.source.index == i) {
					scrollable.scrollToView(viewsToLoad[i].table);
				}
			}
			e.source.backgroundColor = '#666';
		});

		tabView.add(tabLabel);
		if (index != 0) {
			tabbedBar.add(Ti.UI.createView({width:3}));
		}
        tabbedBar.add(tabView);
        myEntry.tabView = tabView;
    }

    var scrollable = Ti.UI.createScrollableView({
		showPagingControl: true,
		backgroundColor: '#000000',
		top:30,
		views:[
			viewsToLoad[0].table,
			viewsToLoad[1].table,
			viewsToLoad[2].table
		]
	});
	scrollable.addEventListener('scroll', function(e) {
		if (e.view) {
			//twitterWindow.title = e.view.viewTitle;
			viewsToLoad[e.currentPage].tabView.fireEvent('click');
		}
	});

	if (!isAndroid()) {
		Titanium.Gesture.addEventListener('orientationchange', function(e){
	    	scrollable.scrollToView(scrollable.currentPage);
		});
	}
	twitterWindow.add(scrollable);
	tabbedBarView.add(tabbedBar);
	twitterWindow.add(tabbedBarView);

    // Using the parsing method shown https://gist.github.com/819929
    var tweetWebJs = "document.body.addEventListener('touchmove', function(e) { e.preventDefault();}, false);";
    var baseHTMLStart = '',
        baseHTMLEnd = '';

    // set this to true if you are only tracking one user
    var single = true;

    var net = Titanium.Network;
    var up = net.online;

    var getTweets = function(entry) {
      // create table view data object
      var data = [];

      var xhr = Ti.Network.createHTTPClient();
      xhr.timeout = 100000;
      xhr.open("GET", entry.url);

      xhr.onload = function() {
        try {
          var json = eval('('+this.responseText+')');
          var tweets = entry.isSearch ? json.results : json;
          for (var c=0;c<tweets.length;c++) {
            var tweet = tweets[c].text;
            var user = entry.isSearch ? tweets[c].from_user : tweets[c].user.screen_name;
            var avatarWidth = 48;
            var avatar;
            if (single ==  true && !entry.isSearch) {
              avatar = tweets[1].user.profile_image_url;
            }
            else {
              avatar = entry.isSearch ? tweets[c].profile_image_url : tweets[c].user.profile_image_url;

            }
            var created_at = prettyDate(strtotime(tweets[c].created_at));
            var bgcolor = (c % 2) === 0 ? '#fff' : '#eee';

            var row = Ti.UI.createTableViewRow({
              hasChild:true,
              backgroundColor:bgcolor,
              height:'auto',
              date:created_at,
              user:user,
              tweet:tweet
            });

            // Create a vertical layout view to hold all the info labels and images for each tweet
            var post_view = Ti.UI.createView({
              height:15,
              left:64,
              top:10,
              right:5
            });

            var av = Ti.UI.createImageView({
              image:avatar,
              left:10,
              top:10,
              height:48,
              width:avatarWidth
            });
            // Add the avatar image to the view
            row.add(av);

            var user_label = Ti.UI.createLabel({
              text:user,
              left:0,
              width:120,
              top:-3,
              height:20,
              textAlign:'left',
              color:'#444444',
              font:{
                fontFamily:'Trebuchet MS',
                fontSize:14,
                fontWeight:'bold'
              }
            });
            // Add the username to the view
            post_view.add(user_label);

            var date_label = Ti.UI.createLabel({
              text:created_at,
              right:20,
              top:-2,
              height:20,
              textAlign:'right',
              width:110,
              color:'#444444',
              font:{
                fontFamily:'Trebuchet MS',
                fontSize:12
              }
            });
            // Add the date to the view
            post_view.add(date_label);
            // Add the vertical layout view to the row
            row.add(post_view);

            var tweet_text = Ti.UI.createLabel({
              text:tweet,
              left:64,
              top:30,
              right:20,
              color:'#333',
              //width:'auto',
              height:'auto',
              textAlign:'left',
              bottom: 10,
              font:{
                fontSize:14
              }
            });

            // Add the tweet to the view
            row.add(tweet_text);
            data[c] = row;
          }

          Titanium.App.Properties.setString("lastTweet",tweet);

          entry.table.setData(data);
          loadedViews.push(entry.table);
          if (loadedViews.length == viewsToLoad.length) {
			loadedViews = [];
			DrupalCon.ui.activityIndicator.hideModal();
          }
        }
        catch(e) {
          Ti.API.info(e);
        }
      };
      // Get the data
      xhr.send();
    }

	var reloadAllTweets = function() {
		DrupalCon.ui.activityIndicator.showModal('Loading latest tweets...');
	  	for (var i = 0; i < viewsToLoad.length; i++) {
	  		getTweets(viewsToLoad[i]);
	  	}
	  };

    // Get the tweets for 'twitter_name'
    if (up) {
      reloadAllTweets();

      if (Ti.Platform.name == 'android') {
        twitterWindow.activity.onCreateOptionsMenu = function(e) {
          var menu = e.menu;

          var m1 = menu.add({
            title : 'Refresh Tweets'
          });
          m1.addEventListener('click', function(e) {
            reloadAllTweets();
          });
        };
      }
      else {
        //create iphone menu.
        var index = 0;
        var button = Ti.UI.createButton({
          systemButton: Ti.UI.iPhone.SystemButton.REFRESH

        });
        twitterWindow.rightNavButton = button;
        button.addEventListener('click', function(e) {
          reloadAllTweets();
        });
      }
    }
    else {
      Ti.API.info("No active network connection.  Please try again when you are connected.");
    }

    return twitterWindow;
  };

})();

<|endoftext|>


<commit_before>/*
*
* Copyright (C) 2011, The Locker Project
* All rights reserved.
*
* Please see the LICENSE file for more information.
*
*/

var request = require('request'),
    lfs = require('../lfs.js'),
    fs = require('fs'),
    options = {provider :            'Some oauth2 consumer',
               endPoint :            'http://consumer.com/oauth/',
               linkToCreate :        'http://change.me/',
               appIDName :           'App ID',
               authEndpoint :        'authorize',
               appSecretName :       'App Secret',
               promptForUsername :   false,
               accessTokenResponse : 'text',
               grantType :           '',
               extraParams :         ''};

var completedCallback, me;

exports.auth = {};
exports.options = {};

exports.authAndRun = function(app, onCompletedCallback) {
    me = app.meData;
    for (i in exports.options) {
        options[i] = exports.options[i];
    }
    if(exports.isAuthed()) {
        onCompletedCallback();
        return;
    }
    completedCallback = onCompletedCallback;
    app.get('/go', go);
    app.get('/auth', handleAuth);
    app.post('/saveAuth', saveAuth);
};

exports.isAuthed = function() {
    try {
        if(!exports.auth)
            exports.auth = {};

        // Already have the stuff read
        if(exports.auth.hasOwnProperty("accessToken"))
            return true;

        console.error('isAuthed.reading in from', process.cwd());
        // Try to read it in
        var authData = JSON.parse(fs.readFileSync('auth.json', 'utf-8'));
        console.error('isAuthed.read and parsed', authData);
        if(authData.hasOwnProperty("accessToken")) {
            exports.auth = authData;
            return true;
        }
    } catch (E) {
        // TODO:  Could actually check the error type here
    }
    return false;
};

function go(req, res) {
    if(!(exports.auth.appKey && exports.auth.appSecret)) {
        if (options.promptForUsername) {
            var prompt = "Username: <input name='username'>
";
        } else {
            var prompt = "";
        }
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end("Enter your personal " + options.provider + " app info that will be used to sync your data" +
                " (create a new one here" +
                " using a callback url of " + me.uri + "auth/) " +
                "<form method='post' action='saveAuth'>" +
                    prompt +
                    options.appIDName + ": <input name='appKey'>
" +
                    options.appSecretName + ": <input name='appSecret'>
" +
                    "<input type='submit' value='Save'>" +
                "</form>");
    } else {
        var newUrl = options.endPoint + "/" + options.authEndpoint + '?client_id=' + exports.auth.appKey +
                        '&response_type=code&redirect_uri=' + me.uri + 'auth/';
        sys.debug('redirecting to ' + newUrl + 'auth');
        if (options.extraParams) {
            newUrl += "&" + options.extraParams;
        }
        res.redirect(newUrl);
    }
}

function handleAuth(req, res) {
    var newUrl = options.endPoint + '/access_token' +
                    '?client_id=' + exports.auth.appKey +
                    '&client_secret=' + exports.auth.appSecret +
                    '&grant_type=' + options.grantType +
                    '&redirect_uri=' + me.uri + 'auth/' +
                    '&code=' + req.param('code');
    request.get({url:newUrl}, function(err, resp, body) {
        if (options.accessTokenResponse == 'json') {
            exports.auth.accessToken = JSON.parse(body).access_token;
        } else {
            console.log("resp", resp);
            console.log("body", body);
            exports.auth.accessToken = querystring.parse(body).access_token;
        }
        lfs.writeObjectToFile("auth.json", exports.auth);
        completedCallback(exports.auth);
        res.redirect(me.uri);
    });
}

function saveAuth(req, res) {
    // res.writeHead(200, {'Content-Type': 'text/html'});
    if(!req.body.appKey || !req.body.appSecret) {
        res.end("missing field(s)?");
        return;
    }
    exports.auth.username = req.param('username') || '';
    exports.auth.appKey = req.param('appKey');
    exports.auth.appSecret = req.param('appSecret');
    res.redirect(me.uri + 'go');
}<commit_msg>debug code<commit_after>/*
*
* Copyright (C) 2011, The Locker Project
* All rights reserved.
*
* Please see the LICENSE file for more information.
*
*/

var request = require('request'),
    lfs = require('../lfs.js'),
    fs = require('fs'),
    options = {provider :            'Some oauth2 consumer',
               endPoint :            'http://consumer.com/oauth/',
               linkToCreate :        'http://change.me/',
               appIDName :           'App ID',
               authEndpoint :        'authorize',
               appSecretName :       'App Secret',
               promptForUsername :   false,
               accessTokenResponse : 'text',
               grantType :           '',
               extraParams :         ''};

var completedCallback, me;

exports.auth = {};
exports.options = {};

exports.authAndRun = function(app, onCompletedCallback) {
    me = app.meData;
    for (i in exports.options) {
        options[i] = exports.options[i];
    }
    if(exports.isAuthed()) {
        onCompletedCallback();
        return;
    }
    completedCallback = onCompletedCallback;
    app.get('/go', go);
    app.get('/auth', handleAuth);
    app.post('/saveAuth', saveAuth);
};

exports.isAuthed = function() {
    try {
        if(!exports.auth)
            exports.auth = {};

        // Already have the stuff read
        if(exports.auth.hasOwnProperty("accessToken"))
            return true;

        // Try to read it in
        var authData = JSON.parse(fs.readFileSync('auth.json', 'utf-8'));
        if(authData.hasOwnProperty("accessToken")) {
            exports.auth = authData;
            return true;
        }
    } catch (E) {
        // TODO:  Could actually check the error type here
    }
    return false;
};

function go(req, res) {
    if(!(exports.auth.appKey && exports.auth.appSecret)) {
        if (options.promptForUsername) {
            var prompt = "Username: <input name='username'>
";
        } else {
            var prompt = "";
        }
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end("Enter your personal " + options.provider + " app info that will be used to sync your data" +
                " (create a new one here" +
                " using a callback url of " + me.uri + "auth/) " +
                "<form method='post' action='saveAuth'>" +
                    prompt +
                    options.appIDName + ": <input name='appKey'>
" +
                    options.appSecretName + ": <input name='appSecret'>
" +
                    "<input type='submit' value='Save'>" +
                "</form>");
    } else {
        var newUrl = options.endPoint + "/" + options.authEndpoint + '?client_id=' + exports.auth.appKey +
                        '&response_type=code&redirect_uri=' + me.uri + 'auth/';
        sys.debug('redirecting to ' + newUrl + 'auth');
        if (options.extraParams) {
            newUrl += "&" + options.extraParams;
        }
        res.redirect(newUrl);
    }
}

function handleAuth(req, res) {
    var newUrl = options.endPoint + '/access_token' +
                    '?client_id=' + exports.auth.appKey +
                    '&client_secret=' + exports.auth.appSecret +
                    '&grant_type=' + options.grantType +
                    '&redirect_uri=' + me.uri + 'auth/' +
                    '&code=' + req.param('code');
    request.get({url:newUrl}, function(err, resp, body) {
        if (options.accessTokenResponse == 'json') {
            exports.auth.accessToken = JSON.parse(body).access_token;
        } else {
            console.log("resp", resp);
            console.log("body", body);
            exports.auth.accessToken = querystring.parse(body).access_token;
        }
        lfs.writeObjectToFile("auth.json", exports.auth);
        completedCallback(exports.auth);
        res.redirect(me.uri);
    });
}

function saveAuth(req, res) {
    // res.writeHead(200, {'Content-Type': 'text/html'});
    if(!req.body.appKey || !req.body.appSecret) {
        res.end("missing field(s)?");
        return;
    }
    exports.auth.username = req.param('username') || '';
    exports.auth.appKey = req.param('appKey');
    exports.auth.appSecret = req.param('appSecret');
    res.redirect(me.uri + 'go');
}<|endoftext|>


<commit_before>$(document).ready(function() {
    $.fn.extend({
        samsonSelect2: function(options) {
            options = $.extend({}, options);
            var $el = $(this);
            var url = undefined !== typeof(options.url) ? options.url : null;

            $(this).select2($.extend({
                placeholder: "",
                allowClear: true,
                initSelection: function(element, callback) {
                    callback({
                        id: this,
                        text: element.data('display-value')
                    })
                },
                query: function(options) {
                    clearTimeout($el.data('timeout'));

                    $el.data('timeout', setTimeout(function() {
                        if (typeof($el.data('ajax')) != 'undefined') {
                            $el.data('ajax').abort();
                        }

                        var data = $el.closest('form').serialize();
                        data = data + "&__autocomplete_page_limit=" + 10;
                        data = data + "&__autocomplete_page=" + options.page;
                        data = data + "&__autocomplete_path=" + escape($el.attr('name'));
                        data = data + "&__autocomplete_search=" + escape(options.term);

                        $el.data('ajax', $.ajax({
                            url: url ? url : $el.closest('form').attr('action'),
                            dataType: 'json',
                            type: 'POST',
                            data: data,
                            success: function(data) {
                                options.callback({
                                    results: data.results,
                                    more: data.total > options.page * 10
                                });
                            },
                            error: function(xhr,b,c) {
                                if (xhr.statusText == 'abort') {
                                    return;
                                }
                                $('.select2-searching').text('An error occurred! ');

                                var token = xhr.getResponseHeader('x-debug-token');
                                if (token) {
                                    $('.select2-searching').append($("<a>", { href: '/_profiler/'+token+"?panel=exception", target: '_blank' }).text('More info'));
                                }

                            }
                        }));
                    }, 100));

                },
                formatResult: function(object, container, query) {
                    return object.textHighlight;
                },
                dropdownCss: function() {
                    return {
                        width: 'auto',
                        minWidth: $el.width()+'px'
                    }
                },
                dropdownCssClass: 'samson-autocomplete'
            }, options));
            if (!$(this).val() && $(this).data('display-value')) {
                $(this).select2('open')
                $(this).select2('container').find('input[type="text"]').val($(this).data('display-value')).trigger('keydown');
            }
        }
    });
});<commit_msg>Update autocomplete.js<commit_after>$(document).ready(function() {
    $.fn.extend({
        samsonSelect2: function(options) {
            options = $.extend({}, options);
            var $el = $(this);
            var url = undefined !== typeof(options.url) ? options.url : null;

            $(this).select2($.extend({
                placeholder: "",
                allowClear: true,
                initSelection: function(element, callback) {
                    callback({
                        id: this,
                        text: element.data('display-value')
                    })
                },
                query: function(options) {
                    clearTimeout($el.data('timeout'));

                    $el.data('timeout', setTimeout(function() {
                        if (typeof($el.data('ajax')) != 'undefined') {
                            $el.data('ajax').abort();
                        }

                        var data = $el.closest('form').serialize();
                        data = data + "&__autocomplete_page_limit=" + 10;
                        data = data + "&__autocomplete_page=" + options.page;
                        data = data + "&__autocomplete_path=" + encodeURIComponent($el.attr('name'));
                        data = data + "&__autocomplete_search=" + encodeURIComponent(options.term);

                        $el.data('ajax', $.ajax({
                            url: url ? url : $el.closest('form').attr('action'),
                            dataType: 'json',
                            type: 'POST',
                            data: data,
                            success: function(data) {
                                options.callback({
                                    results: data.results,
                                    more: data.total > options.page * 10
                                });
                            },
                            error: function(xhr,b,c) {
                                if (xhr.statusText == 'abort') {
                                    return;
                                }
                                $('.select2-searching').text('An error occurred! ');

                                var token = xhr.getResponseHeader('x-debug-token');
                                if (token) {
                                    $('.select2-searching').append($("<a>", { href: '/_profiler/'+token+"?panel=exception", target: '_blank' }).text('More info'));
                                }

                            }
                        }));
                    }, 100));

                },
                formatResult: function(object, container, query) {
                    return object.textHighlight;
                },
                dropdownCss: function() {
                    return {
                        width: 'auto',
                        minWidth: $el.width()+'px'
                    }
                },
                dropdownCssClass: 'samson-autocomplete'
            }, options));
            if (!$(this).val() && $(this).data('display-value')) {
                $(this).select2('open')
                $(this).select2('container').find('input[type="text"]').val($(this).data('display-value')).trigger('keydown');
            }
        }
    });
});
<|endoftext|>


<commit_before>
// WineReview.js
// Author: Matthew Johnson  & David Wells

function WineReview(wine, friend){
	var global = require('ui/common/globals');
	var self = global.createWindow('');
	self.barImage='images/iPhone_Nav_Bar_With_Bkgrd.png';
	var all = wine.all_information;

	var overview = Ti.UI.createView({
		height: '100%',
		width: '100%',
		layout: 'vertical'
	});
	Ti.API.info(all.Labels[0].Url);
	// Add the header to the view.
	var header = require('ui/handheld/Wine_Review/header');
	var head = header(
			wine.name,
			all.Vineyard.Name,
			all.Appellation.Name,
			all.Appellation.Region.Name,
			all.Labels[0].Url
	);
	overview.add(head);
	if(friend)
		overview.add(Ti.UI.createLabel({
			text: friend.fname + "'s Reviews of this wine",
			width: Ti.UI.SIZE,
			height: Ti.UI.SIZE,
			left: 10
		}));
	get_checkin_view = require('ui/handheld/Wine_Review/Checkin');

	var ch = get_checkin_view(all);
	var dd = require('ui/common/elements/dropdown');
	var tableview = null;
	function load_tables(){
		//alert("wineid: "+ JSON.stringify(wine));
		var uid = null;
		if(friend)
			uid = friend.user_id;
		global.api.previous_checkins(wine.id, uid, function(data){
			//alert(JSON.stringify(data));
			if(tableview != null)
				overview.remove(tableview);

			var reviews = [];

			for (var i = 0; i < data.length; i++) {
				var review = data[i];
				var r = Ti.UI.createTableViewRow({
					hasChild:false,
					selectionStyle: 'none',
					layout: 'vertical'
				});

				var rv = Ti.UI.createView({
					layout: 'vertical',
					height: Ti.UI.SIZE,
					width: Ti.UI.FILL,
				});
				r.add(rv);
				rv.add(Ti.UI.createLabel({
					color: 'black',
	    			top: 10,
	    			left: 10,
	    			right: 10,
	    			backgroundColor: global.colors.dark,
					text: "Rating: "+review.rating + " by " +review.friend.fname+" "+review.friend.lname+ "\nDate: " +review.date,
	    			//backgroundColor: global.colors.dark,
					//text: "Rating: "+review.rating + "\nDate: " +review.Date,
					height: Ti.UI.SIZE,
					width: Ti.UI.FILL
				}));

				rv.add(Ti.UI.createLabel({
					text: '"'+review.comment + '"',
					height: Ti.UI.SIZE,
					width: Ti.UI.FILL,
					bottom: 10,
					left: 10,
	    			right: 10,
				}));

				reviews.push(r);

			}
			// create table view
			tableview = Titanium.UI.createTableView({
				data:reviews,
				width: Ti.UI.FILL,
				height: Ti.UI.FILL,
				backgroundColor:'transparent'
			});

			overview.add(tableview);
		});
	};
	load_tables();
	dd(ch.view, self, "Finish Check-In", "Check-In", "up", function(){
		//alert("wine: "+ all.Id + " "+ ch.ta.value + " - " + Math.round(ch.rating.value));
		global.api.checkin(wine.id, ch.ta.value, Math.round(ch.rating.value), function(){
			load_tables();
		});
	});
	self.add(overview);
	return self;
};

module.exports = WineReview;<commit_msg>Added back button to wine review<commit_after>
// WineReview.js
// Author: Matthew Johnson  & David Wells

function WineReview(wine, friend){
	var global = require('ui/common/globals');
	var self = global.createWindow('');
	self.barImage='images/iPhone_Nav_Bar_With_Bkgrd.png';
	var all = wine.all_information;

	// Creates back button
	var back = Ti.UI.createButton({ title: "Back" });
 	back.addEventListener("click", function()
	{
 		self.close({animated:true});
	});
	self.setLeftNavButton(back);

	var overview = Ti.UI.createView({
		height: '100%',
		width: '100%',
		layout: 'vertical'
	});
	Ti.API.info(all.Labels[0].Url);
	// Add the header to the view.
	var header = require('ui/handheld/Wine_Review/header');
	var head = header(
			wine.name,
			all.Vineyard.Name,
			all.Appellation.Name,
			all.Appellation.Region.Name,
			all.Labels[0].Url
	);
	overview.add(head);
	if(friend)
		overview.add(Ti.UI.createLabel({
			text: friend.fname + "'s Reviews of this wine",
			width: Ti.UI.SIZE,
			height: Ti.UI.SIZE,
			left: 10
		}));
	get_checkin_view = require('ui/handheld/Wine_Review/Checkin');

	var ch = get_checkin_view(all);
	var dd = require('ui/common/elements/dropdown');
	var tableview = null;
	function load_tables(){
		//alert("wineid: "+ JSON.stringify(wine));
		var uid = null;
		if(friend)
			uid = friend.user_id;
		global.api.previous_checkins(wine.id, uid, function(data){
			//alert(JSON.stringify(data));
			if(tableview != null)
				overview.remove(tableview);

			var reviews = [];

			for (var i = 0; i < data.length; i++) {
				var review = data[i];
				var r = Ti.UI.createTableViewRow({
					hasChild:false,
					selectionStyle: 'none',
					layout: 'vertical'
				});

				var rv = Ti.UI.createView({
					layout: 'vertical',
					height: Ti.UI.SIZE,
					width: Ti.UI.FILL,
				});
				r.add(rv);
				rv.add(Ti.UI.createLabel({
					color: 'white',
	    			top: 10,
	    			left: 10,
	    			right: 10,
	    			fontSize:14,
	    			backgroundColor: global.colors.dark,
					text: "Rating: "+review.rating + " by " +review.friend.fname+" "+review.friend.lname+ "\nDate: " +review.date,
	    			//backgroundColor: global.colors.dark,
					//text: "Rating: "+review.rating + "\nDate: " +review.Date,
					height: Ti.UI.SIZE,
					width: Ti.UI.FILL
				}));

				rv.add(Ti.UI.createLabel({
					text: '"'+review.comment + '"',
					height: Ti.UI.SIZE,
					width: Ti.UI.FILL,
					bottom: 10,
					left: 10,
	    			right: 10,
				}));

				reviews.push(r);

			}
			// create table view
			tableview = Titanium.UI.createTableView({
				data:reviews,
				width: Ti.UI.FILL,
				height: Ti.UI.FILL,
				backgroundColor:'transparent'
			});

			overview.add(tableview);
		});
	};
	load_tables();
	dd(ch.view, self, "Finish Check-In", "Check-In", "up", function(){
		//alert("wine: "+ all.Id + " "+ ch.ta.value + " - " + Math.round(ch.rating.value));
		global.api.checkin(wine.id, ch.ta.value, Math.round(ch.rating.value), function(){
			load_tables();
		});
	});
	self.add(overview);
	return self;
};

module.exports = WineReview;<|endoftext|>


<commit_before>/*global define*/
define([
        '../Core/DeveloperError',
        '../Core/Color',
        '../Core/combine',
        '../Core/destroyObject',
        '../Core/FAR',
        '../Core/Math',
        '../Core/Cartesian3',
        '../Core/Matrix4',
        '../Core/ComponentDatatype',
        '../Core/PrimitiveType',
        '../Core/BoundingSphere',
        '../Renderer/BufferUsage',
        '../Renderer/BlendingState',
        '../Renderer/CommandLists',
        '../Renderer/DrawCommand',
        '../Renderer/createPickFragmentShaderSource',
        './Material',
        '../Shaders/SensorVolume',
        '../Shaders/CustomSensorVolumeVS',
        '../Shaders/CustomSensorVolumeFS',
        './SceneMode'
    ], function(
        DeveloperError,
        Color,
        combine,
        destroyObject,
        FAR,
        CesiumMath,
        Cartesian3,
        Matrix4,
        ComponentDatatype,
        PrimitiveType,
        BoundingSphere,
        BufferUsage,
        BlendingState,
        CommandLists,
        DrawCommand,
        createPickFragmentShaderSource,
        Material,
        ShadersSensorVolume,
        CustomSensorVolumeVS,
        CustomSensorVolumeFS,
        SceneMode) {
    "use strict";

    var attributeIndices = {
        position : 0,
        normal : 1
    };

    /**
     * DOC_TBA
     *
     * @alias CustomSensorVolume
     * @constructor
     *
     * @see SensorVolumeCollection#addCustom
     */
    var CustomSensorVolume = function(template) {
        var t = template || {};

        this._pickId = undefined;
        this._pickIdThis = t._pickIdThis || this;

        this._colorCommand = new DrawCommand();
        this._pickCommand = new DrawCommand();
        this._commandLists = new CommandLists();

        this._colorCommand.primitiveType = this._pickCommand.primitiveType = PrimitiveType.TRIANGLES;
        this._colorCommand.boundingVolume = this._pickCommand.boundingVolume = new BoundingSphere();

        /**
         * true if this sensor will be shown; otherwise, false
         *
         * @type Boolean
         */
        this.show = (typeof t.show === 'undefined') ? true : t.show;

        /**
         * When true, a polyline is shown where the sensor outline intersections the central body.  The default is true.
         *
         * @type Boolean
         *
         * @see CustomSensorVolume#intersectionColor
         */
        this.showIntersection = (typeof t.showIntersection === 'undefined') ? true : t.showIntersection;

        /**
         *

         * Determines if a sensor intersecting the ellipsoid is drawn through the ellipsoid and potentially out
         * to the other side, or if the part of the sensor intersecting the ellipsoid stops at the ellipsoid.
         *

         *

         * The default is false, meaning the sensor will not go through the ellipsoid.
         *

         *
         * @type Boolean
         */
        this.showThroughEllipsoid = (typeof t.showThroughEllipsoid === 'undefined') ? false : t.showThroughEllipsoid;

        /**
         * The 4x4 transformation matrix that transforms this sensor from model to world coordinates.  In it's model
         * coordinates, the sensor's principal direction is along the positive z-axis.  The clock angle, sometimes
         * called azimuth, is the angle in the sensor's X-Y plane measured from the positive X-axis toward the positive
         * Y-axis.  The cone angle, sometimes called elevation, is the angle out of the X-Y plane along the positive Z-axis.
         * This matrix is available to GLSL vertex and fragment shaders via
         * {@link czm_model} and derived uniforms.
         *

         *

         *

         * Model coordinate system for a custom sensor
         *

         *
         * @type Matrix4
         *
         * @see czm_model
         *
         * @example
         * // The sensor's vertex is located on the surface at -75.59777 degrees longitude and 40.03883 degrees latitude.
         * // The sensor's opens upward, along the surface normal.
         * var center = ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883));
         * sensor.modelMatrix = Transforms.eastNorthUpToFixedFrame(center);
         */
        this.modelMatrix = t.modelMatrix || Matrix4.IDENTITY.clone();

        /**
         * DOC_TBA
         *
         * @type BufferUsage
         */
        this.bufferUsage = t.bufferUsage || BufferUsage.STATIC_DRAW;
        this._bufferUsage = t.bufferUsage || BufferUsage.STATIC_DRAW;

        /**
         * DOC_TBA
         *
         * @type Number
         */
        this.radius = (typeof t.radius === 'undefined') ? Number.POSITIVE_INFINITY : t.radius;

        this._directions = undefined;
        this._directionsDirty = false;
        this.setDirections(t.directions);

        /**
         * The surface appearance of the sensor.  This can be one of several built-in {@link Material} objects or a custom material, scripted with
         * Fabric.
         *

         * The default material is Material.ColorType.
         *

         *
         * @type Material
         *
         * @example
         * // 1. Change the color of the default material to yellow
         * sensor.material.uniforms.color = new Color(1.0, 1.0, 0.0, 1.0);
         *
         * // 2. Change material to horizontal stripes
         * sensor.material = Material.fromType(scene.getContext(), Material.StripeType);
         *
         * @see Fabric
         */
        this.material = (typeof t.material !== 'undefined') ? t.material : Material.fromType(undefined, Material.ColorType);
        this._material = undefined;

        /**
         * The color of the polyline where the sensor outline intersects the central body.  The default is {@link Color.WHITE}.
         *
         * @type Color
         *
         * @see CustomSensorVolume#showIntersection
         */
        this.intersectionColor = (typeof t.intersectionColor !== 'undefined') ? Color.clone(t.intersectionColor) : Color.clone(Color.WHITE);

        var that = this;
        this._uniforms = {
            u_showThroughEllipsoid : function() {
                return that.showThroughEllipsoid;
            },
            u_showIntersection : function() {
                return that.showIntersection;
            },
            u_sensorRadius : function() {
                return isFinite(that.radius) ? that.radius : FAR;
            },
            u_intersectionColor : function() {
                return that.intersectionColor;
            }
        };

        this._mode = SceneMode.SCENE3D;
    };

    /**
     * DOC_TBA
     *
     * @memberof CustomSensorVolume
     *
     * @see CustomSensorVolume#getDirections
     */
    CustomSensorVolume.prototype.setDirections = function(directions) {
        this._directions = directions;
        this._directionsDirty = true;
    };

    /**
     * DOC_TBA
     *
     * @memberof CustomSensorVolume
     *
     * @see CustomSensorVolume#setDirections
     */
    CustomSensorVolume.prototype.getDirections = function() {
        return this._directions;
    };

    CustomSensorVolume.prototype._computePositions = function() {
        var directions = this._directions;
        var length = directions.length;
        var positions = new Float32Array(3 * length);
        var r = isFinite(this.radius) ? this.radius : FAR;

        var boundingVolumePositions = [Cartesian3.ZERO];

        for ( var i = length - 2, j = length - 1, k = 0; k < length; i = j++, j = k++) {
            // PERFORMANCE_IDEA:  We can avoid redundant operations for adjacent edges.
            var n0 = Cartesian3.fromSpherical(directions[i]);
            var n1 = Cartesian3.fromSpherical(directions[j]);
            var n2 = Cartesian3.fromSpherical(directions[k]);

            // Extend position so the volume encompasses the sensor's radius.
            var theta = Math.max(Cartesian3.angleBetween(n0, n1), Cartesian3.angleBetween(n1, n2));
            var distance = r / Math.cos(theta * 0.5);
            var p = n1.multiplyByScalar(distance);

            positions[(j * 3) + 0] = p.x;
            positions[(j * 3) + 1] = p.y;
            positions[(j * 3) + 2] = p.z;

            boundingVolumePositions.push(p);
        }

        BoundingSphere.fromPoints(boundingVolumePositions, this._colorCommand.boundingVolume);

        return positions;
    };

    CustomSensorVolume.prototype._createVertexArray = function(context) {
        var positions = this._computePositions();

        var length = this._directions.length;
        var vertices = new Float32Array(2 * 3 * 3 * length);

        var k = 0;
        for ( var i = length - 1, j = 0; j < length; i = j++) {
            var p0 = new Cartesian3(positions[(i * 3) + 0], positions[(i * 3) + 1], positions[(i * 3) + 2]);
            var p1 = new Cartesian3(positions[(j * 3) + 0], positions[(j * 3) + 1], positions[(j * 3) + 2]);
            var n = p1.cross(p0).normalize(); // Per-face normals

            vertices[k++] = 0.0; // Sensor vertex
            vertices[k++] = 0.0;
            vertices[k++] = 0.0;
            vertices[k++] = n.x;
            vertices[k++] = n.y;
            vertices[k++] = n.z;

            vertices[k++] = p1.x;
            vertices[k++] = p1.y;
            vertices[k++] = p1.z;
            vertices[k++] = n.x;
            vertices[k++] = n.y;
            vertices[k++] = n.z;

            vertices[k++] = p0.x;
            vertices[k++] = p0.y;
            vertices[k++] = p0.z;
            vertices[k++] = n.x;
            vertices[k++] = n.y;
            vertices[k++] = n.z;
        }

        var vertexBuffer = context.createVertexBuffer(new Float32Array(vertices), this.bufferUsage);
        var stride = 2 * 3 * Float32Array.BYTES_PER_ELEMENT;

        var attributes = [{
            index : attributeIndices.position,
            vertexBuffer : vertexBuffer,
            componentsPerAttribute : 3,
            componentDatatype : ComponentDatatype.FLOAT,
            offsetInBytes : 0,
            strideInBytes : stride
        }, {
            index : attributeIndices.normal,
            vertexBuffer : vertexBuffer,
            componentsPerAttribute : 3,
            componentDatatype : ComponentDatatype.FLOAT,
            offsetInBytes : 3 * Float32Array.BYTES_PER_ELEMENT,
            strideInBytes : stride
        }];

        return context.createVertexArray(attributes);
    };

    /**
     * DOC_TBA
     *
     * @memberof CustomSensorVolume
     *
     * @exception {DeveloperError} this.radius must be greater than or equal to zero.
     * @exception {DeveloperError} this.material must be defined.
     */
    CustomSensorVolume.prototype.update = function(context, frameState, commandList) {
        this._mode = frameState.mode;
        if (!this.show || this._mode !== SceneMode.SCENE3D) {
            return;
        }

        if (this.radius < 0.0) {
            throw new DeveloperError('this.radius must be greater than or equal to zero.');
        }

        if (typeof this.material === 'undefined') {
            throw new DeveloperError('this.material must be defined.');
        }

        // Initial render state creation
        if (typeof this._colorCommand.renderState === 'undefined') {
            var rs = context.createRenderState({
                depthTest : {
                    enabled : true
                },
                depthMask : false,
                blending : BlendingState.ALPHA_BLEND
            });

            this._colorCommand.renderState = rs;
            this._pickCommand.renderState = rs;
        }
        // This would be better served by depth testing with a depth buffer that does not
        // include the ellipsoid depth - or a g-buffer containing an ellipsoid mask
        // so we can selectively depth test.
        this._colorCommand.renderState.depthTest.enabled = !this.showThroughEllipsoid;

        // Recreate vertex buffer when directions change
        if ((this._directionsDirty) || (this._bufferUsage !== this.bufferUsage)) {
            this._directionsDirty = false;
            this._bufferUsage = this.bufferUsage;
            this._va = this._va && this._va.destroy();

            var directions = this._directions;
            if (directions && (directions.length >= 3)) {
                this._colorCommand.vertexArray = this._pickCommand.vertexArray = this._createVertexArray(context);
            }
        }

        if (typeof this._colorCommand.vertexArray === 'undefined') {
            return;
        }

        var pass = frameState.passes;
        this._colorCommand.modelMatrix = this._pickCommand.modelMatrix = this.modelMatrix;
        this._commandLists.removeAll();

        var materialChanged = this._material !== this.material;
        this._material = this.material;

        if (pass.color) {
            var colorCommand = this._colorCommand;

            // Recompile shader when material changes
            if (materialChanged || typeof colorCommand.shaderProgram === 'undefined') {
                var fsSource =
                    '#line 0\n' +
                    ShadersSensorVolume +
                    '#line 0\n' +
                    this._material.shaderSource +
                    '#line 0\n' +
                    CustomSensorVolumeFS;

                colorCommand.shaderProgram = context.getShaderCache().replaceShaderProgram(
                    colorCommand.shaderProgram, CustomSensorVolumeVS, fsSource, attributeIndices);
                colorCommand.uniformMap = combine([this._uniforms, this._material._uniforms], false, false);
            }

            this._commandLists.colorList.push(colorCommand);
        }

        if (pass.pick) {
            var pickCommand = this._pickCommand;

            if (typeof this._pickId === 'undefined') {
                this._pickId = context.createPickId(this._pickIdThis);
            }

            // Recompile shader when material changes
            if (materialChanged || typeof pickCommand.shaderProgram === 'undefined') {
                var pickFS = createPickFragmentShaderSource(
                    '#line 0\n' +
                    ShadersSensorVolume +
                    '#line 0\n' +
                    this._material.shaderSource +
                    '#line 0\n' +
                    CustomSensorVolumeFS, 'uniform');

                pickCommand.shaderProgram = context.getShaderCache().replaceShaderProgram(
                    pickCommand.shaderProgram, CustomSensorVolumeVS, pickFS, attributeIndices);

                var that = this;
                pickCommand.uniformMap = combine([this._uniforms, this._material._uniforms, {
                    czm_pickColor : function() {
                        return that._pickId.color;
                    }
                }], false, false);
            }

            this._commandLists.pickList.push(pickCommand);
        }

        if (!this._commandLists.empty()) {
            commandList.push(this._commandLists);
        }
    };

    /**
     * DOC_TBA
     * @memberof CustomSensorVolume
     */
    CustomSensorVolume.prototype.isDestroyed = function() {
        return false;
    };

    /**
     * DOC_TBA
     * @memberof CustomSensorVolume
     */
    CustomSensorVolume.prototype.destroy = function() {
        this._colorCommand.vertexArray = this._colorCommand.vertexArray && this._colorCommand.vertexArray.destroy();
        this._colorCommand.shaderProgram = this._colorCommand.shaderProgram && this._colorCommand.shaderProgram.release();
        this._pickCommand.shaderProgram = this._pickCommand.shaderProgram && this._pickCommand.shaderProgram.release();
        this._pickId = this._pickId && this._pickId.destroy();
        return destroyObject(this);
    };

    return CustomSensorVolume;
});
<commit_msg>fixing CustomSensoreVolume.js<commit_after>/*global define*/
define([
        '../Core/defautlValue',
        '../Core/DeveloperError',
        '../Core/Color',
        '../Core/combine',
        '../Core/destroyObject',
        '../Core/FAR',
        '../Core/Math',
        '../Core/Cartesian3',
        '../Core/Matrix4',
        '../Core/ComponentDatatype',
        '../Core/PrimitiveType',
        '../Core/BoundingSphere',
        '../Renderer/BufferUsage',
        '../Renderer/BlendingState',
        '../Renderer/CommandLists',
        '../Renderer/DrawCommand',
        '../Renderer/createPickFragmentShaderSource',
        './Material',
        '../Shaders/SensorVolume',
        '../Shaders/CustomSensorVolumeVS',
        '../Shaders/CustomSensorVolumeFS',
        './SceneMode'
    ], function(
        defautlValue,
        DeveloperError,
        Color,
        combine,
        destroyObject,
        FAR,
        CesiumMath,
        Cartesian3,
        Matrix4,
        ComponentDatatype,
        PrimitiveType,
        BoundingSphere,
        BufferUsage,
        BlendingState,
        CommandLists,
        DrawCommand,
        createPickFragmentShaderSource,
        Material,
        ShadersSensorVolume,
        CustomSensorVolumeVS,
        CustomSensorVolumeFS,
        SceneMode) {
    "use strict";

    var attributeIndices = {
        position : 0,
        normal : 1
    };

    /**
     * DOC_TBA
     *
     * @alias CustomSensorVolume
     * @constructor
     *
     * @see SensorVolumeCollection#addCustom
     */
    var CustomSensorVolume = function(template) {
        var t = defautlValue(template, {});

        this._pickId = undefined;
        this._pickIdThis = defautlValue(t._pickIdThis, this);

        this._colorCommand = new DrawCommand();
        this._pickCommand = new DrawCommand();
        this._commandLists = new CommandLists();

        this._colorCommand.primitiveType = this._pickCommand.primitiveType = PrimitiveType.TRIANGLES;
        this._colorCommand.boundingVolume = this._pickCommand.boundingVolume = new BoundingSphere();

        /**
         * true if this sensor will be shown; otherwise, false
         *
         * @type Boolean
         */
        this.show = (typeof t.show === 'undefined') ? true : t.show;

        /**
         * When true, a polyline is shown where the sensor outline intersections the central body.  The default is true.
         *
         * @type Boolean
         *
         * @see CustomSensorVolume#intersectionColor
         */
        this.showIntersection = (typeof t.showIntersection === 'undefined') ? true : t.showIntersection;

        /**
         *

         * Determines if a sensor intersecting the ellipsoid is drawn through the ellipsoid and potentially out
         * to the other side, or if the part of the sensor intersecting the ellipsoid stops at the ellipsoid.
         *

         *

         * The default is false, meaning the sensor will not go through the ellipsoid.
         *

         *
         * @type Boolean
         */
        this.showThroughEllipsoid = (typeof t.showThroughEllipsoid === 'undefined') ? false : t.showThroughEllipsoid;

        /**
         * The 4x4 transformation matrix that transforms this sensor from model to world coordinates.  In it's model
         * coordinates, the sensor's principal direction is along the positive z-axis.  The clock angle, sometimes
         * called azimuth, is the angle in the sensor's X-Y plane measured from the positive X-axis toward the positive
         * Y-axis.  The cone angle, sometimes called elevation, is the angle out of the X-Y plane along the positive Z-axis.
         * This matrix is available to GLSL vertex and fragment shaders via
         * {@link czm_model} and derived uniforms.
         *

         *

         *

         * Model coordinate system for a custom sensor
         *

         *
         * @type Matrix4
         *
         * @see czm_model
         *
         * @example
         * // The sensor's vertex is located on the surface at -75.59777 degrees longitude and 40.03883 degrees latitude.
         * // The sensor's opens upward, along the surface normal.
         * var center = ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883));
         * sensor.modelMatrix = Transforms.eastNorthUpToFixedFrame(center);
         */
        this.modelMatrix = defautlValue(t.modelMatrix, Matrix4.IDENTITY.clone());

        /**
         * DOC_TBA
         *
         * @type BufferUsage
         */
        this.bufferUsage = defautlValue(t.bufferUsage, BufferUsage.STATIC_DRAW);
        this._bufferUsage = defautlValue(t.bufferUsage, BufferUsage.STATIC_DRAW);

        /**
         * DOC_TBA
         *
         * @type Number
         */
        this.radius = (typeof t.radius === 'undefined') ? Number.POSITIVE_INFINITY : t.radius;

        this._directions = undefined;
        this._directionsDirty = false;
        this.setDirections(t.directions);

        /**
         * The surface appearance of the sensor.  This can be one of several built-in {@link Material} objects or a custom material, scripted with
         * Fabric.
         *

         * The default material is Material.ColorType.
         *

         *
         * @type Material
         *
         * @example
         * // 1. Change the color of the default material to yellow
         * sensor.material.uniforms.color = new Color(1.0, 1.0, 0.0, 1.0);
         *
         * // 2. Change material to horizontal stripes
         * sensor.material = Material.fromType(scene.getContext(), Material.StripeType);
         *
         * @see Fabric
         */
        this.material = (typeof t.material !== 'undefined') ? t.material : Material.fromType(undefined, Material.ColorType);
        this._material = undefined;

        /**
         * The color of the polyline where the sensor outline intersects the central body.  The default is {@link Color.WHITE}.
         *
         * @type Color
         *
         * @see CustomSensorVolume#showIntersection
         */
        this.intersectionColor = (typeof t.intersectionColor !== 'undefined') ? Color.clone(t.intersectionColor) : Color.clone(Color.WHITE);

        var that = this;
        this._uniforms = {
            u_showThroughEllipsoid : function() {
                return that.showThroughEllipsoid;
            },
            u_showIntersection : function() {
                return that.showIntersection;
            },
            u_sensorRadius : function() {
                return isFinite(that.radius) ? that.radius : FAR;
            },
            u_intersectionColor : function() {
                return that.intersectionColor;
            }
        };

        this._mode = SceneMode.SCENE3D;
    };

    /**
     * DOC_TBA
     *
     * @memberof CustomSensorVolume
     *
     * @see CustomSensorVolume#getDirections
     */
    CustomSensorVolume.prototype.setDirections = function(directions) {
        this._directions = directions;
        this._directionsDirty = true;
    };

    /**
     * DOC_TBA
     *
     * @memberof CustomSensorVolume
     *
     * @see CustomSensorVolume#setDirections
     */
    CustomSensorVolume.prototype.getDirections = function() {
        return this._directions;
    };

    CustomSensorVolume.prototype._computePositions = function() {
        var directions = this._directions;
        var length = directions.length;
        var positions = new Float32Array(3 * length);
        var r = isFinite(this.radius) ? this.radius : FAR;

        var boundingVolumePositions = [Cartesian3.ZERO];

        for ( var i = length - 2, j = length - 1, k = 0; k < length; i = j++, j = k++) {
            // PERFORMANCE_IDEA:  We can avoid redundant operations for adjacent edges.
            var n0 = Cartesian3.fromSpherical(directions[i]);
            var n1 = Cartesian3.fromSpherical(directions[j]);
            var n2 = Cartesian3.fromSpherical(directions[k]);

            // Extend position so the volume encompasses the sensor's radius.
            var theta = Math.max(Cartesian3.angleBetween(n0, n1), Cartesian3.angleBetween(n1, n2));
            var distance = r / Math.cos(theta * 0.5);
            var p = n1.multiplyByScalar(distance);

            positions[(j * 3) + 0] = p.x;
            positions[(j * 3) + 1] = p.y;
            positions[(j * 3) + 2] = p.z;

            boundingVolumePositions.push(p);
        }

        BoundingSphere.fromPoints(boundingVolumePositions, this._colorCommand.boundingVolume);

        return positions;
    };

    CustomSensorVolume.prototype._createVertexArray = function(context) {
        var positions = this._computePositions();

        var length = this._directions.length;
        var vertices = new Float32Array(2 * 3 * 3 * length);

        var k = 0;
        for ( var i = length - 1, j = 0; j < length; i = j++) {
            var p0 = new Cartesian3(positions[(i * 3) + 0], positions[(i * 3) + 1], positions[(i * 3) + 2]);
            var p1 = new Cartesian3(positions[(j * 3) + 0], positions[(j * 3) + 1], positions[(j * 3) + 2]);
            var n = p1.cross(p0).normalize(); // Per-face normals

            vertices[k++] = 0.0; // Sensor vertex
            vertices[k++] = 0.0;
            vertices[k++] = 0.0;
            vertices[k++] = n.x;
            vertices[k++] = n.y;
            vertices[k++] = n.z;

            vertices[k++] = p1.x;
            vertices[k++] = p1.y;
            vertices[k++] = p1.z;
            vertices[k++] = n.x;
            vertices[k++] = n.y;
            vertices[k++] = n.z;

            vertices[k++] = p0.x;
            vertices[k++] = p0.y;
            vertices[k++] = p0.z;
            vertices[k++] = n.x;
            vertices[k++] = n.y;
            vertices[k++] = n.z;
        }

        var vertexBuffer = context.createVertexBuffer(new Float32Array(vertices), this.bufferUsage);
        var stride = 2 * 3 * Float32Array.BYTES_PER_ELEMENT;

        var attributes = [{
            index : attributeIndices.position,
            vertexBuffer : vertexBuffer,
            componentsPerAttribute : 3,
            componentDatatype : ComponentDatatype.FLOAT,
            offsetInBytes : 0,
            strideInBytes : stride
        }, {
            index : attributeIndices.normal,
            vertexBuffer : vertexBuffer,
            componentsPerAttribute : 3,
            componentDatatype : ComponentDatatype.FLOAT,
            offsetInBytes : 3 * Float32Array.BYTES_PER_ELEMENT,
            strideInBytes : stride
        }];

        return context.createVertexArray(attributes);
    };

    /**
     * DOC_TBA
     *
     * @memberof CustomSensorVolume
     *
     * @exception {DeveloperError} this.radius must be greater than or equal to zero.
     * @exception {DeveloperError} this.material must be defined.
     */
    CustomSensorVolume.prototype.update = function(context, frameState, commandList) {
        this._mode = frameState.mode;
        if (typeof this.show === 'undefined' || this._mode !== SceneMode.SCENE3D) {
            return;
        }

        if (this.radius < 0.0) {
            throw new DeveloperError('this.radius must be greater than or equal to zero.');
        }

        if (typeof this.material === 'undefined') {
            throw new DeveloperError('this.material must be defined.');
        }

        // Initial render state creation
        if (typeof this._colorCommand.renderState === 'undefined') {
            var rs = context.createRenderState({
                depthTest : {
                    enabled : true
                },
                depthMask : false,
                blending : BlendingState.ALPHA_BLEND
            });

            this._colorCommand.renderState = rs;
            this._pickCommand.renderState = rs;
        }
        // This would be better served by depth testing with a depth buffer that does not
        // include the ellipsoid depth - or a g-buffer containing an ellipsoid mask
        // so we can selectively depth test.
        this._colorCommand.renderState.depthTest.enabled = !this.showThroughEllipsoid;

        // Recreate vertex buffer when directions change
        if ((this._directionsDirty) || (this._bufferUsage !== this.bufferUsage)) {
            this._directionsDirty = false;
            this._bufferUsage = this.bufferUsage;
            this._va = this._va && this._va.destroy();

            var directions = this._directions;
            if (directions && (directions.length >= 3)) {
                this._colorCommand.vertexArray = this._pickCommand.vertexArray = this._createVertexArray(context);
            }
        }

        if (typeof this._colorCommand.vertexArray === 'undefined') {
            return;
        }

        var pass = frameState.passes;
        this._colorCommand.modelMatrix = this._pickCommand.modelMatrix = this.modelMatrix;
        this._commandLists.removeAll();

        var materialChanged = this._material !== this.material;
        this._material = this.material;

        if (pass.color) {
            var colorCommand = this._colorCommand;

            // Recompile shader when material changes
            if (materialChanged || typeof colorCommand.shaderProgram === 'undefined') {
                var fsSource =
                    '#line 0\n' +
                    ShadersSensorVolume +
                    '#line 0\n' +
                    this._material.shaderSource +
                    '#line 0\n' +
                    CustomSensorVolumeFS;

                colorCommand.shaderProgram = context.getShaderCache().replaceShaderProgram(
                    colorCommand.shaderProgram, CustomSensorVolumeVS, fsSource, attributeIndices);
                colorCommand.uniformMap = combine([this._uniforms, this._material._uniforms], false, false);
            }

            this._commandLists.colorList.push(colorCommand);
        }

        if (pass.pick) {
            var pickCommand = this._pickCommand;

            if (typeof this._pickId === 'undefined') {
                this._pickId = context.createPickId(this._pickIdThis);
            }

            // Recompile shader when material changes
            if (materialChanged || typeof pickCommand.shaderProgram === 'undefined') {
                var pickFS = createPickFragmentShaderSource(
                    '#line 0\n' +
                    ShadersSensorVolume +
                    '#line 0\n' +
                    this._material.shaderSource +
                    '#line 0\n' +
                    CustomSensorVolumeFS, 'uniform');

                pickCommand.shaderProgram = context.getShaderCache().replaceShaderProgram(
                    pickCommand.shaderProgram, CustomSensorVolumeVS, pickFS, attributeIndices);

                var that = this;
                pickCommand.uniformMap = combine([this._uniforms, this._material._uniforms, {
                    czm_pickColor : function() {
                        return that._pickId.color;
                    }
                }], false, false);
            }

            this._commandLists.pickList.push(pickCommand);
        }

        if (!this._commandLists.empty()) {
            commandList.push(this._commandLists);
        }
    };

    /**
     * DOC_TBA
     * @memberof CustomSensorVolume
     */
    CustomSensorVolume.prototype.isDestroyed = function() {
        return false;
    };

    /**
     * DOC_TBA
     * @memberof CustomSensorVolume
     */
    CustomSensorVolume.prototype.destroy = function() {
        this._colorCommand.vertexArray = this._colorCommand.vertexArray && this._colorCommand.vertexArray.destroy();
        this._colorCommand.shaderProgram = this._colorCommand.shaderProgram && this._colorCommand.shaderProgram.release();
        this._pickCommand.shaderProgram = this._pickCommand.shaderProgram && this._pickCommand.shaderProgram.release();
        this._pickId = this._pickId && this._pickId.destroy();
        return destroyObject(this);
    };

    return CustomSensorVolume;
});
<|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

'use strict';

const sockjs = require('sockjs');
const nodehun = require('nodehun');
const logger = require('./../../Common/sources/logger');
const utils = require('./../../Common/sources/utils');
const fs = require('fs');
const co = require('co');
const cfgSockjs = require('config').get('services.CoAuthoring.sockjs');
const languages = require('./languages');
const allLanguages = languages.allLanguages;
const path = require('path');
const arrExistDictionaries = {};
const pathDictionaries = path.join(__dirname, '../dictionaries');
const arrDictionaries = {};

function spell(type, word, id) {
	return new Promise(function(resolve, reject) {
		let dict = null;
		if (arrDictionaries[id]) {
			dict = arrDictionaries[id];
		} else {
			if (arrExistDictionaries[id]) {
				let pathTmp = path.join(pathDictionaries, allLanguages[id], allLanguages[id] + '.');
				dict = arrDictionaries[id] = new nodehun(pathTmp + 'aff', pathTmp + 'dic');
			}
		}

		if (dict) {
			if ("spell" === type) {
				// use setImmediate because https://github.com/nodejs/node/issues/5691
				dict.isCorrect(word, function (err, correct, origWord) {
					return setImmediate(resolve, !err && correct);
				});
			} else if ("suggest" === type) {
				dict.spellSuggestions(word, function (err, correct, suggestions, origWord) {
					return setImmediate(resolve, suggestions);
				});
			}
		} else {
			return setImmediate(resolve, true);
		}
	});
}

exports.install = function (server, callbackFunction) {
	'use strict';

	utils.listFolders(pathDictionaries, true).then((values) => {
		return co(function*() {
			let lang;
			for (let i = 0; i < values.length; ++i) {
				lang = languages.sToId(path.basename(values[i]));
				if (-1 !== lang) {
					arrExistDictionaries[lang] = 1;
				}
			}
			yield spell('spell', 'color', 0x0409);
			callbackFunction();
		});
	});

	const sockjs_echo = sockjs.createServer(cfgSockjs);

	sockjs_echo.on('connection', function (conn) {
		if (!conn) {
			logger.error ("null == conn");
			return;
		}
		conn.on('data', function (message) {
			try {
				let data = JSON.parse(message);
				switch (data.type) {
					case 'spellCheck':	spellCheck(conn, data);break;
				}
			} catch (e) {
				logger.error("error receiving response: %s", e);
			}
		});
		conn.on('error', function () {
			logger.error("On error");
		});
		conn.on('close', function () {
			logger.info("Connection closed or timed out");
		});

		sendData(conn, {type: 'init', languages: Object.keys(arrExistDictionaries)});
	});

	function sendData(conn, data) {
		conn.write(JSON.stringify(data));
	}

	function spellCheck(conn, data) {
		return co(function*() {
			data = JSON.parse(data.spellCheckData);

			let promises = [];
			for (let i = 0, length = data.usrWords.length; i < length; ++i) {
				promises.push(spell(data.type, data.usrWords[i], data.usrLang[i]));
			}
			yield Promise.all(promises).then(values => {
				data[('spell' === data.type ? 'usrCorrect' : 'usrSuggest')] = values;
			});
			sendData(conn, {type: 'spellCheck', spellCheckData: data});
		});
	}

	sockjs_echo.installHandlers(server, {prefix:'/doc/[0-9-.a-zA-Z_=]*/c', log:function (severity, message) {
		//TODO: handle severity
		logger.info(message);
	}});
};
exports.spellSuggest = function (type, word, lang, callbackFunction) {
	return co(function*() {
		callbackFunction(yield spell(type, word, lang));
	});
};
<commit_msg>[spell] Removed redundant<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

'use strict';

const sockjs = require('sockjs');
const nodehun = require('nodehun');
const logger = require('./../../Common/sources/logger');
const utils = require('./../../Common/sources/utils');
const fs = require('fs');
const co = require('co');
const cfgSockjs = require('config').get('services.CoAuthoring.sockjs');
const languages = require('./languages');
const allLanguages = languages.allLanguages;
const path = require('path');
const arrExistDictionaries = {};
const pathDictionaries = path.join(__dirname, '../dictionaries');
const arrDictionaries = {};

function spell(type, word, id) {
	return new Promise(function(resolve, reject) {
		let dict = null;
		if (arrDictionaries[id]) {
			dict = arrDictionaries[id];
		} else {
			if (arrExistDictionaries[id]) {
				let pathTmp = path.join(pathDictionaries, allLanguages[id], allLanguages[id] + '.');
				dict = arrDictionaries[id] = new nodehun(pathTmp + 'aff', pathTmp + 'dic');
			}
		}

		if (dict) {
			if ("spell" === type) {
				// use setImmediate because https://github.com/nodejs/node/issues/5691
				dict.isCorrect(word, function (err, correct, origWord) {
					return setImmediate(resolve, !err && correct);
				});
			} else if ("suggest" === type) {
				dict.spellSuggestions(word, function (err, correct, suggestions, origWord) {
					return setImmediate(resolve, suggestions);
				});
			}
		} else {
			return setImmediate(resolve, true);
		}
	});
}

exports.install = function (server, callbackFunction) {
	'use strict';

	utils.listFolders(pathDictionaries, true).then((values) => {
		return co(function*() {
			let lang;
			for (let i = 0; i < values.length; ++i) {
				lang = languages.sToId(path.basename(values[i]));
				if (-1 !== lang) {
					arrExistDictionaries[lang] = 1;
				}
			}
			yield spell('spell', 'color', 0x0409);
			callbackFunction();
		});
	});

	const sockjs_echo = sockjs.createServer(cfgSockjs);

	sockjs_echo.on('connection', function (conn) {
		if (!conn) {
			logger.error ("null == conn");
			return;
		}
		conn.on('data', function (message) {
			try {
				let data = JSON.parse(message);
				switch (data.type) {
					case 'spellCheck':	spellCheck(conn, data.spellCheckData);break;
				}
			} catch (e) {
				logger.error("error receiving response: %s", e);
			}
		});
		conn.on('error', function () {
			logger.error("On error");
		});
		conn.on('close', function () {
			logger.info("Connection closed or timed out");
		});

		sendData(conn, {type: 'init', languages: Object.keys(arrExistDictionaries)});
	});

	function sendData(conn, data) {
		conn.write(JSON.stringify(data));
	}

	function spellCheck(conn, data) {
		return co(function*() {
			let promises = [];
			for (let i = 0, length = data.usrWords.length; i < length; ++i) {
				promises.push(spell(data.type, data.usrWords[i], data.usrLang[i]));
			}
			yield Promise.all(promises).then(values => {
				data[('spell' === data.type ? 'usrCorrect' : 'usrSuggest')] = values;
			});
			sendData(conn, {type: 'spellCheck', spellCheckData: data});
		});
	}

	sockjs_echo.installHandlers(server, {prefix:'/doc/[0-9-.a-zA-Z_=]*/c', log:function (severity, message) {
		//TODO: handle severity
		logger.info(message);
	}});
};
exports.spellSuggest = function (type, word, lang, callbackFunction) {
	return co(function*() {
		callbackFunction(yield spell(type, word, lang));
	});
};
<|endoftext|>