<commit_before>Ext.define('doweown.controller.Main', {
    extend: 'Ext.app.Controller',

    requires: [
	'Ext.data.proxy.JsonP',
	'Ext.navigation.View',
	'doweown.model.Isbn',
	'doweown.store.Biblio',
	'doweown.store.BranchStore',
	'doweown.store.WorldCatStore'
    ],

    config: {
	views: ['doweown.view.Main', 'doweown.view.SingleBookView',
	  'doweown.view.WorldCatView'],
        refs: { 'scanBtn': 'main #scanBtn',
		'mainScreen': 'main #mainscreen',
		'inputField': 'main #isbnField'
        },
    	control: {
            scanBtn: { tap: 'scanImage' },
	    inputField: { action: 'readIsbn' }
         }
    },

    validateBarcode: function(barcode) {
       var sum, i;

       if (barcode.length == 13) {
          barcode.replace(/[-\s]/g,'');

    	  sum = 0;
    	  for (i = 0; i < 13; i += 2) {
      	    sum += +barcode[i];
    	   }
    	  for (i = 1; i < 12; i += 2){
      		sum += 3 * +barcode[i];
    		}
    	  return sum % 10 === 0;
       }
       else if (barcode.length == 10) {
          barcode = barcode.replace(/[^\dX]/gi, '');
		  var chars = barcode.split('');
		  if(chars[9].toUpperCase() == 'X'){
  			chars[9] = 10;
  		  }
  		  sum = 0;
		  for (i = 0; i < chars.length; i++) {
		  	sum += ((10-i) * parseInt(chars[i]));
  		  }
		  return ((sum % 11) == 0);
       }
       else {
       	  return false;
       }

    },

	//get thumb and optional descriptive blurb info
	googleLookup: function(gBooksUrl, searchType) {
		var ms = this.getMainScreen();
		var title,thumb,description,date,publisher;
		console.log('google lookup');
		console.log('gbooks called url: ' + gBooksUrl);
		Ext.data.JsonP.request({
        	url: gBooksUrl,
			disableCaching: true,
            success: function(res, request) {
                	// Get the gbooks data from the json object result
                console.log('google jsonp call successful');
                console.log('res.totalItems: ' + res.totalItems);
				if (res.totalItems > 0) {
					gBooksResult = true;
				  	console.log("google worked");
				  	thumb = res.items[0].volumeInfo.imageLinks.smallThumbnail
				  	if ( thumb == null ) {
				  	  thumb = 'http://books.google.com/googlebooks/images/no_cover_thumb.gif';
				  	}

				  	console.log('thumb: ' + thumb);
				 	title =  res.items[0].volumeInfo.title;
				 	console.log('title: ' + title);
				 	//console.log('author: ' + author);
	             	date =  res.items[0].volumeInfo.publishedDate;
	             	console.log('date: ' + date);
	                publisher =  res.items[0].volumeInfo.publisher;
	                console.log('publisher: ' + publisher);
	                description = res.items[0].volumeInfo.description;
	                console.log('description: ' + description);
	                //return {thumb: thumb, description: description};
	                //update thumbs
	                if (searchType=='hollis') {
	                   var hollis = Ext.getStore('Biblio');
	                   var hollisRec = hollis.getAt(0);
	                   hollisRec.set('thumb', thumb);
	                   if (hollisRec.get('description') == '')
	                     hollisRec.set('description', description);
	                   hollisRec.set('date', date);
	                   if (hollisRec.get('title') == '' )
	                      hollisRec.set('title', title);
	                   if (hollisRec.get('publisher') == '')
	                     hollisRec.set('publisher', publisher);
	                   console.log('showing singlebookview');
	                   ms.push({ xtype: 'singlebook' });
	                }
	                else {
	                   var worldCat = Ext.getStore('WorldCatStore');
	                   console.log("worldcat store loaded with " + worldCat.getAllCount() + " records");
	                   var worldCatRec = worldCat.getAt(0);
	                   console.log("updating world cat record: " + worldCatRec.get('title') );
	                   worldCatRec.set('thumbnail', thumb);
	                   worldCatRec.set('description', description);
	                   console.log('showing worldcatview');
	                   ms.push({ xtype : 'worldcatview' });
	                }

				}
				else { // not found in gbooks, do worldcat lookup
						//do worldcat lookup
						console.log('thumbnail not found in gbooks');
						if (searchType=='hollis')
	                   		ms.push({ xtype: 'singlebook' });
	                	else
	                   		ms.push({ xtype : 'worldcatview' });
				}
		    },
			failure: function(res, request) { //gBooks lookup req failed - try worldcat anyway
					console.log("gbooks thumbnail lookup call failed");
					if (searchType=='hollis')
	                   	ms.push({ xtype: 'singlebook' });
	                else
	                   ms.push({ xtype : 'worldcatview' });
			}
		});

	},

    worldCatLookup: function(barcode) {
  	console.log('commencing worldcat lookup for isbn: ' + barcode);
  	var ms = this.getMainScreen();
  	var mainController = this;
	var worldCatURL = doweown.config.Config.getWorldCatUrl();
	var gBooksURL = doweown.config.Config.getGoogleBooksUrl();

	var lookupURL = worldCatURL + barcode;
	console.log('worldcat url is: ' + lookupURL);
	var worldCatStore = Ext.getStore('WorldCatStore');
	if (worldCatStore.getAllCount() > 0) {
        worldCatStore.removeAll();
    }
	Ext.data.JsonP.request({
	    url: lookupURL,
	    disableCaching: true,
	    callbackKey: 'callback',
	    params: {
        	wskey: doweown.config.Config.getWorldCatDevKey(),
            oclcsymbol:  doweown.config.Config.getWorldCatLibs(),
            format: 'json'
        },
	    success: function(res, request) {
	        if (typeof res.title != 'undefined'){
	          console.log('worldcat jsonp call successful');
	          var title = res.title;
	          console.log('title: ' + title);
	          var author = res.author;
	          var date = res.date;
	          var publisher = res.publisher;
	          var ISBN = res.ISBN;
	          var totalLibCount = res.totalLibCount;
	          var library = res.library;
	          console.log('libraries: ' + library);
	          var worldCatRec = Ext.create('doweown.model.WorldCatBooks', {
	            'title': title,
	            'author': author,
	            'date': date,
	            'publisher': publisher,
	            'ISBN': ISBN,
	            'library': library
	          });
	          console.log('worldcat record created');
	          worldCatStore.add(worldCatRec);
	          //worldCatStore.sync();
	          console.log('worldcat record added');
	        //worldCatStore.sync();
	        //console.log('worldcat store synced');
	          console.log("worldcat store loaded with " +
	           worldCatStore.getAllCount() + " records");
	          //lookup google for thumbnail & go to worldcat result list
	          var isbnString = '';
	          if (ISBN instanceof Array ) {
                for (var i=0; i < ISBN.length; i++) {
			  	  isbnString = isbnString + 'isbn:' + ISBN[i];
                  if (i < (ISBN.length-1))
                	  isbnString = isbnString + '+OR+';
                 }
              }
              else { // instance of String
                isbnString = "isbn:" + ISBN;
              }
              console.log('isbnString: ' + isbnString);
              gBooksURL = gBooksURL + isbnString;
              console.log('gbooks url: ' + gBooksURL);
	          mainController.googleLookup(gBooksURL,'worldcat');
	          //ms.push({ xtype : 'worldcatview' });
	        }
	        else { //not in worldcat
	        	Ext.Msg.alert("Catalog info for ISBN " + barcode + " not found.");
	        }
	    },
	    failure: function(res, request) { //worldcat lookup  failed - goto email form
	    	Ext.Msg.alert("Catalog info for ISBN " + barcode + " not found.");
	    }

	});

    },

     hollisLookup: function(barcode) {
		//presto search goes here
		var mainController = this;
		var gBooksURL = doweown.config.Config.getGoogleBooksUrl(); // + 'isbn:' + barcode;
		console.log('commencing hollis lookup');
		var ms = this.getMainScreen();
		var availURL;
		var isbnURL = doweown.config.Config.getHollisIsbnUrl() + barcode;
		var similarURL = doweown.config.Config.getHollisSimilarUrl();

		var gBooksResult = false;
		var availResult = false;
		var isbnResult = false;
		var similarResult = false;

		var title = '';
		var publisher = '';
		var place = '';
		var description = '';
		var author = '';
		var thumb = '';
		var date = '';
		var hollisId = 0;
		console.log('hollis url: ' + isbnURL);

		var gBooksStore = Ext.getStore('GbooksStore');
	    if (gBooksStore.getAllCount() > 0) {
        		gBooksStore.removeAll();
         }

		//new direct hollis call
		Ext.data.JsonP.request({
                       url: isbnURL,
                       callbackKey: 'jsonp',
                       disableCaching: true,
                       success: function(res, request) {
			           console.log("hollis lookup");
                         // Get the isbn data from the json object result
                         if (res.mods) {
                          isbnResult = true;
                          console.log("isbn worked");
                          //console.log('gbooks url: ' + gBooksURL);

                          var isbnString = '';
                          var isbnList = res.mods.identifier;
                          if (isbnList instanceof Array) {
                            for (var i=0; i < isbnList.length; i++) {
                          	  if (res.mods.identifier[i].type == 'isbn') {
                          	      var l = res.mods.identifier[i].content;
                          	      if (typeof l == 'string' || l instanceof String){
                          	          l = l.split(' ',1);
                          	       }
                          		  isbnString = isbnString + 'isbn:' + l;
                          		  if (i < (isbnList.length-2)) {
                          		     isbnString = isbnString + '+OR+';
                          		  }
                          	  }
                            }
                          } else { //single isbn
                            if (res.mods.identifier.content instanceof String ||
                              typeof res.mods.identifier.content == 'string') {
                              var l = res.mods.identifier.content.split(' ',1);
                              isbnString = 'isbn:' + l;
                            }
                            else
                              isbnString = 'isbn:' + res.mods.identifier.content;
                          }
                          // append the original isbn barcode found in the gbooks url if
                          // not in the hollis record, since its not always there. good grief
                          if (isbnString.indexOf(barcode) == -1)
                          	isbnString = isbnString + '+OR+isbn:' + barcode;
                          if (isbnString.length == 0)
                             isbnString = 'isbn:' + barcode;
                          console.log('isbnString: ' + isbnString);
                          gBooksURL = gBooksURL + isbnString;
                          //call google
	                      console.log('gbooks url: ' + gBooksURL);

                          hollisId = res.mods.recordInfo.recordIdentifier.substring(0,9);
                          console.log('hollis id is: ' + hollisId);

                          if (res.mods.titleInfo.title instanceof String)
                          	title = res.mods.titleInfo.title;
                          else if (res.mods.titleInfo instanceof Array)
                          	title = res.mods.titleInfo[0].title;
                          else
                          	title = '';
                          if (res.mods.titleInfo.nonSort)
                             title = res.mods.titleInfo.nonSort + ' ' +title;
                          if (res.mods.titleInfo.subTitle)
                             title = title + ': ' + res.mods.titleInfo.subTitle;
                          console.log('hollis title: ' + title);
                          if (res.mods.name instanceof Array ) {
                            author = res.mods.name[0].namePart;
                          }
                          else {
                            author = res.mods.name.namePart;
                          }
                          console.log('hollis author: ' + author);
                          place = res.mods.originInfo.place[1].placeTerm.content;
                          console.log('hollis place: ' + place);
                          publisher = res.mods.originInfo.publisher;
                          console.log('hollis pub: ' + publisher);
                          if (res.mods.originInfo.dateIssued.content)
                             date = res.mods.originInfo.dateIssued.content;
                          else
                             date = res.mods.originInfo.dateIssued;
                          console.log('hollis date: ' + date);

						  //call presto again for availabilty
						  availURL  = doweown.config.Config.getHollisAvailUrl() +hollisId;
                          console.log(availURL);
                          Ext.data.JsonP.request({
                     	      url: availURL,
                              callbackKey: 'jsonp',
                              disableCaching: true,
                              success: function(res, request) {
                                // Get the availability data from the json object result
                                if (res.availability) {
                                  availResult = true;
                                  console.log("avail worked");
                                  //console.log(availResult);
								  //add book to books store and availability store
						          var hollisRec = Ext.create('doweown.model.Isbn', {
						             'title' :   title,
						             'author':   author,
						             'date':     date,
						             'place':    place,
						             'publisher': publisher,
						             'hollisId': hollisId
						          });
						          var Biblio = Ext.getStore('Biblio');

						          if (Biblio.getAllCount() > 0) {
						              Biblio.removeAll();
						          }
								  Biblio.add(hollisRec);
								  var BranchStore = Ext.getStore('BranchStore');
								  if (BranchStore.getAllCount() > 0) {
                                      BranchStore.removeAll();
                                  }
								  BranchStore.getProxy().setUrl(availURL);
                                  BranchStore.load();
								  BranchStore.sync();
                               	  // lookup google for thumbnail & switch to result view
                               	  mainController.googleLookup(gBooksURL,'hollis');
								  //ms.push({ xtype : 'singlebook' });
                                }
                              }
                          });
                	    }
            		   },
					   failure: function(res, request) { //not in hollis
			   			 //do worldcat lookup
			   			 //Ext.Msg.alert(barcode + " not in hollis. sorry.");
			   			 console.log(barcode + " not in hollis. sorry.");
			   			 mainController.worldCatLookup(barcode);
					   }
        			});

     }, //end hollis

    scanImage: function() {
	  var scanner = cordova.require("cordova/plugin/BarcodeScanner");
	  mainController = this;

        scanner.scan(
        	function(result) {
        	   var barcode = result.text;
               if (result.text)
			    {
			    	if (mainController.validateBarcode(barcode)) {
			    		console.log("valid barcode");
                		mainController.hollisLookup(barcode);
                	}
                	else {
                		Ext.Msg.alert("Invalid barcode " + barcode);
                	}
                }
            },
            function(error) {
               Ext.Msg.alert("Whoops! Scanning failed: " + error);
            }
		);
    },

    readIsbn: function() {
	var barcode = this.getInputField().getValue();
	var mainController = this;
	if (barcode.length > 0) {
	  if (mainController.validateBarcode(barcode)) {
		console.log("valid barcode");
		mainController.hollisLookup(barcode);
	  }
	  else {
	   	Ext.Msg.alert("Invalid barcode " + barcode);
	  }
	}
    }

});
<commit_msg>added 'Searching...' window mask/spinning wheel indicator<commit_after>Ext.define('doweown.controller.Main', {
    extend: 'Ext.app.Controller',

    requires: [
	'Ext.data.proxy.JsonP',
	'Ext.navigation.View',
	'doweown.model.Isbn',
	'doweown.store.Biblio',
	'doweown.store.BranchStore',
	'doweown.store.WorldCatStore'
    ],

    config: {
	views: ['doweown.view.Main', 'doweown.view.SingleBookView',
	  'doweown.view.WorldCatView'],
        refs: { 'scanBtn': 'main #scanBtn',
		'mainScreen': 'main #mainscreen',
		'inputField': 'main #isbnField'
        },
    	control: {
            scanBtn: { tap: 'scanImage' },
	    inputField: { action: 'readIsbn' }
         }
    },

    validateBarcode: function(barcode) {
       var sum, i;

       if (barcode.length == 13) {
          barcode.replace(/[-\s]/g,'');

    	  sum = 0;
    	  for (i = 0; i < 13; i += 2) {
      	    sum += +barcode[i];
    	   }
    	  for (i = 1; i < 12; i += 2){
      		sum += 3 * +barcode[i];
    		}
    	  return sum % 10 === 0;
       }
       else if (barcode.length == 10) {
          barcode = barcode.replace(/[^\dX]/gi, '');
		  var chars = barcode.split('');
		  if(chars[9].toUpperCase() == 'X'){
  			chars[9] = 10;
  		  }
  		  sum = 0;
		  for (i = 0; i < chars.length; i++) {
		  	sum += ((10-i) * parseInt(chars[i]));
  		  }
		  return ((sum % 11) == 0);
       }
       else {
       	  return false;
       }

    },

	//get thumb and optional descriptive blurb info
	googleLookup: function(gBooksUrl, searchType) {
		var ms = this.getMainScreen();
		var title,thumb,description,date,publisher;
		console.log('google lookup');
		console.log('gbooks called url: ' + gBooksUrl);
		Ext.data.JsonP.request({
        	url: gBooksUrl,
			disableCaching: true,
            success: function(res, request) {
                	// Get the gbooks data from the json object result
                console.log('google jsonp call successful');
                console.log('res.totalItems: ' + res.totalItems);
				if (res.totalItems > 0) {
					gBooksResult = true;
				  	console.log("google worked");
				  	thumb = res.items[0].volumeInfo.imageLinks.smallThumbnail
				  	if ( thumb == null ) {
				  	  thumb = 'http://books.google.com/googlebooks/images/no_cover_thumb.gif';
				  	}

				  	console.log('thumb: ' + thumb);
				 	title =  res.items[0].volumeInfo.title;
				 	console.log('title: ' + title);
				 	//console.log('author: ' + author);
	             	date =  res.items[0].volumeInfo.publishedDate;
	             	console.log('date: ' + date);
	                publisher =  res.items[0].volumeInfo.publisher;
	                console.log('publisher: ' + publisher);
	                description = res.items[0].volumeInfo.description;
	                console.log('description: ' + description);
	                //return {thumb: thumb, description: description};
	                //update thumbs
	                if (searchType=='hollis') {
	                   var hollis = Ext.getStore('Biblio');
	                   var hollisRec = hollis.getAt(0);
	                   hollisRec.set('thumb', thumb);
	                   if (hollisRec.get('description') == '')
	                     hollisRec.set('description', description);
	                   hollisRec.set('date', date);
	                   if (hollisRec.get('title') == '' )
	                      hollisRec.set('title', title);
	                   if (hollisRec.get('publisher') == '')
	                     hollisRec.set('publisher', publisher);
	                   console.log('showing singlebookview');
			   ms.setMasked(false);
	                   ms.push({ xtype: 'singlebook' });
	                }
	                else {
	                   var worldCat = Ext.getStore('WorldCatStore');
	                   console.log("worldcat store loaded with " + worldCat.getAllCount() + " records");
	                   var worldCatRec = worldCat.getAt(0);
	                   console.log("updating world cat record: " + worldCatRec.get('title') );
	                   worldCatRec.set('thumbnail', thumb);
	                   worldCatRec.set('description', description);
	                   console.log('showing worldcatview');
			   ms.setMasked(false);
	                   ms.push({ xtype : 'worldcatview' });
	                }

				}
				else { // not found in gbooks, do worldcat lookup
				  //do worldcat lookup
				   console.log('thumbnail not found in gbooks');
				   if (searchType=='hollis') {
					ms.setMasked(false);
	                   		ms.push({ xtype: 'singlebook' });
				    }
	                	    else {
					ms.setMasked(false);
	                   		ms.push({ xtype : 'worldcatview' });
				    }
				}
		    },
			failure: function(res, request) { //gBooks lookup req failed - try worldcat anyway
					console.log("gbooks thumbnail lookup call failed");
					if (searchType=='hollis')  {
				ms.setMasked(false);
	                   	ms.push({ xtype: 'singlebook' });
				}
	                else  {
			   ms.setMasked(false);
	                   ms.push({ xtype : 'worldcatview' });
			   }
			}
		});

	},

    worldCatLookup: function(barcode) {
  	console.log('commencing worldcat lookup for isbn: ' + barcode);
  	var ms = this.getMainScreen();
  	var mainController = this;
	var worldCatURL = doweown.config.Config.getWorldCatUrl();
	var gBooksURL = doweown.config.Config.getGoogleBooksUrl();

	var lookupURL = worldCatURL + barcode;
	console.log('worldcat url is: ' + lookupURL);
	var worldCatStore = Ext.getStore('WorldCatStore');
	if (worldCatStore.getAllCount() > 0) {
        worldCatStore.removeAll();
    }
	Ext.data.JsonP.request({
	    url: lookupURL,
	    disableCaching: true,
	    callbackKey: 'callback',
	    params: {
        	wskey: doweown.config.Config.getWorldCatDevKey(),
            oclcsymbol:  doweown.config.Config.getWorldCatLibs(),
            format: 'json'
        },
	    success: function(res, request) {
	        if (typeof res.title != 'undefined'){
	          console.log('worldcat jsonp call successful');
	          var title = res.title;
	          console.log('title: ' + title);
	          var author = res.author;
	          var date = res.date;
	          var publisher = res.publisher;
	          var ISBN = res.ISBN;
	          var totalLibCount = res.totalLibCount;
	          var library = res.library;
	          console.log('libraries: ' + library);
	          var worldCatRec = Ext.create('doweown.model.WorldCatBooks', {
	            'title': title,
	            'author': author,
	            'date': date,
	            'publisher': publisher,
	            'ISBN': ISBN,
	            'library': library
	          });
	          console.log('worldcat record created');
	          worldCatStore.add(worldCatRec);
	          //worldCatStore.sync();
	          console.log('worldcat record added');
	        //worldCatStore.sync();
	        //console.log('worldcat store synced');
	          console.log("worldcat store loaded with " +
	           worldCatStore.getAllCount() + " records");
	          //lookup google for thumbnail & go to worldcat result list
	          var isbnString = '';
	          if (ISBN instanceof Array ) {
                for (var i=0; i < ISBN.length; i++) {
			  	  isbnString = isbnString + 'isbn:' + ISBN[i];
                  if (i < (ISBN.length-1))
                	  isbnString = isbnString + '+OR+';
                 }
              }
              else { // instance of String
                isbnString = "isbn:" + ISBN;
              }
              console.log('isbnString: ' + isbnString);
              gBooksURL = gBooksURL + isbnString;
              console.log('gbooks url: ' + gBooksURL);
	          mainController.googleLookup(gBooksURL,'worldcat');
	          //ms.push({ xtype : 'worldcatview' });
	        }
	        else { //not in worldcat
			ms.setMasked(false);
	        	Ext.Msg.alert("Catalog info for ISBN " + barcode + " not found.");
	        }
	    },
	    failure: function(res, request) { //worldcat lookup  failed - goto email form
		ms.setMasked(false);
	    	Ext.Msg.alert("Catalog info for ISBN " + barcode + " not found.");
	    }

	});

    },

     hollisLookup: function(barcode) {
		//presto search goes here
		var mainController = this;
		var gBooksURL = doweown.config.Config.getGoogleBooksUrl(); // + 'isbn:' + barcode;
		console.log('commencing hollis lookup');
		var ms = this.getMainScreen();
		var availURL;
		var isbnURL = doweown.config.Config.getHollisIsbnUrl() + barcode;
		var similarURL = doweown.config.Config.getHollisSimilarUrl();

		var gBooksResult = false;
		var availResult = false;
		var isbnResult = false;
		var similarResult = false;

		var title = '';
		var publisher = '';
		var place = '';
		var description = '';
		var author = '';
		var thumb = '';
		var date = '';
		var hollisId = 0;
		console.log('hollis url: ' + isbnURL);

		var gBooksStore = Ext.getStore('GbooksStore');
	    if (gBooksStore.getAllCount() > 0) {
        		gBooksStore.removeAll();
         }
		//show searching window
		ms.setMasked({ xtype: 'loadmask', message: 'Searching...'});
		//new direct hollis call
		Ext.data.JsonP.request({
                       url: isbnURL,
                       callbackKey: 'jsonp',
                       disableCaching: true,
                       success: function(res, request) {
			           console.log("hollis lookup");
                         // Get the isbn data from the json object result
                         if (res.mods) {
                          isbnResult = true;
                          console.log("isbn worked");
                          //console.log('gbooks url: ' + gBooksURL);

                          var isbnString = '';
                          var isbnList = res.mods.identifier;
                          if (isbnList instanceof Array) {
                            for (var i=0; i < isbnList.length; i++) {
                          	  if (res.mods.identifier[i].type == 'isbn') {
                          	      var l = res.mods.identifier[i].content;
                          	      if (typeof l == 'string' || l instanceof String){
                          	          l = l.split(' ',1);
                          	       }
                          		  isbnString = isbnString + 'isbn:' + l;
                          		  if (i < (isbnList.length-2)) {
                          		     isbnString = isbnString + '+OR+';
                          		  }
                          	  }
                            }
                          } else { //single isbn
                            if (res.mods.identifier.content instanceof String ||
                              typeof res.mods.identifier.content == 'string') {
                              var l = res.mods.identifier.content.split(' ',1);
                              isbnString = 'isbn:' + l;
                            }
                            else
                              isbnString = 'isbn:' + res.mods.identifier.content;
                          }
                          // append the original isbn barcode found in the gbooks url if
                          // not in the hollis record, since its not always there. good grief
                          if (isbnString.indexOf(barcode) == -1)
                          	isbnString = isbnString + '+OR+isbn:' + barcode;
                          if (isbnString.length == 0)
                             isbnString = 'isbn:' + barcode;
                          console.log('isbnString: ' + isbnString);
                          gBooksURL = gBooksURL + isbnString;
                          //call google
	                      console.log('gbooks url: ' + gBooksURL);

                          hollisId = res.mods.recordInfo.recordIdentifier.substring(0,9);
                          console.log('hollis id is: ' + hollisId);

                          if (res.mods.titleInfo.title instanceof String)
                          	title = res.mods.titleInfo.title;
                          else if (res.mods.titleInfo instanceof Array)
                          	title = res.mods.titleInfo[0].title;
                          else
                          	title = '';
                          if (res.mods.titleInfo.nonSort)
                             title = res.mods.titleInfo.nonSort + ' ' +title;
                          if (res.mods.titleInfo.subTitle)
                             title = title + ': ' + res.mods.titleInfo.subTitle;
                          console.log('hollis title: ' + title);
                          if (res.mods.name instanceof Array ) {
                            author = res.mods.name[0].namePart;
                          }
                          else {
                            author = res.mods.name.namePart;
                          }
                          console.log('hollis author: ' + author);
                          place = res.mods.originInfo.place[1].placeTerm.content;
                          console.log('hollis place: ' + place);
                          publisher = res.mods.originInfo.publisher;
                          console.log('hollis pub: ' + publisher);
                          if (res.mods.originInfo.dateIssued.content)
                             date = res.mods.originInfo.dateIssued.content;
                          else
                             date = res.mods.originInfo.dateIssued;
                          console.log('hollis date: ' + date);

						  //call presto again for availabilty
						  availURL  = doweown.config.Config.getHollisAvailUrl() +hollisId;
                          console.log(availURL);
                          Ext.data.JsonP.request({
                     	      url: availURL,
                              callbackKey: 'jsonp',
                              disableCaching: true,
                              success: function(res, request) {
                                // Get the availability data from the json object result
                                if (res.availability) {
                                  availResult = true;
                                  console.log("avail worked");
                                  //console.log(availResult);
								  //add book to books store and availability store
						          var hollisRec = Ext.create('doweown.model.Isbn', {
						             'title' :   title,
						             'author':   author,
						             'date':     date,
						             'place':    place,
						             'publisher': publisher,
						             'hollisId': hollisId
						          });
						          var Biblio = Ext.getStore('Biblio');

						          if (Biblio.getAllCount() > 0) {
						              Biblio.removeAll();
						          }
								  Biblio.add(hollisRec);
								  var BranchStore = Ext.getStore('BranchStore');
								  if (BranchStore.getAllCount() > 0) {
                                      BranchStore.removeAll();
                                  }
								  BranchStore.getProxy().setUrl(availURL);
                                  BranchStore.load();
								  BranchStore.sync();
                               	  // lookup google for thumbnail & switch to result view
                               	  mainController.googleLookup(gBooksURL,'hollis');
								  //ms.push({ xtype : 'singlebook' });
                                }
                              }
                          });
                	    }
            		   },
					   failure: function(res, request) { //not in hollis
			   			 //do worldcat lookup
			   			 //Ext.Msg.alert(barcode + " not in hollis. sorry.");
			   			 console.log(barcode + " not in hollis. sorry.");
			   			 mainController.worldCatLookup(barcode);
					   }
        			});

     }, //end hollis

    scanImage: function() {
	  var scanner = cordova.require("cordova/plugin/BarcodeScanner");
	  mainController = this;

        scanner.scan(
        	function(result) {
        	   var barcode = result.text;
               if (result.text)
			    {
			    	if (mainController.validateBarcode(barcode)) {
			    		console.log("valid barcode");
                		mainController.hollisLookup(barcode);
                	}
                	else {
                		Ext.Msg.alert("Invalid barcode " + barcode);
                	}
                }
            },
            function(error) {
               Ext.Msg.alert("Whoops! Scanning failed: " + error);
            }
		);
    },

    readIsbn: function() {
	var barcode = this.getInputField().getValue();
	var mainController = this;
	if (barcode.length > 0) {
	  if (mainController.validateBarcode(barcode)) {
		console.log("valid barcode");
		mainController.hollisLookup(barcode);
	  }
	  else {
	   	Ext.Msg.alert("Invalid barcode " + barcode);
	  }
	}
    }

});
<|endoftext|>


<commit_before>const Plugin = require('../../core/Plugin')
const { Provider } = require('../../server')
const { ProviderView } = require('../../views')
const { h } = require('preact')

module.exports = class Instagram extends Plugin {
  constructor (uppy, opts) {
    super(uppy, opts)
    this.type = 'acquirer'
    this.id = this.opts.id || 'Instagram'
    this.title = 'Instagram'
    this.icon = () => (
      <svg aria-hidden="true" class="UppyIcon" width="28" height="28" viewBox="0 0 512 512">
        <path d="M256,49.471c67.266,0,75.233.257,101.8,1.469,24.562,1.121,37.9,5.224,46.778,8.674a78.052,78.052,0,0,1,28.966,18.845,78.052,78.052,0,0,1,18.845,28.966c3.45,8.877,7.554,22.216,8.674,46.778,1.212,26.565,1.469,34.532,1.469,101.8s-0.257,75.233-1.469,101.8c-1.121,24.562-5.225,37.9-8.674,46.778a83.427,83.427,0,0,1-47.811,47.811c-8.877,3.45-22.216,7.554-46.778,8.674-26.56,1.212-34.527,1.469-101.8,1.469s-75.237-.257-101.8-1.469c-24.562-1.121-37.9-5.225-46.778-8.674a78.051,78.051,0,0,1-28.966-18.845,78.053,78.053,0,0,1-18.845-28.966c-3.45-8.877-7.554-22.216-8.674-46.778-1.212-26.564-1.469-34.532-1.469-101.8s0.257-75.233,1.469-101.8c1.121-24.562,5.224-37.9,8.674-46.778A78.052,78.052,0,0,1,78.458,78.458a78.053,78.053,0,0,1,28.966-18.845c8.877-3.45,22.216-7.554,46.778-8.674,26.565-1.212,34.532-1.469,101.8-1.469m0-45.391c-68.418,0-77,.29-103.866,1.516-26.815,1.224-45.127,5.482-61.151,11.71a123.488,123.488,0,0,0-44.62,29.057A123.488,123.488,0,0,0,17.3,90.982C11.077,107.007,6.819,125.319,5.6,152.134,4.369,179,4.079,187.582,4.079,256S4.369,333,5.6,359.866c1.224,26.815,5.482,45.127,11.71,61.151a123.489,123.489,0,0,0,29.057,44.62,123.486,123.486,0,0,0,44.62,29.057c16.025,6.228,34.337,10.486,61.151,11.71,26.87,1.226,35.449,1.516,103.866,1.516s77-.29,103.866-1.516c26.815-1.224,45.127-5.482,61.151-11.71a128.817,128.817,0,0,0,73.677-73.677c6.228-16.025,10.486-34.337,11.71-61.151,1.226-26.87,1.516-35.449,1.516-103.866s-0.29-77-1.516-103.866c-1.224-26.815-5.482-45.127-11.71-61.151a123.486,123.486,0,0,0-29.057-44.62A123.487,123.487,0,0,0,421.018,17.3C404.993,11.077,386.681,6.819,359.866,5.6,333,4.369,324.418,4.079,256,4.079h0Z" />
        <path d="M256,126.635A129.365,129.365,0,1,0,385.365,256,129.365,129.365,0,0,0,256,126.635Zm0,213.338A83.973,83.973,0,1,1,339.974,256,83.974,83.974,0,0,1,256,339.973Z" />
        <circle cx="390.476" cy="121.524" r="30.23" />
      </svg>
    )

    this[this.id] = new Provider(uppy, {
      host: this.opts.host,
      provider: 'instagram',
      authProvider: 'instagram'
    })

    this.files = []

    this.onAuth = this.onAuth.bind(this)
    this.render = this.render.bind(this)

    // set default options
    const defaultOptions = {}

    // merge default options with the ones set by user
    this.opts = Object.assign({}, defaultOptions, opts)
  }

  install () {
    this.view = new ProviderView(this, {
      viewType: 'grid',
      showTitles: false,
      showFilter: false,
      showBreadcrumbs: false
    })
    // Set default state for Instagram
    this.setPluginState({
      authenticated: false,
      files: [],
      folders: [],
      directories: [],
      activeRow: -1,
      filterInput: '',
      isSearchVisible: false
    })

    const target = this.opts.target
    if (target) {
      this.mount(target, this)
    }
  }

  uninstall () {
    this.view.tearDown()
    this.unmount()
  }

  onAuth (authenticated) {
    this.setPluginState({ authenticated })
    if (authenticated) {
      this.view.getFolder('recent')
    }
  }

  isFolder (item) {
    return false
  }

  getItemData (item) {
    return item
  }

  getItemIcon (item) {
    return
  }

  getItemSubList (item) {
    const subItems = []
    item.data.forEach((subItem) => {
      if (subItem.carousel_media) {
        subItem.carousel_media.forEach((i, index) => {
          const { id, created_time } = subItem
          const newSubItem = Object.assign({}, i, { id, created_time })
          newSubItem.carousel_id = index
          subItems.push(newSubItem)
        })
      } else {
        subItems.push(subItem)
      }
    })
    return subItems
  }

  getItemName (item) {
    if (item && item['created_time']) {
      let date = new Date(item['created_time'] * 1000)
      date = date.toLocaleDateString([], {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric'
      })
      // adding both date and carousel_id, so the name is unique
      return `Instagram ${date} ${item.carousel_id || ''}`
    }
    return ''
  }

  getMimeType (item) {
    return item.type === 'video' ? 'video/mp4' : 'image/jpeg'
  }

  getItemId (item) {
    return `${item.id}${item.carousel_id || ''}`
  }

  getItemRequestPath (item) {
    const suffix = isNaN(item.carousel_id) ? '' : `?carousel_id=${item.carousel_id}`
    return `${item.id}${suffix}`
  }

  getItemModifiedDate (item) {
    return item.created_time
  }

  getItemThumbnailUrl (item) {
    return item.images.thumbnail.url
  }

  getNextPagePath () {
    const { files } = this.getPluginState()
    return `recent?max_id=${this.getItemId(files[files.length - 1])}`
  }

  render (state) {
    return this.view.render(state)
  }
}
<commit_msg>add extensions to instagram files @arturi<commit_after>const Plugin = require('../../core/Plugin')
const { Provider } = require('../../server')
const { ProviderView } = require('../../views')
const { h } = require('preact')

module.exports = class Instagram extends Plugin {
  constructor (uppy, opts) {
    super(uppy, opts)
    this.type = 'acquirer'
    this.id = this.opts.id || 'Instagram'
    this.title = 'Instagram'
    this.icon = () => (
      <svg aria-hidden="true" class="UppyIcon" width="28" height="28" viewBox="0 0 512 512">
        <path d="M256,49.471c67.266,0,75.233.257,101.8,1.469,24.562,1.121,37.9,5.224,46.778,8.674a78.052,78.052,0,0,1,28.966,18.845,78.052,78.052,0,0,1,18.845,28.966c3.45,8.877,7.554,22.216,8.674,46.778,1.212,26.565,1.469,34.532,1.469,101.8s-0.257,75.233-1.469,101.8c-1.121,24.562-5.225,37.9-8.674,46.778a83.427,83.427,0,0,1-47.811,47.811c-8.877,3.45-22.216,7.554-46.778,8.674-26.56,1.212-34.527,1.469-101.8,1.469s-75.237-.257-101.8-1.469c-24.562-1.121-37.9-5.225-46.778-8.674a78.051,78.051,0,0,1-28.966-18.845,78.053,78.053,0,0,1-18.845-28.966c-3.45-8.877-7.554-22.216-8.674-46.778-1.212-26.564-1.469-34.532-1.469-101.8s0.257-75.233,1.469-101.8c1.121-24.562,5.224-37.9,8.674-46.778A78.052,78.052,0,0,1,78.458,78.458a78.053,78.053,0,0,1,28.966-18.845c8.877-3.45,22.216-7.554,46.778-8.674,26.565-1.212,34.532-1.469,101.8-1.469m0-45.391c-68.418,0-77,.29-103.866,1.516-26.815,1.224-45.127,5.482-61.151,11.71a123.488,123.488,0,0,0-44.62,29.057A123.488,123.488,0,0,0,17.3,90.982C11.077,107.007,6.819,125.319,5.6,152.134,4.369,179,4.079,187.582,4.079,256S4.369,333,5.6,359.866c1.224,26.815,5.482,45.127,11.71,61.151a123.489,123.489,0,0,0,29.057,44.62,123.486,123.486,0,0,0,44.62,29.057c16.025,6.228,34.337,10.486,61.151,11.71,26.87,1.226,35.449,1.516,103.866,1.516s77-.29,103.866-1.516c26.815-1.224,45.127-5.482,61.151-11.71a128.817,128.817,0,0,0,73.677-73.677c6.228-16.025,10.486-34.337,11.71-61.151,1.226-26.87,1.516-35.449,1.516-103.866s-0.29-77-1.516-103.866c-1.224-26.815-5.482-45.127-11.71-61.151a123.486,123.486,0,0,0-29.057-44.62A123.487,123.487,0,0,0,421.018,17.3C404.993,11.077,386.681,6.819,359.866,5.6,333,4.369,324.418,4.079,256,4.079h0Z" />
        <path d="M256,126.635A129.365,129.365,0,1,0,385.365,256,129.365,129.365,0,0,0,256,126.635Zm0,213.338A83.973,83.973,0,1,1,339.974,256,83.974,83.974,0,0,1,256,339.973Z" />
        <circle cx="390.476" cy="121.524" r="30.23" />
      </svg>
    )

    this[this.id] = new Provider(uppy, {
      host: this.opts.host,
      provider: 'instagram',
      authProvider: 'instagram'
    })

    this.files = []

    this.onAuth = this.onAuth.bind(this)
    this.render = this.render.bind(this)

    // set default options
    const defaultOptions = {}

    // merge default options with the ones set by user
    this.opts = Object.assign({}, defaultOptions, opts)
  }

  install () {
    this.view = new ProviderView(this, {
      viewType: 'grid',
      showTitles: false,
      showFilter: false,
      showBreadcrumbs: false
    })
    // Set default state for Instagram
    this.setPluginState({
      authenticated: false,
      files: [],
      folders: [],
      directories: [],
      activeRow: -1,
      filterInput: '',
      isSearchVisible: false
    })

    const target = this.opts.target
    if (target) {
      this.mount(target, this)
    }
  }

  uninstall () {
    this.view.tearDown()
    this.unmount()
  }

  onAuth (authenticated) {
    this.setPluginState({ authenticated })
    if (authenticated) {
      this.view.getFolder('recent')
    }
  }

  isFolder (item) {
    return false
  }

  getItemData (item) {
    return item
  }

  getItemIcon (item) {
    return
  }

  getItemSubList (item) {
    const subItems = []
    item.data.forEach((subItem) => {
      if (subItem.carousel_media) {
        subItem.carousel_media.forEach((i, index) => {
          const { id, created_time } = subItem
          const newSubItem = Object.assign({}, i, { id, created_time })
          newSubItem.carousel_id = index
          subItems.push(newSubItem)
        })
      } else {
        subItems.push(subItem)
      }
    })
    return subItems
  }

  getItemName (item) {
    if (item && item['created_time']) {
      const ext = item.type === 'video' ? 'mp4' : 'jpeg'
      let date = new Date(item['created_time'] * 1000)
      date = date.toLocaleDateString([], {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric'
      })
      // adding both date and carousel_id, so the name is unique
      return `Instagram ${date} ${item.carousel_id || ''}.${ext}`
    }
    return ''
  }

  getMimeType (item) {
    return item.type === 'video' ? 'video/mp4' : 'image/jpeg'
  }

  getItemId (item) {
    return `${item.id}${item.carousel_id || ''}`
  }

  getItemRequestPath (item) {
    const suffix = isNaN(item.carousel_id) ? '' : `?carousel_id=${item.carousel_id}`
    return `${item.id}${suffix}`
  }

  getItemModifiedDate (item) {
    return item.created_time
  }

  getItemThumbnailUrl (item) {
    return item.images.thumbnail.url
  }

  getNextPagePath () {
    const { files } = this.getPluginState()
    return `recent?max_id=${this.getItemId(files[files.length - 1])}`
  }

  render (state) {
    return this.view.render(state)
  }
}
<|endoftext|>


<commit_before>/***
|''Name''|TiddlySpaceInitialization|
|''Version''|0.6.5|
|''Description''|Initializes new TiddlySpaces the first time they are created|
|''Status''|@@beta@@|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/blob/master/src/plugins/TiddlySpaceInit.js|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlySpaceConfig RandomColorPalettePlugin chrjs ImageMacroPlugin|
!TODO
* robust error notification and recovery
!MarkupPreHead
<!--{{{-->
<link rel="shortcut icon" href="/recipes/%0_public/tiddlers/favicon.ico" />
<link href="/bags/%0_public/tiddlers.atom?select=tag:!excludeLists" rel="alternate" type="application/rss+xml" title="%0\'s public feed"/>
<!--}}}-->
!Code
***/
//{{{
(function($) {

var versionField = "tiddlyspaceinit_version";
var markupPreHead = store.getTiddlerText(tiddler.title + "##MarkupPreHead") || "";
var currentSpace = config.extensions.tiddlyspace.currentSpace;

var plugin = config.extensions.TiddlySpaceInit = {
	version: "0.4",
	SiteTitle: "%0",
	SiteSubtitle: "a TiddlySpace",
	flagTitle: "%0SetupFlag",
	flagWarning: "Please do not modify this tiddler; it was created " +
		"automatically upon space creation.",

	dispatch: function(ev) {
		var title = plugin.flagTitle.format([currentSpace.name]);
		config.annotations[title] = plugin.flagWarning;
		if(currentSpace.type != "private") {
			return;
		}
		var tiddlers = [];
		var tid = store.getTiddler(title);
		if(tid) {
			curVersion = parseFloat(tid.fields[versionField]);
			reqVersion = parseFloat(plugin.version);
			if(curVersion < reqVersion) {
				plugin.update(curVersion, tid);
				tid.fields[versionField] = plugin.version;
				tid.incChangeCount();
				tid = store.saveTiddler(tid);
				tiddlers.push(tid);
			}
		} else { // first run
			tid = new Tiddler(title);
			tid.tags = ["excludeLists", "excludeSearch", "excludePublisher"];
			tid.fields = $.extend({}, config.defaultCustomFields);
			tid.fields[versionField] = plugin.version;
			tid.text = "@@%0@@".format([plugin.flagWarning]);
			tid = store.saveTiddler(tid);
			tiddlers = tiddlers.concat(plugin.firstRun(), tid);
		}
		autoSaveChanges(null, tiddlers);
	},
	setupMarkupPreHead: function() {
		var pubWorkspace = plugin.getPublicWorkspace();
		var existing = store.getTiddler("MarkupPreHead");
		if(!existing || existing.fields["server.workspace"] != pubWorkspace) {
			var prehead = new Tiddler("MarkupPreHead");
			prehead.fields = $.extend({}, config.defaultCustomFields);
			prehead.fields["server.workspace"] = pubWorkspace;
			prehead.text = markupPreHead.format([currentSpace.name]);
			prehead.fields["server.page.revision"] = "false";
			prehead.tags = ["excludeLists"];
			prehead = store.saveTiddler(prehead);
			autoSaveChanges(null, [prehead]);
		}
	},
	update: function(curVersion, flagTiddler) {
		if(curVersion < 0.2) {
			this.createAvatar();
		}
		if(curVersion < 0.3) {
			flagTiddler.tags.pushUnique("excludePublisher");
		}
		if(curVersion < 0.4) {
			this.setupMarkupPreHead();
		}
	},
	firstRun: function() {
		var tiddlers = [];
		var pubWorkspace = plugin.getPublicWorkspace();
		// generate Site*itle
		$.each(["SiteTitle", "SiteSubtitle"], function(i, item) {
			var tid = new Tiddler(item);
			tid.tags = ["excludeLists", "excludeSearch"];
			tid.fields = $.extend({}, config.defaultCustomFields, {
				"server.workspace": pubWorkspace
			});
			tid.text = plugin[item].format([currentSpace.name]);
			tid = store.saveTiddler(tid);
			tiddlers.push(tid);
		});
		// generate ColorPalette (ensuring it's public)
		var wfield = "server.workspace";
		var workspace = config.defaultCustomFields[wfield];
		config.defaultCustomFields[wfield] = pubWorkspace; // XXX: hacky
		config.macros.RandomColorPalette.generatePalette({}, true);
		config.defaultCustomFields[wfield] = workspace;
		// generate avatar
		this.createAvatar();
		this.setupMarkupPreHead();
		return tiddlers;
	},
	getPublicWorkspace: function() {
		return "bags/%0".format([plugin.getPublicBag()]);
	},
	getPublicBag: function() {
		var pubBag = currentSpace.name + "_public";
		return pubBag;
	},
	createAvatar: function() {
		var avatar = "SiteIcon";
		var tweb = config.extensions.tiddlyweb;
		var host = tweb.host;
		var notify = function(xhr, error, exc) {
			displayMessage("ERROR: could not create avatar - " + // TODO: i18n
				"%0: %1".format([xhr.statusText, xhr.responseText]));
			// TODO: resolve!?
		};

		var pubBag = plugin.getPublicBag();
		var tid = new tiddlyweb.Tiddler(avatar);
		tid.bag = new tiddlyweb.Bag(pubBag, host);

		var callback = function(data, status, xhr) {}; // avatar already exists; do nothing
		var errback = function(xhr, error, exc) {
			if(xhr.status != 404) {
				return;
			}
			// copy default avatar
			var _notify = function(tid, status, xhr) {
				displayMessage("created avatar"); // TODO: i18n
				var image = config.macros.image;
				if(image && image.refreshImage) {
					image.refreshImage("/bags/%0_public/tiddlers/SiteIcon".format([currentSpace.name]));
					image.refreshImage("SiteIcon");
				}
			};
			var _callback = function(tid, status, xhr) {
				tid.title = avatar;
				tid.bag.name = pubBag;
				delete tid.etag;
				tid.put(_notify, notify); // TODO: add to current session document (via adaptor?)
			};
			tweb.getUserInfo(function(user) {
				var avatarTitle = currentSpace.name == user.name ?
					"defaultUserIcon" : "defaultSiteIcon";
				var tid = new tiddlyweb.Tiddler(avatarTitle);
				tid.bag = new tiddlyweb.Bag("common", host);
				tid.get(_callback, notify);
			});
		};
		tid.get(callback, errback);
	}
};

$(document).bind("startup", plugin.dispatch);

})(jQuery);
//}}}
<commit_msg>post-merge cleanup<commit_after>/***
|''Name''|TiddlySpaceInitialization|
|''Version''|0.6.5|
|''Description''|Initializes new TiddlySpaces the first time they are created|
|''Status''|@@beta@@|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/blob/master/src/plugins/TiddlySpaceInit.js|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlySpaceConfig RandomColorPalettePlugin chrjs ImageMacroPlugin|
!TODO
* robust error notification and recovery
!MarkupPreHead
<!--{{{-->
<link rel="shortcut icon" href="/recipes/%0_public/tiddlers/favicon.ico" />
<link href="/bags/%0_public/tiddlers.atom?select=tag:!excludeLists"
	rel="alternate" type="application/atom+xml" title="%0's public feed" />
<!--}}}-->
!Code
***/
//{{{
(function($) {

var versionField = "tiddlyspaceinit_version";
var markupPreHead = store.getTiddlerText(tiddler.title + "##MarkupPreHead", "");
var currentSpace = config.extensions.tiddlyspace.currentSpace;

var plugin = config.extensions.TiddlySpaceInit = {
	version: "0.4",
	SiteTitle: "%0",
	SiteSubtitle: "a TiddlySpace",
	flagTitle: "%0SetupFlag",
	flagWarning: "Please do not modify this tiddler; it was created " +
		"automatically upon space creation.",

	dispatch: function(ev) {
		var title = plugin.flagTitle.format([currentSpace.name]);
		config.annotations[title] = plugin.flagWarning;
		if(currentSpace.type != "private") {
			return;
		}
		var tiddlers = [];
		var tid = store.getTiddler(title);
		if(tid) {
			curVersion = parseFloat(tid.fields[versionField]);
			reqVersion = parseFloat(plugin.version);
			if(curVersion < reqVersion) {
				plugin.update(curVersion, tid);
				tid.fields[versionField] = plugin.version;
				tid.incChangeCount();
				tid = store.saveTiddler(tid);
				tiddlers.push(tid);
			}
		} else { // first run
			tid = new Tiddler(title);
			tid.tags = ["excludeLists", "excludeSearch", "excludePublisher"];
			tid.fields = $.extend({}, config.defaultCustomFields);
			tid.fields[versionField] = plugin.version;
			tid.text = "@@%0@@".format([plugin.flagWarning]);
			tid = store.saveTiddler(tid);
			tiddlers = tiddlers.concat(plugin.firstRun(), tid);
		}
		autoSaveChanges(null, tiddlers);
	},
	setupMarkupPreHead: function() {
		var pubWorkspace = this.getPublicWorkspace();
		var existing = store.getTiddler("MarkupPreHead");
		if(!existing || existing.fields["server.workspace"] != pubWorkspace) {
			var prehead = new Tiddler("MarkupPreHead");
			prehead.text = markupPreHead.format(currentSpace.name);
			prehead.tags = ["excludeLists"];
			prehead.fields = $.extend({}, config.defaultCustomFields);
			prehead.fields["server.workspace"] = pubWorkspace;
			prehead.fields["server.page.revision"] = "false";
			prehead = store.saveTiddler(prehead);
			autoSaveChanges(null, [prehead]);
		}
	},
	update: function(curVersion, flagTiddler) {
		if(curVersion < 0.2) {
			this.createAvatar();
		}
		if(curVersion < 0.3) {
			flagTiddler.tags.pushUnique("excludePublisher");
		}
		if(curVersion < 0.4) {
			this.setupMarkupPreHead();
		}
	},
	firstRun: function() {
		var tiddlers = [];
		var pubWorkspace = this.getPublicWorkspace();
		// generate Site*itle
		$.each(["SiteTitle", "SiteSubtitle"], function(i, item) {
			var tid = new Tiddler(item);
			tid.tags = ["excludeLists", "excludeSearch"];
			tid.fields = $.extend({}, config.defaultCustomFields, {
				"server.workspace": pubWorkspace
			});
			tid.text = plugin[item].format([currentSpace.name]);
			tid = store.saveTiddler(tid);
			tiddlers.push(tid);
		});
		// generate ColorPalette (ensuring it's public)
		var wfield = "server.workspace";
		var workspace = config.defaultCustomFields[wfield];
		config.defaultCustomFields[wfield] = pubWorkspace; // XXX: hacky
		config.macros.RandomColorPalette.generatePalette({}, true);
		config.defaultCustomFields[wfield] = workspace;
		// generate avatar
		this.createAvatar();
		this.setupMarkupPreHead();
		return tiddlers;
	},
	getPublicWorkspace: function() {
		return "bags/%0".format(this.getPublicBag());
	},
	getPublicBag: function() {
		return currentSpace.name + "_public";
	},
	createAvatar: function() {
		var avatar = "SiteIcon";
		var tweb = config.extensions.tiddlyweb;
		var host = tweb.host;
		var notify = function(xhr, error, exc) {
			displayMessage("ERROR: could not create avatar - " + // TODO: i18n
				"%0: %1".format([xhr.statusText, xhr.responseText]));
			// TODO: resolve!?
		};

		var pubBag = this.getPublicBag();
		var tid = new tiddlyweb.Tiddler(avatar);
		tid.bag = new tiddlyweb.Bag(pubBag, host);

		var callback = function(data, status, xhr) {}; // avatar already exists; do nothing
		var errback = function(xhr, error, exc) {
			if(xhr.status != 404) {
				return;
			}
			// copy default avatar
			var _notify = function(tid, status, xhr) {
				displayMessage("created avatar"); // TODO: i18n
				var image = config.macros.image;
				if(image && image.refreshImage) {
					image.refreshImage("/bags/%0_public/tiddlers/SiteIcon".format([currentSpace.name]));
					image.refreshImage("SiteIcon");
				}
			};
			var _callback = function(tid, status, xhr) {
				tid.title = avatar;
				tid.bag.name = pubBag;
				delete tid.etag;
				tid.put(_notify, notify); // TODO: add to current session document (via adaptor?)
			};
			tweb.getUserInfo(function(user) {
				var avatarTitle = currentSpace.name == user.name ?
					"defaultUserIcon" : "defaultSiteIcon";
				var tid = new tiddlyweb.Tiddler(avatarTitle);
				tid.bag = new tiddlyweb.Bag("common", host);
				tid.get(_callback, notify);
			});
		};
		tid.get(callback, errback);
	}
};

$(document).bind("startup", plugin.dispatch);

})(jQuery);
//}}}
<|endoftext|>


<commit_before>'use strict';

var drawChart = function(d3, svg, scope, iElement, iAttrs) {
    svg.selectAll("*").remove();

    if(scope.data == undefined) {
        return;
    }

    var height = scope.height,
        width = scope.width || d3.select(iElement[0])[0][0].offsetWidth - 20,
        translator = scope.labels;

    var barOrdering;
    if(scope.ordering) {
        barOrdering = scope.ordering.map(function(d) { return translator(d); });
    } else {
        barOrdering = dataset.map(function(d) { return translator(d.key); });
    }

    var dataset = [];
    var scorecards = scope.data;
    var keys = _.keys(scorecards[0].simple);
    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if(_.contains(scope.ordering, key)) {
            var obj = {};
            for(var j = 0; j < scorecards.length; j++) {
                var sc = scorecards[j];
                obj[sc.faction] = sc.simple[key] || 0;
            }
            dataset.push({ key: key, value: obj});
        }
    }

    svg.attr("width", width)
        .attr("height", height);

    var margin = { top: 30, bottom: 30, left: 100, right: 30};

    var barPadding = 5,
        yBottom = height - margin.bottom,
        yTop = margin.top,
        xLeft = margin.left,
        xRight = width - margin.right;

    // some numbers can be negative (e.g. leech). We'll take the absolute value
    // of all numbers for building the graphs, and use color styling to mark
    // these as negative

    var yScale = d3.scale.ordinal()
        .domain(barOrdering)
        .rangeRoundBands([yTop, yBottom], .1);

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .orient("left");

    svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(" + xLeft + ",0)")
        .call(yAxis)
        .selectAll("text");
        // .style("text-anchor", "end")
        // .attr("dx", "-.8em")
        // .attr("dy", ".15em")
        // .attr("transform", function(d) {
        //     return "rotate(-30)"
        // });
}

angular.module('d3').directive('d3Scoregraph', ['d3', function(d3) {
    return {
        restrict: 'EA',
        scope: {
            data: '=', // binding to an angular object
            width: '@',    // static binding to a value
            height: '@',
            ordering: '=',
            labels: '='
        },
        link: function(scope, iElement, iAttrs) {
            var svg = d3.select(iElement[0])
                .append("svg");

            // use auto scaling for width
            if(scope.width == undefined) {
                svg.style("width", "100%");
            }

            // on window resize, re-render d3 canvas
            window.onresize = function() {
                return scope.$apply();
            };
            scope.$watch(function() {
                return angular.element(window)[0].innerWidth;
            }, function() {
                return scope.render();
            });

            // watch for data changes and re-render
            scope.$watch('data', function(newVals, oldVals) {
                return scope.render(newVals);
            }, true);

            // define render function
            scope.render = function() {
                drawChart(d3, svg, scope, iElement, iAttrs);
            };
        }
    };
}]);<commit_msg>Horizontal bar graph for a single faction (hardcoded). Progress!<commit_after>'use strict';

var drawChart = function(d3, svg, scope, iElement, iAttrs) {
    svg.selectAll("*").remove();

    if(scope.data == undefined) {
        return;
    }

    var height = scope.height,
        width = scope.width || d3.select(iElement[0])[0][0].offsetWidth - 20,
        translator = scope.labels;

    var barOrdering;
    if(scope.ordering) {
        barOrdering = scope.ordering.map(function(d) { return translator(d); });
    } else {
        barOrdering = dataset.map(function(d) { return translator(d.key); });
    }

    var dataset = [];
    var scorecards = scope.data;
    var keys = _.keys(scorecards[0].simple);
    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if(_.contains(scope.ordering, key)) {
            var obj = {};
            for(var j = 0; j < scorecards.length; j++) {
                var sc = scorecards[j];
                obj[sc.faction] = sc.simple[key] || 0;
            }
            dataset.push({ key: key, value: obj});
        }
    }

    svg.attr("width", width)
        .attr("height", height);

    var margin = { top: 30, bottom: 30, left: 100, right: 30};

    var barPadding = 5,
        yBottom = height - margin.bottom,
        yTop = margin.top,
        xLeft = margin.left,
        xRight = width - margin.right;

    // some numbers can be negative (e.g. leech). We'll take the absolute value
    // of all numbers for building the graphs, and use color styling to mark
    // these as negative

    var yScale = d3.scale.ordinal()
        .domain(barOrdering)
        .rangeRoundBands([yTop, yBottom], .1);

    var largestValue = d3.max(dataset, function(f) {
        return d3.max(_.values(f.value), function(d) {
            return Math.abs(d);
        })
    });

    var xScale = d3.scale.linear()
        .domain([0, largestValue])
        .range([xLeft, xRight]);

    var barGroup = svg.selectAll("g")
        .data(dataset)
        .enter()
        .append("g")
        .attr("transform", function(d, i) {
            var y = yTop + yScale(translator(d.key)) - (yScale.rangeBand() / 2);
            return "translate(" + xLeft + "," + y + ")";
        })
        // setting width/height on a group doesn't do anything as far as i can tell
        .attr("height", yScale.rangeBand())
        .attr("width", xRight - xLeft);

    barGroup.append("rect")
        // .attr("x", function(d) { return yScale(Math.abs(d.value)); })
        .attr("height", function(d) { return yScale.rangeBand(); })
        .attr("width", function(d) { return xScale(Math.abs(d.value['giants'])); })
        .attr("class", function(d) {
            if(d.value['giants'] >= 0) {
                return "bar";
            }
            else {
                return "bar negative-bar"
            }
        });

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .orient("left");

    // svg.append("text")
    //     .text(largestValue)
    //     .attr("y", 100)
    //     .attr("x", 200);

    svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(" + xLeft + ",0)")
        .call(yAxis)
        .selectAll("text");
        // .style("text-anchor", "end")
        // .attr("dx", "-.8em")
        // .attr("dy", ".15em")
        // .attr("transform", function(d) {
        //     return "rotate(-30)"
        // });
}

angular.module('d3').directive('d3Scoregraph', ['d3', function(d3) {
    return {
        restrict: 'EA',
        scope: {
            data: '=', // binding to an angular object
            width: '@',    // static binding to a value
            height: '@',
            ordering: '=',
            labels: '='
        },
        link: function(scope, iElement, iAttrs) {
            var svg = d3.select(iElement[0])
                .append("svg");

            // use auto scaling for width
            if(scope.width == undefined) {
                svg.style("width", "100%");
            }

            // on window resize, re-render d3 canvas
            window.onresize = function() {
                return scope.$apply();
            };
            scope.$watch(function() {
                return angular.element(window)[0].innerWidth;
            }, function() {
                return scope.render();
            });

            // watch for data changes and re-render
            scope.$watch('data', function(newVals, oldVals) {
                return scope.render(newVals);
            }, true);

            // define render function
            scope.render = function() {
                drawChart(d3, svg, scope, iElement, iAttrs);
            };
        }
    };
}]);<|endoftext|>


<commit_before>class element {
    constructor(height, width, texture) {
        this.height = height;
        this.width = width;
        this.texture = texture;
    }
}

class placedElement extends element {
    constructor(x, y, height, width, texture) {
        super(height, width, texture);
        this.x = x;
        this.y = y;
    }
}

class freeSpace {
    constructor(x, y, height, width) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
}

class board {
    constructor(height, width, texture) {
        this.height = height;
        this.width = width;
        this.texture = texture;
        this.strips = [];
        this.free = [new freeSpace(0, 0, height, width)];
    }
    canFitElementInStrip(element) {
        if(this.strips !== []) {
            this.strips.forEach((strip) => {
                if(strip.height <= element.height) {
                    stip.free.forEach((free) => {
                        if(free.height >= element.height && free.width >= element.width) {
                            return true;
                        }
                    });
                }
            });
        }
        return false;
    }
    fitNewStrip(height) {
        this.free.forEach((free, index) => {
            if(free.height >= height) {
                this.strips.push(new Strip(free.x, free.y, height, this.width));
                this.free.splice(index, 1);
                this.free.push(new freeSpace(free.x + height, free.y, free.height - height, this.width));
                return true;
            }
        });
        return false;
    }
}

class strip {
    constructor(x, y, height, width) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
        this.elements = [];
        this.free = [];
    }
}

let elements = [];
let boards = [];
let kerf = 0;

module.exports = () => {
    // sprawdzicc czy zdana formatka nie jest wieksza niz płyta
    let elementsNotOptimized = [];
    let elementsLeft = elements;
    elementsLeft.sort((a, b) => {
        if (a.height != b.height) {
            // sortuj pionowymi
            return b.height - a.height;
        } else {
            // sortuj pozimiymi
            return b.width - a.width;
        }
    });
    elementsLeft.forEach((element) => {
        // sprawdz czy w istniejacym pasie o tym samym y nie ma miejsca na formatkę
        boards.forEach((board) => {
            if(board.canFitElementInStrip(element)) {
                // place element there
            }
        });
    });
    // sprawdz czy w istniejacym pasie o mniejszym y nie ma miejsca na formatkę
    // obróć i jeszcze raz?
    // dodaj formatkę do pasa lub dodaj nowy pas i dodaj do niego formatkę

};

module.exports.addElement = (height, width, texture = null, amount = 1) => {
    for (let i = 0; i < amount; i++) {
        elements.push(new element(height, width, texture));
    }
};

module.exports.addBoard = (height, width, texture = null, amount = 1) => {
    for (let i = 0; i < amount; i++) {
        boards.push(new board(height, width, texture));
    }
};

module.exports.setKerf = (newKerf) => {
    kerf = newKerf;
};

module.exports.getElements = () => {
    return elements;
};

module.exports.getBoards = () => {
    return boards;
};

module.exports.getKerf = () => {
    return kerf;
};
<commit_msg>Implemented basic functionality of an algorythm<commit_after>class element {
    constructor(height, width, texture) {
        this.height = height;
        this.width = width;
        this.texture = texture;
    }
}

class placedElement extends element {
    constructor(x, y, height, width, texture) {
        super(height, width, texture);
        this.x = x;
        this.y = y;
    }
}

class freeSpace {
    constructor(x, y, height, width) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
}

class strip {
    constructor(x, y, height, width) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
        this.elements = [];
        this.free = [new freeSpace(0,0, height, width)];
    }
    fitElement(element) {
        let done = false;
        if (this.height <= element.height) {
            this.free.forEach((free, index) => {
                if (!done && free.width >= element.width) {
                    this.elements.push(new placedElement(free.x, free.y, element.height, element.width, element.texture));
                    this.free.splice(index, 1);
                    this.free.push(new freeSpace(free.x + element.width, free.y, free.height, free.width - element.width));
                    done = true;
                }
            });
        }
        return done;
    }
}

class board {
    constructor(height, width, texture) {
        this.height = height;
        this.width = width;
        this.texture = texture;
        this.strips = [];
        this.free = [new freeSpace(0, 0, height, width)];
    }
    fitElement(element) {
        let done = false;
        if (this.strips !== []) {
            this.strips.forEach((strip) => {
                if(!done && strip.fitElement(element)) {
                    done = true;
                }
            });
        }
        return done;
    }
    fitNewStrip(height) {
        let done = false;
        this.free.forEach((free, index) => {
            if (!done && free.height >= height) {
                this.strips.push(new strip(free.x, free.y, height, this.width));
                this.free.splice(index, 1);
                this.free.push(new freeSpace(free.x, free.y + height, free.height - height, this.width));
                done = true;
            }
        });
        return done;
    }
}

let elements = [];
let boards = [];
let kerf = 0;

module.exports = () => {
    // sprawdzicc czy zdana formatka nie jest wieksza niz płyta
    let elementsNotOptimized = [];
    let elementsLeft = elements;
    let boardsOptimized = boards;
    elementsLeft.sort((a, b) => {
        if (a.height != b.height) {
            // sortuj pionowymi
            return b.height - a.height;
        } else {
            // sortuj pozimiymi
            return b.width - a.width;
        }
    });
    elementsLeft.forEach((element, index) => {
        // sprawdz czy w istniejacym pasie o tym samym y nie ma miejsca na formatkę
        let done = false;
        boardsOptimized.forEach((board) => {
            if (!done && board.fitElement(element)) {
                // place element there
                done = true;
                elementsLeft.splice(index, 1);
            }
        });
        if (!done) {
            // jesli nie zrob nowy pas
            let done = false;
            boardsOptimized.forEach((board) => {
                if(!done && board.fitNewStrip(element.height)) {
                    console.log('after new strip');
                    console.log(board.fitElement(element));
                    done = true;
                }
            });
            if(!done) {
                elementsLeft.splice(index, 1);
                elementsNotOptimized.push(element);
            }
        }
    });
    // sprawdz czy w istniejacym pasie o mniejszym y nie ma miejsca na formatkę
    // obróć i jeszcze raz?
    // dodaj formatkę do pasa lub dodaj nowy pas i dodaj do niego formatkę
    return boardsOptimized;
};

module.exports.addElement = (height, width, texture = null, amount = 1) => {
    for (let i = 0; i < amount; i++) {
        elements.push(new element(height, width, texture));
    }
};

module.exports.addBoard = (height, width, texture = null, amount = 1) => {
    for (let i = 0; i < amount; i++) {
        boards.push(new board(height, width, texture));
    }
};

module.exports.setKerf = (newKerf) => {
    kerf = newKerf;
};

module.exports.getElements = () => {
    return elements;
};

module.exports.getBoards = () => {
    return boards;
};

module.exports.getKerf = () => {
    return kerf;
};
<|endoftext|>


<commit_before>/**
 * @author Mat Groves http://matgroves.com/
 */

/**
 * A tiling sprite is a fast way of rendering a tiling image
 *
 * @class TilingSprite
 * @extends Sprite
 * @constructor
 * @param texture {Texture} the texture of the tiling sprite
 * @param width {Number}  the width of the tiling sprite
 * @param height {Number} the height of the tiling sprite
 */
PIXI.TilingSprite = function(texture, width, height)
{
    PIXI.Sprite.call(this, texture);

    /**
     * The width of the tiling sprite
     *
     * @property width
     * @type Number
     */
    this._width = width || 128;

    /**
     * The height of the tiling sprite
     *
     * @property height
     * @type Number
     */
    this._height = height || 128;

    /**
     * The scaling of the image that is being tiled
     *
     * @property tileScale
     * @type Point
     */
    this.tileScale = new PIXI.Point(1, 1);

    /**
     * A point that represents the scale of the texture object
     *
     * @property tileScaleOffset
     * @type Point
     */
    this.tileScaleOffset = new PIXI.Point(1, 1);

    /**
     * The offset position of the image that is being tiled
     *
     * @property tilePosition
     * @type Point
     */
    this.tilePosition = new PIXI.Point();

    /**
     * Whether this sprite is renderable or not
     *
     * @property renderable
     * @type Boolean
     * @default true
     */
    this.renderable = true;

    /**
     * The tint applied to the sprite. This is a hex value
     *
     * @property tint
     * @type Number
     * @default 0xFFFFFF
     */
    this.tint = 0xFFFFFF;

    /**
     * If enabled a green rectangle will be drawn behind the generated tiling texture, allowing you to visually
     * debug the texture being used.
     *
     * @property textureDebug
     * @type Boolean
     */
    this.textureDebug = false;

    /**
     * The blend mode to be applied to the sprite
     *
     * @property blendMode
     * @type Number
     * @default PIXI.blendModes.NORMAL;
     */
    this.blendMode = PIXI.blendModes.NORMAL;

    /**
     * The CanvasBuffer object that the tiled texture is drawn to.
     *
     * @property canvasBuffer
     * @type PIXI.CanvasBuffer
     */
    this.canvasBuffer = null;

    /**
     * An internal Texture object that holds the tiling texture that was generated from TilingSprite.texture.
     *
     * @property tilingTexture
     * @type PIXI.Texture
     */
    this.tilingTexture = null;

    /**
     * The Context fill pattern that is used to draw the TilingSprite in Canvas mode only (will be null in WebGL).
     *
     * @property tilePattern
     * @type PIXI.Texture
     */
    this.tilePattern = null;

    /**
     * If true the TilingSprite will run generateTexture on its **next** render pass.
     * This is set by the likes of Phaser.LoadTexture.setFrame.
     *
     * @property refreshTexture
     * @type Boolean
     * @default true
     */
    this.refreshTexture = true;

    this.frameWidth = 0;
    this.frameHeight = 0;

};

PIXI.TilingSprite.prototype = Object.create(PIXI.Sprite.prototype);
PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;

PIXI.TilingSprite.prototype.setTexture = function(texture)
{
    if (this.texture !== texture)
    {
        this.texture = texture;
        this.refreshTexture = true;
        this.cachedTint = 0xFFFFFF;
    }

};

/**
* Renders the object using the WebGL renderer
*
* @method _renderWebGL
* @param renderSession {RenderSession}
* @private
*/
PIXI.TilingSprite.prototype._renderWebGL = function(renderSession)
{
    if (this.visible === false || this.alpha === 0)
    {
        return;
    }

    if (this._mask)
    {
        renderSession.spriteBatch.stop();
        renderSession.maskManager.pushMask(this.mask, renderSession);
        renderSession.spriteBatch.start();
    }

    if (this._filters)
    {
        renderSession.spriteBatch.flush();
        renderSession.filterManager.pushFilter(this._filterBlock);
    }

    if (this.refreshTexture)
    {
        this.generateTilingTexture(true);

        if (this.tilingTexture)
        {
            if (this.tilingTexture.needsUpdate)
            {
                renderSession.renderer.updateTexture(this.tilingTexture.baseTexture);
                this.tilingTexture.needsUpdate = false;
            }
        }
        else
        {
            return;
        }
    }

    renderSession.spriteBatch.renderTilingSprite(this);

    for (var i = 0; i < this.children.length; i++)
    {
        this.children[i]._renderWebGL(renderSession);
    }

    renderSession.spriteBatch.stop();

    if (this._filters)
    {
        renderSession.filterManager.popFilter();
    }

    if (this._mask)
    {
        renderSession.maskManager.popMask(this._mask, renderSession);
    }

    renderSession.spriteBatch.start();

};

/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.TilingSprite.prototype._renderCanvas = function(renderSession)
{
    if (this.visible === false || this.alpha === 0)
    {
        return;
    }

    var context = renderSession.context;

    if (this._mask)
    {
        renderSession.maskManager.pushMask(this._mask, renderSession);
    }

    context.globalAlpha = this.worldAlpha;

    var wt = this.worldTransform;
    var resolution = renderSession.resolution;

    context.setTransform(wt.a * resolution, wt.b * resolution, wt.c * resolution, wt.d * resolution, wt.tx * resolution, wt.ty * resolution);

    if (this.refreshTexture)
    {
        this.generateTilingTexture(false);

        if (this.tilingTexture)
        {
            this.tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
        }
        else
        {
            return;
        }
    }

    var sessionBlendMode = renderSession.currentBlendMode;

    //  Check blend mode
    if (this.blendMode !== renderSession.currentBlendMode)
    {
        renderSession.currentBlendMode = this.blendMode;
        context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
    }

    var tilePosition = this.tilePosition;
    var tileScale = this.tileScale;

    tilePosition.x %= this.tilingTexture.baseTexture.width;
    tilePosition.y %= this.tilingTexture.baseTexture.height;

    //  Translate
    context.scale(tileScale.x, tileScale.y);
    context.translate(tilePosition.x + (this.anchor.x * -this._width), tilePosition.y + (this.anchor.y * -this._height));

    context.fillStyle = this.tilePattern;

    var tx = -tilePosition.x;
    var ty = -tilePosition.y;
    var tw = this._width / tileScale.x;
    var th = this._height / tileScale.y;

    //  Allow for pixel rounding
    if (renderSession.roundPixels)
    {
        tx |= 0;
        ty |= 0;
        tw |= 0;
        th |= 0;
    }

    context.fillRect(tx, ty, tw, th);

    //  Translate back again
    context.scale(1 / tileScale.x, 1 / tileScale.y);
    context.translate(-tilePosition.x + (this.anchor.x * this._width), -tilePosition.y + (this.anchor.y * this._height));

    if (this._mask)
    {
        renderSession.maskManager.popMask(renderSession);
    }

    for (var i = 0; i < this.children.length; i++)
    {
        this.children[i]._renderCanvas(renderSession);
    }

    //  Reset blend mode
    if (sessionBlendMode !== this.blendMode)
    {
        renderSession.currentBlendMode = sessionBlendMode;
        context.globalCompositeOperation = PIXI.blendModesCanvas[sessionBlendMode];
    }

};

/**
 * When the texture is updated, this event will fire to update the scale and frame
 *
 * @method onTextureUpdate
 * @param event
 * @private
 */
PIXI.TilingSprite.prototype.onTextureUpdate = function()
{
   // overriding the sprite version of this!
};

/**
*
* @method generateTilingTexture
*
* @param forcePowerOfTwo {Boolean} Whether we want to force the texture to be a power of two
*/
PIXI.TilingSprite.prototype.generateTilingTexture = function(forcePowerOfTwo)
{
    if (!this.texture.baseTexture.hasLoaded)
    {
        return;
    }

    var texture = this.texture;
    var frame = texture.frame;

    var targetWidth = this._frame.sourceSizeW;
    var targetHeight = this._frame.sourceSizeH;

    var dx = 0;
    var dy = 0;

    if (this._frame.trimmed)
    {
        dx = this._frame.spriteSourceSizeX;
        dy = this._frame.spriteSourceSizeY;
    }

    if (forcePowerOfTwo)
    {
        targetWidth = PIXI.getNextPowerOfTwo(targetWidth);
        targetHeight = PIXI.getNextPowerOfTwo(targetHeight);
    }

    if (this.canvasBuffer)
    {
        this.canvasBuffer.resize(targetWidth, targetHeight);
        this.tilingTexture.baseTexture.width = targetWidth;
        this.tilingTexture.baseTexture.height = targetHeight;
        this.tilingTexture.needsUpdate = true;
    }
    else
    {
        this.canvasBuffer = new PIXI.CanvasBuffer(targetWidth, targetHeight);
        this.tilingTexture = PIXI.Texture.fromCanvas(this.canvasBuffer.canvas);
        this.tilingTexture = PIXI.Texture.fromCanvas(this.canvasBuffer.canvas);
        this.tilingTexture.isTiling = true;
        this.tilingTexture.needsUpdate = true;
    }

    if (this.textureDebug)
    {
        this.canvasBuffer.context.strokeStyle = '#00ff00';
        this.canvasBuffer.context.strokeRect(0, 0, targetWidth, targetHeight);
    }

    //  If a sprite sheet we need this:
    var w = texture.crop.width;
    var h = texture.crop.height;

    if (w !== targetWidth || h !== targetHeight)
    {
        w = targetWidth;
        h = targetHeight;
    }

    this.canvasBuffer.context.drawImage(texture.baseTexture.source,
                           texture.crop.x,
                           texture.crop.y,
                           texture.crop.width,
                           texture.crop.height,
                           dx,
                           dy,
                           w,
                           h);

    this.tileScaleOffset.x = frame.width / targetWidth;
    this.tileScaleOffset.y = frame.height / targetHeight;

    this.refreshTexture = false;

    this.tilingTexture.baseTexture._powerOf2 = true;

};

/**
* Returns the framing rectangle of the sprite as a PIXI.Rectangle object
*
* @method getBounds
* @return {Rectangle} the framing rectangle
*/
PIXI.TilingSprite.prototype.getBounds = function()
{
    var width = this._width;
    var height = this._height;

    var w0 = width * (1-this.anchor.x);
    var w1 = width * -this.anchor.x;

    var h0 = height * (1-this.anchor.y);
    var h1 = height * -this.anchor.y;

    var worldTransform = this.worldTransform;

    var a = worldTransform.a;
    var b = worldTransform.b;
    var c = worldTransform.c;
    var d = worldTransform.d;
    var tx = worldTransform.tx;
    var ty = worldTransform.ty;

    var x1 = a * w1 + c * h1 + tx;
    var y1 = d * h1 + b * w1 + ty;

    var x2 = a * w0 + c * h1 + tx;
    var y2 = d * h1 + b * w0 + ty;

    var x3 = a * w0 + c * h0 + tx;
    var y3 = d * h0 + b * w0 + ty;

    var x4 =  a * w1 + c * h0 + tx;
    var y4 =  d * h0 + b * w1 + ty;

    var maxX = -Infinity;
    var maxY = -Infinity;

    var minX = Infinity;
    var minY = Infinity;

    minX = x1 < minX ? x1 : minX;
    minX = x2 < minX ? x2 : minX;
    minX = x3 < minX ? x3 : minX;
    minX = x4 < minX ? x4 : minX;

    minY = y1 < minY ? y1 : minY;
    minY = y2 < minY ? y2 : minY;
    minY = y3 < minY ? y3 : minY;
    minY = y4 < minY ? y4 : minY;

    maxX = x1 > maxX ? x1 : maxX;
    maxX = x2 > maxX ? x2 : maxX;
    maxX = x3 > maxX ? x3 : maxX;
    maxX = x4 > maxX ? x4 : maxX;

    maxY = y1 > maxY ? y1 : maxY;
    maxY = y2 > maxY ? y2 : maxY;
    maxY = y3 > maxY ? y3 : maxY;
    maxY = y4 > maxY ? y4 : maxY;

    var bounds = this._bounds;

    bounds.x = minX;
    bounds.width = maxX - minX;

    bounds.y = minY;
    bounds.height = maxY - minY;

    // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
    this._currentBounds = bounds;

    return bounds;
};

PIXI.TilingSprite.prototype.destroy = function () {

    this.canvasBuffer.destroy();

    PIXI.Sprite.prototype.destroy.call(this);

    this.tileScale = null;
    this.tileScaleOffset = null;
    this.tilePosition = null;

    if (this.tilingTexture)
    {
        this.tilingTexture.destroy(true);
        this.tilingTexture = null;
    }

};

/**
 * The width of the sprite, setting this will actually modify the scale to achieve the value set
 *
 * @property width
 * @type Number
 */
Object.defineProperty(PIXI.TilingSprite.prototype, 'width', {

    get: function() {
        return this._width;
    },

    set: function(value) {
        this._width = value;
    }

});

/**
 * The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
 *
 * @property height
 * @type Number
 */
Object.defineProperty(PIXI.TilingSprite.prototype, 'height', {

    get: function() {
        return  this._height;
    },

    set: function(value) {
        this._height = value;
    }

});
<commit_msg>Fixes edge case when TilingSprite removed before render<commit_after>/**
 * @author Mat Groves http://matgroves.com/
 */

/**
 * A tiling sprite is a fast way of rendering a tiling image
 *
 * @class TilingSprite
 * @extends Sprite
 * @constructor
 * @param texture {Texture} the texture of the tiling sprite
 * @param width {Number}  the width of the tiling sprite
 * @param height {Number} the height of the tiling sprite
 */
PIXI.TilingSprite = function(texture, width, height)
{
    PIXI.Sprite.call(this, texture);

    /**
     * The width of the tiling sprite
     *
     * @property width
     * @type Number
     */
    this._width = width || 128;

    /**
     * The height of the tiling sprite
     *
     * @property height
     * @type Number
     */
    this._height = height || 128;

    /**
     * The scaling of the image that is being tiled
     *
     * @property tileScale
     * @type Point
     */
    this.tileScale = new PIXI.Point(1, 1);

    /**
     * A point that represents the scale of the texture object
     *
     * @property tileScaleOffset
     * @type Point
     */
    this.tileScaleOffset = new PIXI.Point(1, 1);

    /**
     * The offset position of the image that is being tiled
     *
     * @property tilePosition
     * @type Point
     */
    this.tilePosition = new PIXI.Point();

    /**
     * Whether this sprite is renderable or not
     *
     * @property renderable
     * @type Boolean
     * @default true
     */
    this.renderable = true;

    /**
     * The tint applied to the sprite. This is a hex value
     *
     * @property tint
     * @type Number
     * @default 0xFFFFFF
     */
    this.tint = 0xFFFFFF;

    /**
     * If enabled a green rectangle will be drawn behind the generated tiling texture, allowing you to visually
     * debug the texture being used.
     *
     * @property textureDebug
     * @type Boolean
     */
    this.textureDebug = false;

    /**
     * The blend mode to be applied to the sprite
     *
     * @property blendMode
     * @type Number
     * @default PIXI.blendModes.NORMAL;
     */
    this.blendMode = PIXI.blendModes.NORMAL;

    /**
     * The CanvasBuffer object that the tiled texture is drawn to.
     *
     * @property canvasBuffer
     * @type PIXI.CanvasBuffer
     */
    this.canvasBuffer = null;

    /**
     * An internal Texture object that holds the tiling texture that was generated from TilingSprite.texture.
     *
     * @property tilingTexture
     * @type PIXI.Texture
     */
    this.tilingTexture = null;

    /**
     * The Context fill pattern that is used to draw the TilingSprite in Canvas mode only (will be null in WebGL).
     *
     * @property tilePattern
     * @type PIXI.Texture
     */
    this.tilePattern = null;

    /**
     * If true the TilingSprite will run generateTexture on its **next** render pass.
     * This is set by the likes of Phaser.LoadTexture.setFrame.
     *
     * @property refreshTexture
     * @type Boolean
     * @default true
     */
    this.refreshTexture = true;

    this.frameWidth = 0;
    this.frameHeight = 0;

};

PIXI.TilingSprite.prototype = Object.create(PIXI.Sprite.prototype);
PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;

PIXI.TilingSprite.prototype.setTexture = function(texture)
{
    if (this.texture !== texture)
    {
        this.texture = texture;
        this.refreshTexture = true;
        this.cachedTint = 0xFFFFFF;
    }

};

/**
* Renders the object using the WebGL renderer
*
* @method _renderWebGL
* @param renderSession {RenderSession}
* @private
*/
PIXI.TilingSprite.prototype._renderWebGL = function(renderSession)
{
    if (this.visible === false || this.alpha === 0)
    {
        return;
    }

    if (this._mask)
    {
        renderSession.spriteBatch.stop();
        renderSession.maskManager.pushMask(this.mask, renderSession);
        renderSession.spriteBatch.start();
    }

    if (this._filters)
    {
        renderSession.spriteBatch.flush();
        renderSession.filterManager.pushFilter(this._filterBlock);
    }

    if (this.refreshTexture)
    {
        this.generateTilingTexture(true);

        if (this.tilingTexture)
        {
            if (this.tilingTexture.needsUpdate)
            {
                renderSession.renderer.updateTexture(this.tilingTexture.baseTexture);
                this.tilingTexture.needsUpdate = false;
            }
        }
        else
        {
            return;
        }
    }

    renderSession.spriteBatch.renderTilingSprite(this);

    for (var i = 0; i < this.children.length; i++)
    {
        this.children[i]._renderWebGL(renderSession);
    }

    renderSession.spriteBatch.stop();

    if (this._filters)
    {
        renderSession.filterManager.popFilter();
    }

    if (this._mask)
    {
        renderSession.maskManager.popMask(this._mask, renderSession);
    }

    renderSession.spriteBatch.start();

};

/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.TilingSprite.prototype._renderCanvas = function(renderSession)
{
    if (this.visible === false || this.alpha === 0)
    {
        return;
    }

    var context = renderSession.context;

    if (this._mask)
    {
        renderSession.maskManager.pushMask(this._mask, renderSession);
    }

    context.globalAlpha = this.worldAlpha;

    var wt = this.worldTransform;
    var resolution = renderSession.resolution;

    context.setTransform(wt.a * resolution, wt.b * resolution, wt.c * resolution, wt.d * resolution, wt.tx * resolution, wt.ty * resolution);

    if (this.refreshTexture)
    {
        this.generateTilingTexture(false);

        if (this.tilingTexture)
        {
            this.tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
        }
        else
        {
            return;
        }
    }

    var sessionBlendMode = renderSession.currentBlendMode;

    //  Check blend mode
    if (this.blendMode !== renderSession.currentBlendMode)
    {
        renderSession.currentBlendMode = this.blendMode;
        context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
    }

    var tilePosition = this.tilePosition;
    var tileScale = this.tileScale;

    tilePosition.x %= this.tilingTexture.baseTexture.width;
    tilePosition.y %= this.tilingTexture.baseTexture.height;

    //  Translate
    context.scale(tileScale.x, tileScale.y);
    context.translate(tilePosition.x + (this.anchor.x * -this._width), tilePosition.y + (this.anchor.y * -this._height));

    context.fillStyle = this.tilePattern;

    var tx = -tilePosition.x;
    var ty = -tilePosition.y;
    var tw = this._width / tileScale.x;
    var th = this._height / tileScale.y;

    //  Allow for pixel rounding
    if (renderSession.roundPixels)
    {
        tx |= 0;
        ty |= 0;
        tw |= 0;
        th |= 0;
    }

    context.fillRect(tx, ty, tw, th);

    //  Translate back again
    context.scale(1 / tileScale.x, 1 / tileScale.y);
    context.translate(-tilePosition.x + (this.anchor.x * this._width), -tilePosition.y + (this.anchor.y * this._height));

    if (this._mask)
    {
        renderSession.maskManager.popMask(renderSession);
    }

    for (var i = 0; i < this.children.length; i++)
    {
        this.children[i]._renderCanvas(renderSession);
    }

    //  Reset blend mode
    if (sessionBlendMode !== this.blendMode)
    {
        renderSession.currentBlendMode = sessionBlendMode;
        context.globalCompositeOperation = PIXI.blendModesCanvas[sessionBlendMode];
    }

};

/**
 * When the texture is updated, this event will fire to update the scale and frame
 *
 * @method onTextureUpdate
 * @param event
 * @private
 */
PIXI.TilingSprite.prototype.onTextureUpdate = function()
{
   // overriding the sprite version of this!
};

/**
*
* @method generateTilingTexture
*
* @param forcePowerOfTwo {Boolean} Whether we want to force the texture to be a power of two
*/
PIXI.TilingSprite.prototype.generateTilingTexture = function(forcePowerOfTwo)
{
    if (!this.texture.baseTexture.hasLoaded)
    {
        return;
    }

    var texture = this.texture;
    var frame = texture.frame;

    var targetWidth = this._frame.sourceSizeW;
    var targetHeight = this._frame.sourceSizeH;

    var dx = 0;
    var dy = 0;

    if (this._frame.trimmed)
    {
        dx = this._frame.spriteSourceSizeX;
        dy = this._frame.spriteSourceSizeY;
    }

    if (forcePowerOfTwo)
    {
        targetWidth = PIXI.getNextPowerOfTwo(targetWidth);
        targetHeight = PIXI.getNextPowerOfTwo(targetHeight);
    }

    if (this.canvasBuffer)
    {
        this.canvasBuffer.resize(targetWidth, targetHeight);
        this.tilingTexture.baseTexture.width = targetWidth;
        this.tilingTexture.baseTexture.height = targetHeight;
        this.tilingTexture.needsUpdate = true;
    }
    else
    {
        this.canvasBuffer = new PIXI.CanvasBuffer(targetWidth, targetHeight);
        this.tilingTexture = PIXI.Texture.fromCanvas(this.canvasBuffer.canvas);
        this.tilingTexture = PIXI.Texture.fromCanvas(this.canvasBuffer.canvas);
        this.tilingTexture.isTiling = true;
        this.tilingTexture.needsUpdate = true;
    }

    if (this.textureDebug)
    {
        this.canvasBuffer.context.strokeStyle = '#00ff00';
        this.canvasBuffer.context.strokeRect(0, 0, targetWidth, targetHeight);
    }

    //  If a sprite sheet we need this:
    var w = texture.crop.width;
    var h = texture.crop.height;

    if (w !== targetWidth || h !== targetHeight)
    {
        w = targetWidth;
        h = targetHeight;
    }

    this.canvasBuffer.context.drawImage(texture.baseTexture.source,
                           texture.crop.x,
                           texture.crop.y,
                           texture.crop.width,
                           texture.crop.height,
                           dx,
                           dy,
                           w,
                           h);

    this.tileScaleOffset.x = frame.width / targetWidth;
    this.tileScaleOffset.y = frame.height / targetHeight;

    this.refreshTexture = false;

    this.tilingTexture.baseTexture._powerOf2 = true;

};

/**
* Returns the framing rectangle of the sprite as a PIXI.Rectangle object
*
* @method getBounds
* @return {Rectangle} the framing rectangle
*/
PIXI.TilingSprite.prototype.getBounds = function()
{
    var width = this._width;
    var height = this._height;

    var w0 = width * (1-this.anchor.x);
    var w1 = width * -this.anchor.x;

    var h0 = height * (1-this.anchor.y);
    var h1 = height * -this.anchor.y;

    var worldTransform = this.worldTransform;

    var a = worldTransform.a;
    var b = worldTransform.b;
    var c = worldTransform.c;
    var d = worldTransform.d;
    var tx = worldTransform.tx;
    var ty = worldTransform.ty;

    var x1 = a * w1 + c * h1 + tx;
    var y1 = d * h1 + b * w1 + ty;

    var x2 = a * w0 + c * h1 + tx;
    var y2 = d * h1 + b * w0 + ty;

    var x3 = a * w0 + c * h0 + tx;
    var y3 = d * h0 + b * w0 + ty;

    var x4 =  a * w1 + c * h0 + tx;
    var y4 =  d * h0 + b * w1 + ty;

    var maxX = -Infinity;
    var maxY = -Infinity;

    var minX = Infinity;
    var minY = Infinity;

    minX = x1 < minX ? x1 : minX;
    minX = x2 < minX ? x2 : minX;
    minX = x3 < minX ? x3 : minX;
    minX = x4 < minX ? x4 : minX;

    minY = y1 < minY ? y1 : minY;
    minY = y2 < minY ? y2 : minY;
    minY = y3 < minY ? y3 : minY;
    minY = y4 < minY ? y4 : minY;

    maxX = x1 > maxX ? x1 : maxX;
    maxX = x2 > maxX ? x2 : maxX;
    maxX = x3 > maxX ? x3 : maxX;
    maxX = x4 > maxX ? x4 : maxX;

    maxY = y1 > maxY ? y1 : maxY;
    maxY = y2 > maxY ? y2 : maxY;
    maxY = y3 > maxY ? y3 : maxY;
    maxY = y4 > maxY ? y4 : maxY;

    var bounds = this._bounds;

    bounds.x = minX;
    bounds.width = maxX - minX;

    bounds.y = minY;
    bounds.height = maxY - minY;

    // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
    this._currentBounds = bounds;

    return bounds;
};

PIXI.TilingSprite.prototype.destroy = function () {

    PIXI.Sprite.prototype.destroy.call(this);

    if (this.canvasBuffer)
    {
        this.canvasBuffer.destroy();
        this.canvasBuffer = null;
    }

    this.tileScale = null;
    this.tileScaleOffset = null;
    this.tilePosition = null;

    if (this.tilingTexture)
    {
        this.tilingTexture.destroy(true);
        this.tilingTexture = null;
    }

};

/**
 * The width of the sprite, setting this will actually modify the scale to achieve the value set
 *
 * @property width
 * @type Number
 */
Object.defineProperty(PIXI.TilingSprite.prototype, 'width', {

    get: function() {
        return this._width;
    },

    set: function(value) {
        this._width = value;
    }

});

/**
 * The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
 *
 * @property height
 * @type Number
 */
Object.defineProperty(PIXI.TilingSprite.prototype, 'height', {

    get: function() {
        return  this._height;
    },

    set: function(value) {
        this._height = value;
    }

});
<|endoftext|>