<commit_before>'use strict';

function globalModule_Try(moduleString) {
	try {
		return require(moduleString);
	} catch (exception) {
		console.log("FAILED TO LOAD: \"" + moduleString + "\"");
		console.log(exception);
		return null;
	}
}

function dump_debug_string(string) {
	var fileSystem_Module = globalModule_Try('fs');
	var inHouseFileHandle = fileSystem_Module.openSync("./local_debug_dump.txt", 'a');
	fileSystem_Module.writeSync(inHouseFileHandle, string);
	fileSystem_Module.closeSync(inHouseFileHandle);
}

// var endMarker = " MIN_END\n";
// dump_debug_string("1: " + regExp_ResultArray[1] + ".min" +
// regExp_ResultArray[2] + carriageReturn + endMarker);
// dump_debug_string("2 no_cr: " + regExp_ResultArray[1] + endMarker);
// dump_debug_string("3 no_cr: " + regExp_ResultArray[1] + ".min" + endMarker);
// dump_debug_string("4 no_cr: " + regExp_ResultArray[1] + ".min" +
// regExp_ResultArray[2] + endMarker);
// dump_debug_string("5: " + regExp_ResultArray[1] + ".min" +
// regExp_ResultArray[2] + carriageReturn + endMarker);
// dump_debug_string("TARGET no_cr: " + regExp_ResultArray[2] + endMarker);
//
// var endMarker = " REGULAR_END\n";
// dump_debug_string("1: " + regExp_ResultArray[1] + regExp_ResultArray[2] +
// carriageReturn + endMarker);
// dump_debug_string("2 no_cr: " + regExp_ResultArray[1] + endMarker);
// dump_debug_string("3 no_cr: " + regExp_ResultArray[1] + regExp_ResultArray[2]
// + endMarker);
// dump_debug_string("4: " + regExp_ResultArray[1] + regExp_ResultArray[2] +
// carriageReturn + endMarker);
// dump_debug_string("TARGET no_cr: " + regExp_ResultArray[2] + endMarker);

function message_locator_service(mainMessage) {
	var path_Module = globalModule_Try('path');
	var stackTrace_Module = globalModule_Try('stack-trace');
	var currentFrame = stackTrace_Module.get()[1];
	console.log(mainMessage + " >>> \"" + path_Module.basename(currentFrame.getFileName()) + ":" +
	    currentFrame.getLineNumber() + "\"\n");
}

function spot_the_head(htmlLineArray) {
	var headAreaMark_Array = [ -1, -1 ];
	var headMark_RegExp = new RegExp("<\\s*\\/?\\s*head\\s*>", "i");
	for (var i = 0; i < htmlLineArray.length; i++) {
		if (headMark_RegExp.exec(htmlLineArray[i]) !== null) {
			if (headAreaMark_Array[0] === -1) {
				headAreaMark_Array[0] = i;
			} else {
				headAreaMark_Array[1] = i;
				break;
			}
		}
	}
	if (headAreaMark_Array[0] === -1 || headAreaMark_Array[1] === -1) {
		message_locator_service("HEAD AREA BOUNDRIES BUGGY OR NOT FOUND AT ALL...!");
		return false;
	} else {
		return headAreaMark_Array;
	}
}

function carriage_return_needed() {
	var os_Module = globalModule_Try('os');
	var windowsSpotter_RegExp = new RegExp("windows", "i");
	if (windowsSpotter_RegExp.exec(os_Module.type()) !== null) {
		return true;
	} else {
		return false;
	}
}

function end_of_line_clean_save(fileName, array, carriageReturn) {
	var carriageReturnString = "";
	if (carriageReturn) {
		carriageReturnString = "\r";
	}
	var fileSystem_Module = globalModule_Try('fs');
	var currentFileHandle = fileSystem_Module.openSync(fileName, 'w');

	var lineSpotter_RegExp = new RegExp("^([\\x20\\x09]*)(.*)\\x0d*$", "i");
	var initialLineResultArray = lineSpotter_RegExp.exec(array[0]);
	if (initialLineResultArray !== null) {
		if (initialLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, initialLineResultArray[1] + initialLineResultArray[2] +
			    carriageReturnString + "\n");
		}
	} else {
		message_locator_service("MISSED THE INITIAL LINE...!");
		return false;
	}
	for (var j = 1; j < (array.length - 1); j++) {
		var lineResultArray = lineSpotter_RegExp.exec(array[j]);
		if (lineResultArray !== null) {
			if (j === (array.length - 2)) {
				var nextToLast_ResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
				if (!nextToLast_ResultArray[2]) {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2]);
				} else {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
					    "\n");
				}
			} else {
				fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
				    "\n");
			}
		} else {
			message_locator_service("MISSED A LINE...!");
			return false;
		}
	}
	var finalLineResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
	if (finalLineResultArray !== null) {
		if (finalLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, finalLineResultArray[1] + finalLineResultArray[2]);
		}
	} else {
		message_locator_service("MISSED THE FINAL LINE...!");
		return false;
	}
	fileSystem_Module.closeSync(currentFileHandle);
	return true;
}

function array_from_file_delete(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		fileSystem_Module.unlinkSync(entire_fileName);
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

function array_from_file(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

// Switching html head area to minified targets...
function toMin(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var hasMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(?:\\.min)+(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	var carelessAboutMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		if (hasMin_RegExp.exec(contentArray[i]) === null) {
			var regExp_ResultArray = carelessAboutMin_RegExp.exec(contentArray[i]);
			if (regExp_ResultArray !== null) {
				contentArray[i] = regExp_ResultArray[1] + ".min" + regExp_ResultArray[2] + carriageReturn;
				if (!changed) {
					changed = true;
				}
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

// Switching html head area to regular targets...
function toRegular(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var minSuspect_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)\\.min(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		var regExp_ResultArray = minSuspect_RegExp.exec(contentArray[i]);
		if (regExp_ResultArray !== null) {
			contentArray[i] = regExp_ResultArray[1] + regExp_ResultArray[2] + carriageReturn;
			if (!changed) {
				changed = true;
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

function delete_writingArray_ToFile(fileName, array) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(fileName)) {
		fileSystem_Module.unlinkSync(fileName);
	}
	var inHouseFileHandle = fileSystem_Module.openSync(fileName, 'w');
	for (var i = 0; i < (array.length - 1); i++) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[i] + "\n");
	}
	if (array[array.length - 1]) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[array.length - 1]);
	}
	fileSystem_Module.closeSync(inHouseFileHandle);
}

module.exports = {
  process_wildcard_input : function(direction, source, directory) {
	  console.log("DIRECTION: \"" + direction + "\" SOURCE: \"" + source + "\" DIRECTORY: \"" + directory + "\"\n");
	  var fileSystem_Module = globalModule_Try('fs');
	  var raw_file_array = fileSystem_Module.readdirSync(directory);
	  var targets_file_array = [];
	  for (var i = 0; i < raw_file_array.length; i++) {
		  console.log(raw_file_array[i]);
	  }
  },

  toggle_all_head_links : function(direction, file) {
	  var pointToMin = false;
	  if (direction === 'min') {
		  pointToMin = true;
	  }
	  var targetFile_LineArray = array_from_file(file);
	  if (targetFile_LineArray) {
		  var windowsNeeded_carriageReturn = "";
		  if (carriage_return_needed) {
			  windowsNeeded_carriageReturn = "\r";
		  }
		  var headStart = spot_the_head(targetFile_LineArray)[0];
		  var headEnd = spot_the_head(targetFile_LineArray)[1];

		  // Actual array manipulation...
		  if (pointToMin) {
			  targetFile_LineArray = toMin(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  } else {
			  targetFile_LineArray = toRegular(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  }
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  },

  end_of_line_refresh : function(file) {
	  console.log("CURRENTLY REFRESHING FILE: \"" + file + "\"");
	  var targetFile_LineArray = array_from_file_delete(file);
	  if (targetFile_LineArray) {
		  return end_of_line_clean_save(file, targetFile_LineArray, carriage_return_needed());
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  }
};
<commit_msg>Getting the wildcard nicely... - MH - PT<commit_after>'use strict';

function globalModule_Try(moduleString) {
	try {
		return require(moduleString);
	} catch (exception) {
		console.log("FAILED TO LOAD: \"" + moduleString + "\"");
		console.log(exception);
		return null;
	}
}

function dump_debug_string(string) {
	var fileSystem_Module = globalModule_Try('fs');
	var inHouseFileHandle = fileSystem_Module.openSync("./local_debug_dump.txt", 'a');
	fileSystem_Module.writeSync(inHouseFileHandle, string);
	fileSystem_Module.closeSync(inHouseFileHandle);
}

// var endMarker = " MIN_END\n";
// dump_debug_string("1: " + regExp_ResultArray[1] + ".min" +
// regExp_ResultArray[2] + carriageReturn + endMarker);
// dump_debug_string("2 no_cr: " + regExp_ResultArray[1] + endMarker);
// dump_debug_string("3 no_cr: " + regExp_ResultArray[1] + ".min" + endMarker);
// dump_debug_string("4 no_cr: " + regExp_ResultArray[1] + ".min" +
// regExp_ResultArray[2] + endMarker);
// dump_debug_string("5: " + regExp_ResultArray[1] + ".min" +
// regExp_ResultArray[2] + carriageReturn + endMarker);
// dump_debug_string("TARGET no_cr: " + regExp_ResultArray[2] + endMarker);
//
// var endMarker = " REGULAR_END\n";
// dump_debug_string("1: " + regExp_ResultArray[1] + regExp_ResultArray[2] +
// carriageReturn + endMarker);
// dump_debug_string("2 no_cr: " + regExp_ResultArray[1] + endMarker);
// dump_debug_string("3 no_cr: " + regExp_ResultArray[1] + regExp_ResultArray[2]
// + endMarker);
// dump_debug_string("4: " + regExp_ResultArray[1] + regExp_ResultArray[2] +
// carriageReturn + endMarker);
// dump_debug_string("TARGET no_cr: " + regExp_ResultArray[2] + endMarker);

function message_locator_service(mainMessage) {
	var path_Module = globalModule_Try('path');
	var stackTrace_Module = globalModule_Try('stack-trace');
	var currentFrame = stackTrace_Module.get()[1];
	console.log(mainMessage + " >>> \"" + path_Module.basename(currentFrame.getFileName()) + ":" +
	    currentFrame.getLineNumber() + "\"\n");
}

function spot_the_head(htmlLineArray) {
	var headAreaMark_Array = [ -1, -1 ];
	var headMark_RegExp = new RegExp("<\\s*\\/?\\s*head\\s*>", "i");
	for (var i = 0; i < htmlLineArray.length; i++) {
		if (headMark_RegExp.exec(htmlLineArray[i]) !== null) {
			if (headAreaMark_Array[0] === -1) {
				headAreaMark_Array[0] = i;
			} else {
				headAreaMark_Array[1] = i;
				break;
			}
		}
	}
	if (headAreaMark_Array[0] === -1 || headAreaMark_Array[1] === -1) {
		message_locator_service("HEAD AREA BOUNDRIES BUGGY OR NOT FOUND AT ALL...!");
		return false;
	} else {
		return headAreaMark_Array;
	}
}

function carriage_return_needed() {
	var os_Module = globalModule_Try('os');
	var windowsSpotter_RegExp = new RegExp("windows", "i");
	if (windowsSpotter_RegExp.exec(os_Module.type()) !== null) {
		return true;
	} else {
		return false;
	}
}

function end_of_line_clean_save(fileName, array, carriageReturn) {
	var carriageReturnString = "";
	if (carriageReturn) {
		carriageReturnString = "\r";
	}
	var fileSystem_Module = globalModule_Try('fs');
	var currentFileHandle = fileSystem_Module.openSync(fileName, 'w');

	var lineSpotter_RegExp = new RegExp("^([\\x20\\x09]*)(.*)\\x0d*$", "i");
	var initialLineResultArray = lineSpotter_RegExp.exec(array[0]);
	if (initialLineResultArray !== null) {
		if (initialLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, initialLineResultArray[1] + initialLineResultArray[2] +
			    carriageReturnString + "\n");
		}
	} else {
		message_locator_service("MISSED THE INITIAL LINE...!");
		return false;
	}
	for (var j = 1; j < (array.length - 1); j++) {
		var lineResultArray = lineSpotter_RegExp.exec(array[j]);
		if (lineResultArray !== null) {
			if (j === (array.length - 2)) {
				var nextToLast_ResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
				if (!nextToLast_ResultArray[2]) {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2]);
				} else {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
					    "\n");
				}
			} else {
				fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
				    "\n");
			}
		} else {
			message_locator_service("MISSED A LINE...!");
			return false;
		}
	}
	var finalLineResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
	if (finalLineResultArray !== null) {
		if (finalLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, finalLineResultArray[1] + finalLineResultArray[2]);
		}
	} else {
		message_locator_service("MISSED THE FINAL LINE...!");
		return false;
	}
	fileSystem_Module.closeSync(currentFileHandle);
	return true;
}

function array_from_file_delete(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		fileSystem_Module.unlinkSync(entire_fileName);
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

function array_from_file(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

// Switching html head area to minified targets...
function toMin(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var hasMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(?:\\.min)+(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	var carelessAboutMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		if (hasMin_RegExp.exec(contentArray[i]) === null) {
			var regExp_ResultArray = carelessAboutMin_RegExp.exec(contentArray[i]);
			if (regExp_ResultArray !== null) {
				contentArray[i] = regExp_ResultArray[1] + ".min" + regExp_ResultArray[2] + carriageReturn;
				if (!changed) {
					changed = true;
				}
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

// Switching html head area to regular targets...
function toRegular(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var minSuspect_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)\\.min(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		var regExp_ResultArray = minSuspect_RegExp.exec(contentArray[i]);
		if (regExp_ResultArray !== null) {
			contentArray[i] = regExp_ResultArray[1] + regExp_ResultArray[2] + carriageReturn;
			if (!changed) {
				changed = true;
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

function delete_writingArray_ToFile(fileName, array) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(fileName)) {
		fileSystem_Module.unlinkSync(fileName);
	}
	var inHouseFileHandle = fileSystem_Module.openSync(fileName, 'w');
	for (var i = 0; i < (array.length - 1); i++) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[i] + "\n");
	}
	if (array[array.length - 1]) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[array.length - 1]);
	}
	fileSystem_Module.closeSync(inHouseFileHandle);
}

module.exports = {
  process_wildcard_input : function(direction, source, directory) {
	  console.log("DIRECTION: \"" + direction + "\" SOURCE: \"" + source + "\" DIRECTORY: \"" + directory + "\"\n");
	  var wildcard_extractor_RegExp = new RegExp("^\\*(.+)$");
	  var result_array = wildcard_extractor_RegExp.exec(source);

	  console.log("WIRDCARD: \"" + result_array[1] + "\"");
	  var wildcard_RegExp = new RegExp(source + "$", "i");
	  var fileSystem_Module = globalModule_Try('fs');
	  var raw_file_array = fileSystem_Module.readdirSync(directory);
	  var targets_file_array = [];
	  for (var i = 0; i < raw_file_array.length; i++) {
		  console.log(raw_file_array[i]);
	  }
  },

  toggle_all_head_links : function(direction, file) {
	  var pointToMin = false;
	  if (direction === 'min') {
		  pointToMin = true;
	  }
	  var targetFile_LineArray = array_from_file(file);
	  if (targetFile_LineArray) {
		  var windowsNeeded_carriageReturn = "";
		  if (carriage_return_needed) {
			  windowsNeeded_carriageReturn = "\r";
		  }
		  var headStart = spot_the_head(targetFile_LineArray)[0];
		  var headEnd = spot_the_head(targetFile_LineArray)[1];

		  // Actual array manipulation...
		  if (pointToMin) {
			  targetFile_LineArray = toMin(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  } else {
			  targetFile_LineArray = toRegular(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  }
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  },

  end_of_line_refresh : function(file) {
	  console.log("CURRENTLY REFRESHING FILE: \"" + file + "\"");
	  var targetFile_LineArray = array_from_file_delete(file);
	  if (targetFile_LineArray) {
		  return end_of_line_clean_save(file, targetFile_LineArray, carriage_return_needed());
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  }
};
<|endoftext|>


<commit_before>define([
    'jquery',
    'angular',
    'qlik',
    'text!./TabbedContainer.css',
    'text!./template.html',
    './properties/definition',
    './constants/colors',
    './services/tabService',
    './services/colorsService',
    './directives/stackedContainer'
],

    function($, a, qlik, cssStyles, template, definition, colors) {
        var colorsService;

        $("<style>").html(cssStyles).appendTo("head");

        return {
            initialProperties: {
                version: 1.0
            },
            definition: definition,
            support: {
                snapshot: true,
                export: false,
                exportData: false
            },
            template: template,
            priority: 0,
            paint: function($element, layout) {
                /* the background of the container can be determined
                 * by the color picker or the text input. The latter has priority. */
                if(layout.backgroundColorCode.length > 0) {
                    var tileBackground = layout.backgroundColorCode;
                } else {
                    var tileBackgroundRgb = colors.palette[layout.backgroundColor]);
                    var tileBackground = colorsService.toString(tileBackgroundRgb, 0.2);
                }

                // Paint the border and the background of the object container
                var tileBorder = colorsService.hexToRgb(colors.palette[layout.borderColor]);
                $element.find('.tab_container').css('border-color', colorsService.toString(tileBorder));
                $element.find('.tab_content').css('background-color', tileBackground);

                return qlik.Promise.resolve();
            },
            resize: function($element, layout) {

                this.paint($element, layout);

            },
            controller: ['$scope', '$timeout', 'tabService', 'colorsService',
                function($scope, $timeout, tabService, cService) {
                    colorsService = cService;
                    $scope.layout.colors = colors;
                    $scope.currentObject;

                    $scope.isTabActive = function(tab, activeTab) {
                        return tab.id === activeTab.id;
                    }

                    $scope.getTabStyles = function(tab, activeTab) {
                        var buttonBackground = colorsService.hexToRgb(colors.palette[$scope.layout.buttonColor])

                        return $scope.isTabActive(tab, activeTab) ?
                            {
                                'background-color': colorsService.toString(buttonBackground, 0.2),
                                'border-color': colorsService.toString(buttonBackground)
                            } :
                            {
                                'background-color': colors.inactive.background,
                                'border-color': colors.inactive.border
                            }
                    }

                    $scope.onTabClick = function(index) {
                        $scope.activeTab = $scope.tabItems[index];

                        qlik.currApp().getObject(
                            $('#' + $scope.localId + '_' + $scope.activeTab.id),
                            $scope.activeTab.objectid
                        )
                    }

                    $scope.localId = $scope.$parent.options.id;
                    $scope.tabItems = tabService.getTabInfo($scope);
                    $scope.activeTab = $scope.tabItems[0];

                    /** Reinitialize the tabItems object if the layout changes,
                     * which happens when the user gives some input.
                     *
                     * Then, check for the following scenarios:
                     *     1. The first tab is added -> render it inmediately
                     *     2. The active tab was removed -> take user to tab 0
                     *     3. Otherwise, reload the current object */
                    $scope.$watch('layout', function(newValue){
                        var prevNumberTabs = $scope.tabItems.length;
                        $scope.tabItems = tabService.getTabInfo($scope);

                        if(prevNumberTabs === 0 && $scope.tabItems.length > 0){
                            $scope.onTabClick(0);
                        } else if($scope.tabItems.length > 0){
                            // if active tab is -1, then it was removed
                            var activeTabIndex = -1;
                            for(var i=0; i<$scope.tabItems.length; i++){
                                if($scope.tabItems[i].index === $scope.activeTab.index) {
                                    activeTabIndex = i;
                                    break;
                                }
                            }

                            $timeout(function(){
                                (activeTabIndex === -1) ? $scope.onTabClick(0)
                                    : $scope.onTabClick(activeTabIndex);
                            },200)
                        }
                    }, true);
                }
            ]
        };

    }
);
<commit_msg>Syntax fix<commit_after>define([
    'jquery',
    'angular',
    'qlik',
    'text!./TabbedContainer.css',
    'text!./template.html',
    './properties/definition',
    './constants/colors',
    './services/tabService',
    './services/colorsService',
    './directives/stackedContainer'
],

    function($, a, qlik, cssStyles, template, definition, colors) {
        var colorsService;

        $("<style>").html(cssStyles).appendTo("head");

        return {
            initialProperties: {
                version: 1.0
            },
            definition: definition,
            support: {
                snapshot: true,
                export: false,
                exportData: false
            },
            template: template,
            priority: 0,
            paint: function($element, layout) {
                /* the background of the container can be determined
                 * by the color picker or the text input. The latter has priority. */
                if(layout.backgroundColorCode.length > 0) {
                    var tileBackground = layout.backgroundColorCode;
                } else {
                    var tileBackgroundRgb = colors.palette([layout.backgroundColor]);
                    var tileBackground = colorsService.toString(tileBackgroundRgb, 0.2);
                }

                // Paint the border and the background of the object container
                var tileBorder = colorsService.hexToRgb(colors.palette[layout.borderColor]);
                $element.find('.tab_container').css('border-color', colorsService.toString(tileBorder));
                $element.find('.tab_content').css('background-color', tileBackground);

                return qlik.Promise.resolve();
            },
            resize: function($element, layout) {

                this.paint($element, layout);

            },
            controller: ['$scope', '$timeout', 'tabService', 'colorsService',
                function($scope, $timeout, tabService, cService) {
                    colorsService = cService;
                    $scope.layout.colors = colors;
                    $scope.currentObject;

                    $scope.isTabActive = function(tab, activeTab) {
                        return tab.id === activeTab.id;
                    }

                    $scope.getTabStyles = function(tab, activeTab) {
                        var buttonBackground = colorsService.hexToRgb(colors.palette[$scope.layout.buttonColor])

                        return $scope.isTabActive(tab, activeTab) ?
                            {
                                'background-color': colorsService.toString(buttonBackground, 0.2),
                                'border-color': colorsService.toString(buttonBackground)
                            } :
                            {
                                'background-color': colors.inactive.background,
                                'border-color': colors.inactive.border
                            }
                    }

                    $scope.onTabClick = function(index) {
                        $scope.activeTab = $scope.tabItems[index];

                        qlik.currApp().getObject(
                            $('#' + $scope.localId + '_' + $scope.activeTab.id),
                            $scope.activeTab.objectid
                        )
                    }

                    $scope.localId = $scope.$parent.options.id;
                    $scope.tabItems = tabService.getTabInfo($scope);
                    $scope.activeTab = $scope.tabItems[0];

                    /** Reinitialize the tabItems object if the layout changes,
                     * which happens when the user gives some input.
                     *
                     * Then, check for the following scenarios:
                     *     1. The first tab is added -> render it inmediately
                     *     2. The active tab was removed -> take user to tab 0
                     *     3. Otherwise, reload the current object */
                    $scope.$watch('layout', function(newValue){
                        var prevNumberTabs = $scope.tabItems.length;
                        $scope.tabItems = tabService.getTabInfo($scope);

                        if(prevNumberTabs === 0 && $scope.tabItems.length > 0){
                            $scope.onTabClick(0);
                        } else if($scope.tabItems.length > 0){
                            // if active tab is -1, then it was removed
                            var activeTabIndex = -1;
                            for(var i=0; i<$scope.tabItems.length; i++){
                                if($scope.tabItems[i].index === $scope.activeTab.index) {
                                    activeTabIndex = i;
                                    break;
                                }
                            }

                            $timeout(function(){
                                (activeTabIndex === -1) ? $scope.onTabClick(0)
                                    : $scope.onTabClick(activeTabIndex);
                            },200)
                        }
                    }, true);
                }
            ]
        };

    }
);
<|endoftext|>


<commit_before>import SPELLS from 'common/SPELLS';

import CoreAbilities from 'parser/core/modules/Abilities';
import SpellLink from 'common/SpellLink';
import React from 'react';

class Abilities extends CoreAbilities {
  spellbook() {
    const combatant = this.selectedCombatant;
    return [
      {
        spell: SPELLS.ASCENDANCE_TALENT_ENHANCEMENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 180,
        gcd: {
          base: 1500,
        },
        enabled: combatant.hasTalent(SPELLS.ASCENDANCE_TALENT_ENHANCEMENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 1.0,
        },
      },
      {
        spell: SPELLS.FERAL_SPIRIT,
        buffSpellId: [ //Feral Spirit isn't an actual buff, so we can only show the Elemental Spirits buffs
          SPELLS.ELEMENTAL_SPIRITS_BUFF_MOLTEN_WEAPON.id,
          SPELLS.ELEMENTAL_SPIRITS_BUFF_ICY_EDGE.id,
          SPELLS.ELEMENTAL_SPIRITS_BUFF_CRACKLING_SURGE.id,
        ],
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: combatant.hasTalent(SPELLS.ELEMENTAL_SPIRITS_TALENT) ? 90 : 120,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
        },
      },
      {
        spell: SPELLS.EARTH_ELEMENTAL,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 300,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          minor: 0.9,
          recommendedEfficiency: 0.8,
          extraSuggestion: (
            <>
              The total damage that it deals is equal to 2-3 GCDs. Additionally their attacks have a chance to trigger <SpellLink id={SPELLS.STORMBRINGER.id} />, weapon enchantments, azerite traits and essence effects. (Corruption effects have not been confirmed.)
            </>
          ),
        },
      },
      {
        spell: SPELLS.EARTHEN_SPIKE_TALENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        enabled: combatant.hasTalent(SPELLS.EARTHEN_SPIKE_TALENT.id),
        cooldown: 20,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
        },
      },
      {
        spell: SPELLS.TOTEM_MASTERY_TALENT_ENHANCEMENT,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        enabled: combatant.hasTalent(SPELLS.TOTEM_MASTERY_TALENT_ENHANCEMENT.id),
        gcd: {
          base: 1000,
        },
        cooldown: 120,
      },
      {
        spell: SPELLS.LIGHTNING_BOLT_ENHANCE,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        cooldown: combatant.hasTalent(SPELLS.OVERCHARGE_TALENT) ? 7.5 : 0,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.WIND_SHEAR,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        cooldown: 12,
        gcd: null,
      },
      {
        spell: SPELLS.ROCKBITER,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        charges: 2,
        cooldown: haste => (combatant.hasTalent(SPELLS.BOULDERFIST_TALENT.id) ? 6 * 0.85 : 6) / (1 + haste),
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.FROSTBRAND,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.FLAMETONGUE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
        cooldown: haste => 12 / (1 + haste),
      },
      {
        spell: SPELLS.STORMSTRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 9 / (1 + haste),
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.LAVA_LASH,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CRASH_LIGHTNING,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL_AOE,
        gcd: {
          base: 1500,
        },
        cooldown: haste => 6 / (1 + haste),
      },
      {
        spell: SPELLS.FERAL_LUNGE_TALENT,
        enabled: combatant.hasTalent(SPELLS.FERAL_LUNGE_TALENT),
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
      },
      {
        spell: SPELLS.SPIRIT_WALK,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 60,
      },
      {
        spell: SPELLS.GHOST_WOLF,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CAPACITOR_TOTEM,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        cooldown: 60,
      },
      {
        spell: SPELLS.EARTHBIND_TOTEM,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        cooldown: 30,
      },
      {
        spell: SPELLS.TREMOR_TOTEM,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        cooldown: 60,
      },
      {
        spell: SPELLS.WIND_RUSH_TOTEM_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.WIND_RUSH_TOTEM_TALENT),
        gcd: {
          base: 1500,
        },
        cooldown: 120,
      },
      {
        spell: SPELLS.HEALING_SURGE_ENHANCE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.PURGE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.HEX,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CLEANSE_SPIRIT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 8,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.ASTRAL_SHIFT,
        buffSpellId: SPELLS.ASTRAL_SHIFT.id,
        cooldown: 90,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        isDefensive: true,
      },
      {
        spell: SPELLS.FURY_OF_AIR_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL_AOE,
        gcd: {
          base: 1500,
        },
        enabled: combatant.hasTalent(SPELLS.FURY_OF_AIR_TALENT.id),
      },
      {
        spell: SPELLS.SUNDERING_TALENT,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        gcd: {
          base: 1500,
        },
        enabled: combatant.hasTalent(SPELLS.SUNDERING_TALENT.id),
        cooldown: 40,
      },
      {
        spell: SPELLS.LIGHTNING_SHIELD_TALENT,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        gcd: null,
        enabled: combatant.hasTalent(SPELLS.LIGHTNING_SHIELD_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0,
        },
      },
      {
        spell: SPELLS.REINCARNATION,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: [SPELLS.BLOODLUST, SPELLS.HEROISM],
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        gcd: null,
      },

      {
        spell: SPELLS.BERSERKING,
        buffSpellId: SPELLS.BERSERKING.id,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 180,
        isUndetectable: true,
        gcd: null,
        castEfficiency: {
          suggestion: true,
        },
      },
      {
        spell: [SPELLS.BLOOD_FURY_PHYSICAL, SPELLS.BLOOD_FURY_SPELL_AND_PHYSICAL, SPELLS.BLOOD_FURY_SPELL],
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 120,
        isUndetectable: true,
        gcd: null,
        castEfficiency: {
          suggestion: true,
        },
      },
    ];
  }
}

export default Abilities;
<commit_msg>Marked most utility abilities as 'undetectable'<commit_after>import SPELLS from 'common/SPELLS';

import CoreAbilities from 'parser/core/modules/Abilities';
import SpellLink from 'common/SpellLink';
import React from 'react';

class Abilities extends CoreAbilities {
  spellbook() {
    const combatant = this.selectedCombatant;
    return [
      {
        spell: SPELLS.ASCENDANCE_TALENT_ENHANCEMENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 180,
        gcd: {
          base: 1500,
        },
        enabled: combatant.hasTalent(SPELLS.ASCENDANCE_TALENT_ENHANCEMENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 1.0,
        },
      },
      {
        spell: SPELLS.FERAL_SPIRIT,
        buffSpellId: [ //Feral Spirit isn't an actual buff, so we can only show the Elemental Spirits buffs
          SPELLS.ELEMENTAL_SPIRITS_BUFF_MOLTEN_WEAPON.id,
          SPELLS.ELEMENTAL_SPIRITS_BUFF_ICY_EDGE.id,
          SPELLS.ELEMENTAL_SPIRITS_BUFF_CRACKLING_SURGE.id,
        ],
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: combatant.hasTalent(SPELLS.ELEMENTAL_SPIRITS_TALENT) ? 90 : 120,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
        },
      },
      {
        spell: SPELLS.EARTH_ELEMENTAL,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 300,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          minor: 0.9,
          recommendedEfficiency: 0.8,
          extraSuggestion: (
            <>
              The total damage that it deals is equal to 2-3 GCDs. Additionally their attacks have a chance to trigger <SpellLink id={SPELLS.STORMBRINGER.id} />, weapon enchantments, azerite traits and essence effects. (Corruption effects have not been confirmed.)
            </>
          ),
        },
      },
      {
        spell: SPELLS.EARTHEN_SPIKE_TALENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        enabled: combatant.hasTalent(SPELLS.EARTHEN_SPIKE_TALENT.id),
        cooldown: 20,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
        },
      },
      {
        spell: SPELLS.TOTEM_MASTERY_TALENT_ENHANCEMENT,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        enabled: combatant.hasTalent(SPELLS.TOTEM_MASTERY_TALENT_ENHANCEMENT.id),
        gcd: {
          base: 1000,
        },
        cooldown: 120,
      },
      {
        spell: SPELLS.LIGHTNING_BOLT_ENHANCE,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        cooldown: combatant.hasTalent(SPELLS.OVERCHARGE_TALENT) ? 7.5 : 0,
        gcd: {
          base: 1500,
        },
        isUndetectable: true,
      },
      {
        spell: SPELLS.WIND_SHEAR,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        cooldown: 12,
        gcd: null,
      },
      {
        spell: SPELLS.ROCKBITER,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        charges: 2,
        cooldown: haste => (combatant.hasTalent(SPELLS.BOULDERFIST_TALENT.id) ? 6 * 0.85 : 6) / (1 + haste),
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.FROSTBRAND,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.FLAMETONGUE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
        cooldown: haste => 12 / (1 + haste),
      },
      {
        spell: SPELLS.STORMSTRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 9 / (1 + haste),
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.LAVA_LASH,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CRASH_LIGHTNING,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL_AOE,
        gcd: {
          base: 1500,
        },
        cooldown: haste => 6 / (1 + haste),
      },
      {
        spell: SPELLS.FERAL_LUNGE_TALENT,
        enabled: combatant.hasTalent(SPELLS.FERAL_LUNGE_TALENT),
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
      },
      {
        spell: SPELLS.SPIRIT_WALK,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 60,
      },
      {
        spell: SPELLS.GHOST_WOLF,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CAPACITOR_TOTEM,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        cooldown: 60,
        isUndetectable: true,
      },
      {
        spell: SPELLS.EARTHBIND_TOTEM,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        cooldown: 30,
        isUndetectable: true,
      },
      {
        spell: SPELLS.TREMOR_TOTEM,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        cooldown: 60,
        isUndetectable: true,
      },
      {
        spell: SPELLS.WIND_RUSH_TOTEM_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.WIND_RUSH_TOTEM_TALENT),
        gcd: {
          base: 1500,
        },
        cooldown: 120,
      },
      {
        spell: SPELLS.HEALING_SURGE_ENHANCE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        isUndetectable: true,
      },
      {
        spell: SPELLS.PURGE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
        isUndetectable: true,
      },
      {
        spell: SPELLS.HEX,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
        isUndetectable: true,
      },
      {
        spell: SPELLS.CLEANSE_SPIRIT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 8,
        gcd: {
          base: 1500,
        },
        isUndetectable: true,
      },
      {
        spell: SPELLS.ASTRAL_SHIFT,
        buffSpellId: SPELLS.ASTRAL_SHIFT.id,
        cooldown: 90,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        isDefensive: true,
      },
      {
        spell: SPELLS.FURY_OF_AIR_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL_AOE,
        gcd: {
          base: 1500,
        },
        enabled: combatant.hasTalent(SPELLS.FURY_OF_AIR_TALENT.id),
      },
      {
        spell: SPELLS.SUNDERING_TALENT,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        gcd: {
          base: 1500,
        },
        enabled: combatant.hasTalent(SPELLS.SUNDERING_TALENT.id),
        cooldown: 40,
      },
      {
        spell: SPELLS.LIGHTNING_SHIELD_TALENT,
        category: Abilities.SPELL_CATEGORIES.OTHERS,
        gcd: null,
        enabled: combatant.hasTalent(SPELLS.LIGHTNING_SHIELD_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0,
        },
        isUndetectable: true,
      },
      {
        spell: SPELLS.REINCARNATION,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        gcd: {
          base: 1500,
        },
        isUndetectable: true,
      },
      {
        spell: [SPELLS.BLOODLUST, SPELLS.HEROISM],
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        gcd: null,
        isUndetectable: true,
      },
      {
        spell: SPELLS.BERSERKING,
        buffSpellId: SPELLS.BERSERKING.id,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 180,
        isUndetectable: true,
        gcd: null,
        castEfficiency: {
          suggestion: true,
        },
      },
      {
        spell: [SPELLS.BLOOD_FURY_PHYSICAL, SPELLS.BLOOD_FURY_SPELL_AND_PHYSICAL, SPELLS.BLOOD_FURY_SPELL],
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 120,
        isUndetectable: true,
        gcd: null,
        castEfficiency: {
          suggestion: true,
        },
      },
    ];
  }
}

export default Abilities;
<|endoftext|>


<commit_before>'use strict';
const got = require('got');
const pluralize = require('pluralize');
const config = require('./config');
const copy = require('./copy');
const Shuffle = require('./schema').Shuffle;
const Team = require('./schema').Team;

function updateShuffleMessage(team, shuffle) {
    let text = copy.startMessageText;

    if (shuffle.people.length > 0) {
        let names = shuffle.people.map((person) => `@${person.name}`);

        // Add 'and' between the last two names
        if (names.length > 1) {
            const last = names.pop();
            const secondToLast = names.pop();
            const lastTwo = `${secondToLast} and ${last}`;
            names.push(lastTwo);
        }

        names = names.join(', ');

        text = `${copy.startMessageText} ${names} ${pluralize('has', shuffle.people.length)} already joined!`;
    }

    got.post('https://slack.com/api/chat.update', {
        json: true,
        timeout: 5000,
        body: {
            token: team.botAccessToken,
            ts: shuffle.messageTimestamp,
            channel: shuffle.channelId,
            parse: 'full',
            link_names: 1,
            text,
        },
    })
    .then((res) => res.body)
    .then((response) => {
        if (response.warning) {
            console.error(response.warning);
        }

        if (!response.ok) {
            console.error(response.error);
            return;
        }
    }, (error) => console.error(error));
}

function joinShuffle(teamId, channelId, user) {
    Promise.all([
        Team.findById(teamId).exec(),
        Shuffle.findOne({ teamId, channelId, active: true }).exec(),
    ]).then((values) => {
        const team = values[0];
        const shuffle = values[1];

        if (!shuffle) {
            return;
        }

        // User is already in the shuffle
        if (shuffle.people.find((p) => p.id === user.id)) {
            return;
        }

        shuffle.people.push({ _id: user.id, name: user.name });
        shuffle.save();

        updateShuffleMessage(team, shuffle);
    });
}

function leaveShuffle(teamId, channelId, user) {
    Promise.all([
        Team.findById(teamId).exec(),
        Shuffle.findOne({ teamId, channelId, active: true }).exec(),
    ]).then((values) => {
        const team = values[0];
        const shuffle = values[1];

        if (!shuffle) {
            return;
        }

        shuffle.people.id(user.id).remove();
        shuffle.save();

        updateShuffleMessage(team, shuffle);
    });
}

function *route() {
    let body = this.request.body.payload;

    if (!body) {
        this.response.status = 400;
        return;
    }

    body = JSON.parse(body);

    if (body.token !== config.SLACK_VERIFICATION_TOKEN) {
        this.response.status = 401;
        return;
    }

    const callback = body.callback_id;
    const action = body.actions[0].name;
    const teamId = body.team.id;
    const channelId = body.channel.id;
    const user = body.user;

    if (callback === 'start' && action === 'join') {
        this.body = '';
        joinShuffle(teamId, channelId, user);
    } else if (callback === 'start' && action === 'leave') {
        this.body = '';
        leaveShuffle(teamId, channelId, user);
    } else {
        this.body = {
            replace_original: false,
            text: copy.noopButton,
        };
    }
}

module.exports = route;
<commit_msg>buttons: improve validation<commit_after>'use strict';
const got = require('got');
const pluralize = require('pluralize');
const config = require('./config');
const copy = require('./copy');
const Shuffle = require('./schema').Shuffle;
const Team = require('./schema').Team;

function updateShuffleMessage(team, shuffle) {
    let text = copy.startMessageText;

    if (shuffle.people.length > 0) {
        let names = shuffle.people.map((person) => `@${person.name}`);

        // Add 'and' between the last two names
        if (names.length > 1) {
            const last = names.pop();
            const secondToLast = names.pop();
            const lastTwo = `${secondToLast} and ${last}`;
            names.push(lastTwo);
        }

        names = names.join(', ');

        text = `${copy.startMessageText} ${names} ${pluralize('has', shuffle.people.length)} already joined!`;
    }

    got.post('https://slack.com/api/chat.update', {
        json: true,
        timeout: 5000,
        body: {
            token: team.botAccessToken,
            ts: shuffle.messageTimestamp,
            channel: shuffle.channelId,
            parse: 'full',
            link_names: 1,
            text,
        },
    })
    .then((res) => res.body)
    .then((response) => {
        if (response.warning) {
            console.error(response.warning);
        }

        if (!response.ok) {
            console.error(response.error);
            return;
        }
    }, (error) => console.error(error));
}

function joinShuffle(teamId, channelId, user) {
    Promise.all([
        Team.findById(teamId).exec(),
        Shuffle.findOne({ teamId, channelId, active: true }).exec(),
    ]).then((values) => {
        const team = values[0];
        const shuffle = values[1];

        if (!team || !shuffle) {
            return;
        }

        // User is already in the shuffle
        if (shuffle.people.find((p) => p.id === user.id)) {
            return;
        }

        shuffle.people.push({ _id: user.id, name: user.name });
        shuffle.save();

        updateShuffleMessage(team, shuffle);
    });
}

function leaveShuffle(teamId, channelId, user) {
    Promise.all([
        Team.findById(teamId).exec(),
        Shuffle.findOne({ teamId, channelId, active: true }).exec(),
    ]).then((values) => {
        const team = values[0];
        const shuffle = values[1];

        if (!team || !shuffle) {
            return;
        }

        shuffle.people.id(user.id).remove();
        shuffle.save();

        updateShuffleMessage(team, shuffle);
    });
}

function *route() {
    let body = this.request.body.payload;

    if (!body) {
        this.response.status = 400;
        return;
    }

    body = JSON.parse(body);

    if (body.token !== config.SLACK_VERIFICATION_TOKEN) {
        this.response.status = 401;
        return;
    }

    const callback = body.callback_id;
    const action = body.actions[0].name;
    const teamId = body.team.id;
    const channelId = body.channel.id;
    const user = body.user;

    if (callback === 'start' && action === 'join') {
        this.body = '';
        joinShuffle(teamId, channelId, user);
    } else if (callback === 'start' && action === 'leave') {
        this.body = '';
        leaveShuffle(teamId, channelId, user);
    } else {
        this.body = {
            replace_original: false,
            text: copy.noopButton,
        };
    }
}

module.exports = route;
<|endoftext|>


<commit_before>/*
 * The webapp module provides support for building web applications in RingoJS.
 */

// import modules
require('core/object');
require('core/string');

include('ringo/webapp/request');
include('ringo/webapp/response');

var engine = require('ringo/engine');
var Server = require('ringo/httpserver').Server;

export('start', 'stop', 'getConfig', 'handleRequest');

var server;
var log = require('ringo/logging').getLogger(module.id);

module.shared = true;

/**
 * Handler function called by the JSGI servlet.
 *
 * @param env the JSGI environment argument
 */
function handleRequest(env) {
    // get config and apply it to req, res
    var config = getConfig();
    if (log.isDebugEnabled()){
        log.debug('got config: ' + config.toSource());
    }

    var webenv = require('ringo/webapp/env');
    webenv.env = env;
    var req = webenv.req = new Request(env);
    var res = null;

    req.charset = config.charset || 'utf8';

    // URI-decode path-info
    req.pathInfo = decodeURI(req.pathInfo);
    // remember current scriptname as application root as scriptName will be
    // set to actual script by resolveInConfig().
    req.rootPath = req.scriptName;

    try {
        res = resolveInConfig(req, config);
    } catch (e if e.redirect) {
        return new RedirectResponse(e.redirect);
    }
    return res;
}

function resolveInConfig(req, config) {
    if (log.isDebugEnabled()) {
        log.debug('resolving path ' + req.pathInfo);
    }
    // set the root context path on which this app is mounted in the config module
    config.rootPath = req.scriptName + "/";
    // set config property in webapp env module
    var webenv = require('ringo/webapp/env');
    webenv.addConfig(config);

    if (!Array.isArray(config.urls)) {
        log.info("No URL mapping defined (urls is " + config.urls + "), throwing 404.");
        throw {notfound: true};
    }

    var path = req.pathInfo.replace(/^\/+|\/+$/g, "");

    for each (var urlEntry in config.urls) {
        if (!Array.isArray(urlEntry) || urlEntry.length < 2) {
            log.info("Ignoring unsupported URL mapping: " + urlEntry);
            continue;
        }
        if (log.isDebugEnabled()) {
            log.debug("checking url line: " + urlEntry);
        }
        var match = getPattern(urlEntry).exec(path);
        if (log.isDebugEnabled()) {
            log.debug("got match: " + match);
        }

        if (match) {
            var module = getModule(urlEntry);
            if (log.isDebugEnabled()) {
                log.debug("module: " + module);
            }
            // move matching path fragment from PATH_INFO to SCRIPT_NAME
            req.appendToScriptName(match[0]);
            // prepare action arguments, adding regexp capture groups if any
            var args = [req].concat(match.slice(1));
            // lookup action in module
            var action = getAction(req, module, urlEntry, args);
            // log.debug("got action: " + action);
            if (typeof action == "function") {
                var res = action.apply(module, args);
                if (res && typeof res.close === 'function') {
                    return res.close();
                }
                return res;
            } else if (Array.isArray(module.urls)) {
                return resolveInConfig(req, module);
            }
        }
    }
    throw { notfound: true };
}

function getPattern(spec) {
    var pattern = spec[0];
    if (typeof pattern == "string") {
        if (pattern.startsWith("/"))
            pattern = pattern.replace("/", "^");
        pattern = spec[0] = new RegExp(pattern);
    } else if (!(pattern instanceof RegExp)) {
        throw Error("Pattern must be a regular expression or string");
    }
    return pattern;
}

function getModule(spec) {
    var module = spec[1];
    if (typeof module == "string") {
        module = require(module);
    } else if (!(module instanceof Object)) {
        throw Error("Module must be a string or object");
    }
    return module;
}

function getAction(req, module, urlconf, args) {
    var path = splitPath(req.pathInfo);
    var action;
    // if url-conf has a hard-coded action name use it
    var name = urlconf[2];
    if (typeof module === "function") {
        action = module;
    } else {
        if (!name) {
            // action name is not defined in url mapping, try to get it from the request path
            name = path[0];
            if (name) {
                action = module[name.replace(/\./g, "_")];
                if (typeof action == "function") {
                    // If the request path contains additional elements check whether the
                    // candidate function has formal arguments to take them
                    if (path.length <= 1 || args.length + path.length - 1 <= action.length) {
                        req.appendToScriptName(name);
                        Array.prototype.push.apply(args, path.slice(1));
                        return action;
                    }
                }
            }
            // no matching action, fall back to "index"
            name = "index";
        }
        action = module[name];
    }
    if (typeof action == "function") {
        // insert predefined arguments if defined in url-conf
        if (urlconf.length > 3) {
            var spliceArgs = [1, 0].concat(urlconf.slice(3));
            Array.prototype.splice.apply(args, spliceArgs);
        }
        if (path.length == 0 || args.length + path.length <= action.length) {
            if (args.slice(1).join('').length == 0) {
                req.checkTrailingSlash();
            }
            Array.prototype.push.apply(args, path);
            return action;
        }
    }
    return null;
}

function splitPath(path) {
    //remove leading and trailing slashes and split
    var array = path.replace(/^\/+|\/+$/g, "").split(/\/+/);
    return array.length == 1 && array[0] == "" ? [] : array;
}

/**
 * Try to load the configuration module.
 * @param configModuleName optional module name, default is 'config'
 */
function getConfig(configModuleName) {
    configModuleName = configModuleName || 'config';
    return require(configModuleName);
}

/**
 * Start the jetty server using the given config module, or the
 * default "config" module if called without argument.
 */
function start(config) {
    // start jetty http server
    config = config || getConfig();
    var httpConfig = Object.merge(config.httpConfig || {}, {
        moduleName: "config",
        functionName: "app"
    });

    server = new Server(httpConfig).start();
}

/**
 * Stop the jetty server.
 */
function stop() {
    // stop jetty HTTP server
    server.stop();
}

if (require.main == module.id) {
    for (var i = 1; i < system.args.length; i++) {
        var arg = system.args[i];
        if (arg.indexOf('-') == 0) {
            break;
        }
        engine.addRepository(arg);
    }
    log.info('Setup module search: ' + engine.getRepositories());
    start();
}
<commit_msg>Some more debugging output in helma/webapp<commit_after>/*
 * The webapp module provides support for building web applications in RingoJS.
 */

// import modules
require('core/object');
require('core/string');

include('ringo/webapp/request');
include('ringo/webapp/response');

var engine = require('ringo/engine');
var Server = require('ringo/httpserver').Server;

export('start', 'stop', 'getConfig', 'handleRequest');

var server;
var log = require('ringo/logging').getLogger(module.id);

module.shared = true;

/**
 * Handler function called by the JSGI servlet.
 *
 * @param env the JSGI environment argument
 */
function handleRequest(env) {
    // get config and apply it to req, res
    var config = getConfig();
    if (log.isDebugEnabled()){
        log.debug('got config: ' + config.toSource());
    }

    var webenv = require('ringo/webapp/env');
    webenv.env = env;
    var req = webenv.req = new Request(env);
    var res = null;

    req.charset = config.charset || 'utf8';

    // URI-decode path-info
    req.pathInfo = decodeURI(req.pathInfo);
    // remember current scriptname as application root as scriptName will be
    // set to actual script by resolveInConfig().
    req.rootPath = req.scriptName;

    try {
        res = resolveInConfig(req, config);
    } catch (e if e.redirect) {
        return new RedirectResponse(e.redirect);
    }
    return res;
}

function resolveInConfig(req, config) {
    if (log.isDebugEnabled()) {
        log.debug('resolving path ' + req.pathInfo);
    }
    // set the root context path on which this app is mounted in the config module
    config.rootPath = req.scriptName + "/";
    // set config property in webapp env module
    var webenv = require('ringo/webapp/env');
    webenv.addConfig(config);

    if (!Array.isArray(config.urls)) {
        log.info("No URL mapping defined (urls is " + config.urls + "), throwing 404.");
        throw {notfound: true};
    }

    var path = req.pathInfo.replace(/^\/+|\/+$/g, "");

    for each (var urlEntry in config.urls) {
        if (!Array.isArray(urlEntry) || urlEntry.length < 2) {
            log.info("Ignoring unsupported URL mapping: " + urlEntry);
            continue;
        }
        if (log.isDebugEnabled()) {
            log.debug("checking url line: " + urlEntry);
        }
        var match = getPattern(urlEntry).exec(path);
        if (log.isDebugEnabled()) {
            log.debug("got match: " + match);
        }

        if (match) {
            var module = getModule(urlEntry);
            if (log.isDebugEnabled()) {
                log.debug("module: " + module);
            }
            // move matching path fragment from PATH_INFO to SCRIPT_NAME
            req.appendToScriptName(match[0]);
            // prepare action arguments, adding regexp capture groups if any
            var args = [req].concat(match.slice(1));
            // lookup action in module
            var action = getAction(req, module, urlEntry, args);
            // log.debug("got action: " + action);
            if (typeof action == "function") {
                var res = action.apply(module, args);
                if (res && typeof res.close === 'function') {
                    return res.close();
                }
                return res;
            } else if (Array.isArray(module.urls)) {
                return resolveInConfig(req, module);
            } else {
                log.error("Unable to resolve action for : " + action);
            }
        }
    }
    throw { notfound: true };
}

function getPattern(spec) {
    var pattern = spec[0];
    if (typeof pattern == "string") {
        if (pattern.startsWith("/"))
            pattern = pattern.replace("/", "^");
        pattern = spec[0] = new RegExp(pattern);
    } else if (!(pattern instanceof RegExp)) {
        throw Error("Pattern must be a regular expression or string");
    }
    return pattern;
}

function getModule(spec) {
    var module = spec[1];
    if (typeof module == "string") {
        if (log.isDebugEnabled()) {
            log.debug("requiring module", module);
        }
        module = require(module);
    } else if (!(module instanceof Object)) {
        throw Error("Module must be a string or object");
    }
    return module;
}

function getAction(req, module, urlconf, args) {
    var path = splitPath(req.pathInfo);
    var action;
    // if url-conf has a hard-coded action name use it
    var name = urlconf[2];
    if (typeof module === "function") {
        action = module;
    } else {
        if (!name) {
            // action name is not defined in url mapping, try to get it from the request path
            name = path[0];
            if (name) {
                action = module[name.replace(/\./g, "_")];
                if (typeof action == "function") {
                    // If the request path contains additional elements check whether the
                    // candidate function has formal arguments to take them
                    if (path.length <= 1 || args.length + path.length - 1 <= action.length) {
                        req.appendToScriptName(name);
                        Array.prototype.push.apply(args, path.slice(1));
                        return action;
                    }
                }
            }
            // no matching action, fall back to "index"
            name = "index";
        }
        action = module[name];
    }
    if (typeof action == "function") {
        // insert predefined arguments if defined in url-conf
        if (urlconf.length > 3) {
            var spliceArgs = [1, 0].concat(urlconf.slice(3));
            Array.prototype.splice.apply(args, spliceArgs);
        }
        if (path.length == 0 || args.length + path.length <= action.length) {
            if (args.slice(1).join('').length == 0) {
                req.checkTrailingSlash();
            }
            Array.prototype.push.apply(args, path);
            return action;
        }
    }
    return null;
}

function splitPath(path) {
    //remove leading and trailing slashes and split
    var array = path.replace(/^\/+|\/+$/g, "").split(/\/+/);
    return array.length == 1 && array[0] == "" ? [] : array;
}

/**
 * Try to load the configuration module.
 * @param configModuleName optional module name, default is 'config'
 */
function getConfig(configModuleName) {
    configModuleName = configModuleName || 'config';
    return require(configModuleName);
}

/**
 * Start the jetty server using the given config module, or the
 * default "config" module if called without argument.
 */
function start(config) {
    // start jetty http server
    config = config || getConfig();
    var httpConfig = Object.merge(config.httpConfig || {}, {
        moduleName: "config",
        functionName: "app"
    });

    server = new Server(httpConfig).start();
}

/**
 * Stop the jetty server.
 */
function stop() {
    // stop jetty HTTP server
    server.stop();
}

if (require.main == module.id) {
    for (var i = 1; i < system.args.length; i++) {
        var arg = system.args[i];
        if (arg.indexOf('-') == 0) {
            break;
        }
        engine.addRepository(arg);
    }
    log.info('Setup module search: ' + engine.getRepositories());
    start();
}
<|endoftext|>


<commit_before>/**
 * React Native Playground
 * https://github.com/jsierles/rnplay
 */

'use strict';

var React = require('react-native');

var {
  ActivityIndicatorIOS,
  AppRegistry,
  StyleSheet,
  Text,
  ListView,
  View,
  Image,
  TouchableOpacity
} = React;

var ReactART = require('ReactNativeART');
var AppReloader = require('NativeModules').AppReloader;
var Camera = require('react-native-camera');
var Overlay = require('react-native-overlay');

var REQUEST_URL = 'http://rnplay.org/builds/0.4.4/plays/public.json';

var RNPlayNative = React.createClass({
  getInitialState: function() {
    return {
      loaded: false,
      isModalOpen: false,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
    };
  },

  componentDidMount: function() {
    this.fetchApps();
  },

  fetchApps: function() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((data) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(data),
          loaded: true
        });
      })
      .done();
  },

  renderAppList: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.header}>React Native Playground</Text>
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this.renderApp}
          style={styles.listView}
        />
        <TouchableOpacity onPress={() => this.setState({isModalOpen: true})}>
          <Image style={styles.cameraButton} resizeMode="contain" source={require("image!photo-camera5")} />
        </TouchableOpacity>
        <Overlay isVisible={this.state.isModalOpen}>
          <Camera
            ref="cam"
            style={styles.container}
            onBarCodeRead={this.onBarCodeRead}>
            <TouchableOpacity onPress={() => this.setState({isModalOpen: false})}>
              <Text style={styles.cancelButton}>X</Text>
            </TouchableOpacity>
          </Camera>
        </Overlay>
      </View>
    );
  },

  renderApp: function(app) {
    return (
      <TouchableOpacity onPress={() => this.selectApp(app)}>
        <Text style={styles.app}>{app.name || app.module_name}</Text>
      </TouchableOpacity>
    );
  },

  selectApp: function(app) {
    console.log(app);
    AppReloader.reloadAppWithURLString(app.bundle_url, app.module_name);
  },

  renderLoading: function() {
    return (
      <View style={styles.container}>
        <ActivityIndicatorIOS size="large" />
      </View>
    );
  },

  onBarCodeRead(data) {
    if (!this.barCodeRead) {
      this.barCodeRead = true
      var appdata = JSON.parse(data.data)
      AppReloader.reloadAppWithURLString(appdata.url, appdata.module_name);
    }
  },

  render: function() {
    if (!this.state.loaded) {
      return this.renderLoading();
    } else {
      return this.renderAppList();
    }
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 30
  },
  cameraButton: {
    height: 60,
    width: 20,
    alignSelf: 'center',
    marginLeft: 5
  },
  cancelButton: {
    color: '#fff',
    flex: 1,
    fontSize: 25,
    marginLeft: 20
  },
  header: {
    textAlign: "center",
    fontSize: 25,
    paddingBottom: 20,
    color: '#888'
  },
  app: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
    color: '#2B608A'
  }
});

AppRegistry.registerComponent('RNPlayNative', () => RNPlayNative);
<commit_msg>display play usernames and avatars<commit_after>/**
 * React Native Playground
 * https://github.com/jsierles/rnplay
 */

'use strict';

var React = require('react-native');

var {
  ActivityIndicatorIOS,
  AppRegistry,
  StyleSheet,
  Text,
  ListView,
  View,
  Image,
  TouchableOpacity
} = React;

var ReactART = require('ReactNativeART');
var AppReloader = require('NativeModules').AppReloader;
var Camera = require('react-native-camera');
var Overlay = require('react-native-overlay');

var REQUEST_URL = 'https://rnplay.org/builds/0.4.4/plays/public.json';

var RNPlayNative = React.createClass({
  getInitialState: function() {
    return {
      loaded: false,
      isModalOpen: false,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
    };
  },

  componentDidMount: function() {
    this.fetchApps();
  },

  fetchApps: function() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((data) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(data),
          loaded: true
        });
      })
      .done();
  },

  renderAppList: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.header}>React Native Playground</Text>
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this.renderApp}
          style={styles.listView}
        />
        <TouchableOpacity onPress={() => this.setState({isModalOpen: true})}>
          <Image style={styles.cameraButton} resizeMode="contain" source={require("image!photo-camera5")} />
        </TouchableOpacity>
        <Overlay isVisible={this.state.isModalOpen}>
          <Camera
            ref="cam"
            style={styles.container}
            onBarCodeRead={this.onBarCodeRead}>
            <TouchableOpacity onPress={() => this.setState({isModalOpen: false})}>
              <Text style={styles.cancelButton}>X</Text>
            </TouchableOpacity>
          </Camera>
        </Overlay>
      </View>
    );
  },

  renderApp: function(app) {
    return (
      <View style={styles.appContainer}>
        <TouchableOpacity onPress={() => this.selectApp(app)}>
          <Text style={styles.app}>{app.name || app.module_name}</Text>
        </TouchableOpacity>
        <View style={styles.creator}>
          <Text style={styles.username}>{app.creator.username || 'anonymous'}</Text>
          <Image style={styles.avatar} source={{uri: app.creator.avatar_url || 'https://facebook.github.io/react-native/img/header_logo.png'}} />
        </View>
      </View>
    );

  },

  selectApp: function(app) {
    AppReloader.reloadAppWithURLString(app.bundle_url, app.module_name);
  },

  renderLoading: function() {
    return (
      <View style={styles.container}>
        <ActivityIndicatorIOS size="large" />
      </View>
    );
  },

  onBarCodeRead(data) {
    if (!this.barCodeRead) {
      this.barCodeRead = true
      var appdata = JSON.parse(data.data)
      AppReloader.reloadAppWithURLString(appdata.url, appdata.module_name);
    }
  },

  render: function() {
    if (!this.state.loaded) {
      return this.renderLoading();
    } else {
      return this.renderAppList();
    }
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 30
  },
  appContainer: {
    marginBottom: 20
  },
  creator: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center'
  },
  username: {
    fontSize: 12,
    opacity: .5
  },
  cameraButton: {
    height: 60,
    width: 20,
    alignSelf: 'center',
    marginLeft: 5
  },
  avatar: {
    width: 20,
    height: 20,
    marginLeft: 5,
    borderRadius: 10,
    opacity: .5,
    marginTop: 3,
    backgroundColor: "#000"
  },
  cancelButton: {
    color: '#fff',
    flex: 1,
    fontSize: 25,
    marginLeft: 20
  },
  header: {
    textAlign: "center",
    fontSize: 25,
    paddingBottom: 20,
    color: '#888'
  },
  app: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
    color: '#2B608A'
  }
});

AppRegistry.registerComponent('RNPlayNative', () => RNPlayNative);
<|endoftext|>


<commit_before>// 'use strict';
//
// const esprima = require('esprima');
// // const escodegen = require('escodegen');
//
// /** @class */
// class AutoComplete {
//   getHintsByValue(currentExpression, currentWord) {
//     let root;
//
//     try {
//       root = esprima.parse(currentExpression);
//     } catch (err) {
//       return {
//         hints: null,
//         value: currentExpression
//       };
//     }
//
//     return {
//       hints: [],
//       value: currentExpression
//     };
//   }
// }
//
// /** @exports AutoComplete */
// module.exports = new AutoComplete();
<commit_msg>clean up comment out code<commit_after><|endoftext|>


<commit_before>// ==========================================================================
//                            DG.Attribute
//
//  Copyright (c) 2014 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

sc_require('models/model_store');
sc_require('models/base_model');

/** @class
 *
 * Describes the named constituent data values of a case. An attribute may be
 * 'nominal' or 'numeric', meaning the data value will either be interpreted as
 * string valued or numeric. An attribute may be a formula, meaning that the
 * attribute's corresponding data value would be computed.
 * An attribute may be editable or not. Some properties of attributes affect
 * how the corresponding values are displayed. For example, 'precision' affects
 * the formatting of numeric attributes, and 'colormap' affects the color's used
 * when the attribute is displayed in a graph legend.
 *
 * @extends SC.BaseModel
 */
DG.Attribute = DG.BaseModel.extend(
  /** @scope DG.Attribute.prototype */ {

    /**
     * The name of the attribute
     * @property {String}
     */
    name: '',

    /**
     * The formula for the attribute
     * @property {String}
     */
    formula: '',

    /**
     * The map of attribute and category color values, for the attribute.
     * For special color keys and values, see:
     *   DG.ColorUtilities.getAttributeColorFromColorMap(),
     *   DG.ColorUtilities.getCategoryColorFromColorMap(),
     *   DG.ColorUtilities.simpleColorNames()
     * @property {Object}
     */
    colormap: null,

    /**
     * A description of/comment for the attribute
     * @property {String}
     */
    description: '',

    /**
     * Type of the attribute: 'numeric' or 'nominal'
     */
    type: null,

    /**
     * A relational link back to the parent collection.
     * @property {DG.CollectionRecord}
     */
    collection: null,

    /**
     * Number of decimal places to use for display.
     * Applicable only to numeric values.
     * @property {Number}
     */
    precision: 2,

      /**
       * Currently the only significance of this string property is that it
       * shows in parentheses next to attribute names in case table column
       * headers and graph axis labels.
       * @property{String}
       */
      unit: null,

    /**
     * True if the attribute is user-editable, false otherwise.
     * By default user-created attributes are editable as well as
     * any game-created attributes marked as such.
     * @property {Boolean}
     */
    editable: false,

    /**
     @private
     The DG.Formula for evaluation.
     @property   {DG.Formula}
     */
    _dgFormula: null,

    /**
     Initialization function.
     */
    init: function() {
      sc_super();

      // Handle formula passed in as property at creation
      var formulaSource = this.get('formula');
      if( !SC.empty( formulaSource) && !this._dgFormula) {
        this.createDGFormula();
        this._dgFormula.set('source', formulaSource);
      }
      if (typeof this.collection === 'number') {
        this.collection = DG.store.find(DG.Attribute, this.collection);
      }
      this.colormap = {};
    },

    verify: function () {
      if (SC.empty(this.collection)) {
        DG.logWarn('Unattached attribute: ' + this.id);
      }
      if (typeof this.collection === 'number') {
        DG.logWarn('Unresolved reference to collection id, ' + this.collection +
          ', in attribute: ' + this.id);
      }
      if (!(this.collection.recordType
        && this.collection.recordType() === DG.Collection) ) {
        DG.logWarn('Unexpected collection RecordType: '
          + this.collection.recordTypeString());
      }
    },

    /**
     Destruction function.
     */
    destroy: function() {
      var attrID = this.get('id');

      if( !SC.none( attrID)) {
        delete DG.Attribute.idMap[ attrID];
      }

      if (this.collection) {
        this.collection.attrs.removeObject(this);
      }

      if( this._dgFormula)
        this.destroyDGFormula();
      sc_super();
    },

    /**
     Utility function for creating the DG.Formula when necessary
     and hooking up the necessary observers.
     */
    createDGFormula: function() {
      this._dgFormula = DG.Formula.create({
        context: DG.CollectionFormulaContext.
          create({ collection: this.get('collection') })
      });
      this._dgFormula.addObserver('dependentChange', this, 'dependentDidChange');
    },

    /**
     Utility function for destroying the DG.Formula when necessary
     and cleanup up the necessary observers.
     */
    destroyDGFormula: function() {
      this._dgFormula.removeObserver('dependentChange', this, 'dependentDidChange');
      this._dgFormula.destroy();
      this._dgFormula = null;
    },

    /**
     * {Computed} True if the attribute has a non-empty formula.
     * @property {Boolean}
     */
    hasFormula: function() {
      return !SC.empty( this.get('formula'));
    }.property('formula').cacheable(),

    /**
     * Evaluates the attribute's formula in the context of the specified namespace object.
     * @param {Object}    Namespace object with property:value pairs for evaluation context
     * @return {Number | ?} Result of evaluation
     */
    evalFormula: function( iCase) {
      var tFormula = this._dgFormula,
        tReturnValue = NaN;
      try {
        // Client is responsible for passing _case_ and _id_
        tReturnValue = tFormula.evaluate({ _case_: iCase, _id_: iCase && iCase.get('id') });
      }
      catch(e) {
        // Return error objects as attribute values.
        tReturnValue = e;
      }

      return tReturnValue;
    },

    /**
     Observer function called when the formula changes.
     This function creates, updates, or destroys the corresponding
     DG.Formula as needed and sets up/tears down the necessary
     observers whenever the formula changes.
     */
    formulaDidChange: function() {
      var tSource = this.get('formula');

      // Non-empty formula string -- we need a DG.Formula
      if( !SC.empty( tSource)) {
        // Create the DG.Formula if we don't have one yet
        if( !this._dgFormula)
          this.createDGFormula();
        // Update the DG.Formula with the new source
        this._dgFormula.set('source', tSource);
      }

      // empty formula string -- no need for a DG.Formula
      else {
        if( this._dgFormula)
          this.destroyDGFormula();
      }
    }.observes('formula'),

    /**
     Observer function called when an attribute formula notifies
     that one of its dependents has changed.
     */
    dependentDidChange: function( iNotifier, iKey) {
      this.notifyPropertyChange( iKey);
    },

    /**
     Override to update our attribute map to include attributes loaded
     from documents.
     */
    didLoadRecord: function() {
      var id = this.get('id');
      DG.Attribute.idMap[ id] = this;
    },
    toArchive: function () {
      return {
        name: this.name,
        type: this.type,
        defaultMin: this.defaultMin,
        defaultMax: this.defaultMax,
        description: this.description,
        colormap: this.colormap || undefined,
        blockDisplayOfEmptyCategories: this.blockDisplayOfEmptyCategories || undefined,
        editable: this.hasFormula()? this.editable: undefined,
        formula: this.hasFormula()? this.formula: undefined,
        guid: this.id,
        precision: this.precision,
        unit: this.unit
      };
    }
  });

/**
 Global map from attribute ID to attribute.
 More efficient than calling DG.store.find(DG.Attribute, attrID);
 */
DG.Attribute.idMap = {};

/**
 Retrieves an attribute by its ID using our internal map.
 @param  {Number}  iAttrID -- the ID of the attribute to be retrieved
 */
DG.Attribute.getAttributeByID = function( iAttrID) {
  return DG.Attribute.idMap[ iAttrID];
};

/**
 * Creates a new attribute with the specified properties.
 * @param {Object}  iProperties List of properties to apply to the newly-created DG.Attribute.
 * @return {DG.Attribute}   The newly-created DG.Attribute
 */
DG.Attribute.createAttribute = function( iProperties) {
  var collection = DG.store.resolve(iProperties.collection),
    newAttribute;

  iProperties.collection = collection;
  newAttribute = DG.Attribute.create(iProperties || {});
  if( iProperties.colormap) {
    newAttribute.colormap = SC.clone( iProperties.colormap);
  }

  DG.store.commitRecords();
  DG.Attribute.idMap[ newAttribute.get('id')] = newAttribute;
  return newAttribute;
};

/**
 * Destroys the specified DG.Attribute.
 * @param {DG.Attribute}  The DG.Attribute to destroy
 */
DG.Attribute.destroyAttribute = function( iAttribute) {
  iAttribute.destroy();
};
<commit_msg>Fix bug: Editable columns lose their editability by save and restore.<commit_after>// ==========================================================================
//                            DG.Attribute
//
//  Copyright (c) 2014 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

sc_require('models/model_store');
sc_require('models/base_model');

/** @class
 *
 * Describes the named constituent data values of a case. An attribute may be
 * 'nominal' or 'numeric', meaning the data value will either be interpreted as
 * string valued or numeric. An attribute may be a formula, meaning that the
 * attribute's corresponding data value would be computed.
 * An attribute may be editable or not. Some properties of attributes affect
 * how the corresponding values are displayed. For example, 'precision' affects
 * the formatting of numeric attributes, and 'colormap' affects the color's used
 * when the attribute is displayed in a graph legend.
 *
 * @extends SC.BaseModel
 */
DG.Attribute = DG.BaseModel.extend(
  /** @scope DG.Attribute.prototype */ {

    /**
     * The name of the attribute
     * @property {String}
     */
    name: '',

    /**
     * The formula for the attribute
     * @property {String}
     */
    formula: '',

    /**
     * The map of attribute and category color values, for the attribute.
     * For special color keys and values, see:
     *   DG.ColorUtilities.getAttributeColorFromColorMap(),
     *   DG.ColorUtilities.getCategoryColorFromColorMap(),
     *   DG.ColorUtilities.simpleColorNames()
     * @property {Object}
     */
    colormap: null,

    /**
     * A description of/comment for the attribute
     * @property {String}
     */
    description: '',

    /**
     * Type of the attribute: 'numeric' or 'nominal'
     */
    type: null,

    /**
     * A relational link back to the parent collection.
     * @property {DG.CollectionRecord}
     */
    collection: null,

    /**
     * Number of decimal places to use for display.
     * Applicable only to numeric values.
     * @property {Number}
     */
    precision: 2,

      /**
       * Currently the only significance of this string property is that it
       * shows in parentheses next to attribute names in case table column
       * headers and graph axis labels.
       * @property{String}
       */
      unit: null,

    /**
     * True if the attribute is user-editable, false otherwise.
     * By default user-created attributes are editable as well as
     * any game-created attributes marked as such.
     * @property {Boolean}
     */
    editable: false,

    /**
     @private
     The DG.Formula for evaluation.
     @property   {DG.Formula}
     */
    _dgFormula: null,

    /**
     Initialization function.
     */
    init: function() {
      sc_super();

      // Handle formula passed in as property at creation
      var formulaSource = this.get('formula');
      if( !SC.empty( formulaSource) && !this._dgFormula) {
        this.createDGFormula();
        this._dgFormula.set('source', formulaSource);
      }
      if (typeof this.collection === 'number') {
        this.collection = DG.store.find(DG.Attribute, this.collection);
      }
      this.colormap = {};
    },

    verify: function () {
      if (SC.empty(this.collection)) {
        DG.logWarn('Unattached attribute: ' + this.id);
      }
      if (typeof this.collection === 'number') {
        DG.logWarn('Unresolved reference to collection id, ' + this.collection +
          ', in attribute: ' + this.id);
      }
      if (!(this.collection.recordType
        && this.collection.recordType() === DG.Collection) ) {
        DG.logWarn('Unexpected collection RecordType: '
          + this.collection.recordTypeString());
      }
    },

    /**
     Destruction function.
     */
    destroy: function() {
      var attrID = this.get('id');

      if( !SC.none( attrID)) {
        delete DG.Attribute.idMap[ attrID];
      }

      if (this.collection) {
        this.collection.attrs.removeObject(this);
      }

      if( this._dgFormula)
        this.destroyDGFormula();
      sc_super();
    },

    /**
     Utility function for creating the DG.Formula when necessary
     and hooking up the necessary observers.
     */
    createDGFormula: function() {
      this._dgFormula = DG.Formula.create({
        context: DG.CollectionFormulaContext.
          create({ collection: this.get('collection') })
      });
      this._dgFormula.addObserver('dependentChange', this, 'dependentDidChange');
    },

    /**
     Utility function for destroying the DG.Formula when necessary
     and cleanup up the necessary observers.
     */
    destroyDGFormula: function() {
      this._dgFormula.removeObserver('dependentChange', this, 'dependentDidChange');
      this._dgFormula.destroy();
      this._dgFormula = null;
    },

    /**
     * {Computed} True if the attribute has a non-empty formula.
     * @property {Boolean}
     */
    hasFormula: function() {
      return !SC.empty( this.get('formula'));
    }.property('formula').cacheable(),

    /**
     * Evaluates the attribute's formula in the context of the specified namespace object.
     * @param {Object}    Namespace object with property:value pairs for evaluation context
     * @return {Number | ?} Result of evaluation
     */
    evalFormula: function( iCase) {
      var tFormula = this._dgFormula,
        tReturnValue = NaN;
      try {
        // Client is responsible for passing _case_ and _id_
        tReturnValue = tFormula.evaluate({ _case_: iCase, _id_: iCase && iCase.get('id') });
      }
      catch(e) {
        // Return error objects as attribute values.
        tReturnValue = e;
      }

      return tReturnValue;
    },

    /**
     Observer function called when the formula changes.
     This function creates, updates, or destroys the corresponding
     DG.Formula as needed and sets up/tears down the necessary
     observers whenever the formula changes.
     */
    formulaDidChange: function() {
      var tSource = this.get('formula');

      // Non-empty formula string -- we need a DG.Formula
      if( !SC.empty( tSource)) {
        // Create the DG.Formula if we don't have one yet
        if( !this._dgFormula)
          this.createDGFormula();
        // Update the DG.Formula with the new source
        this._dgFormula.set('source', tSource);
      }

      // empty formula string -- no need for a DG.Formula
      else {
        if( this._dgFormula)
          this.destroyDGFormula();
      }
    }.observes('formula'),

    /**
     Observer function called when an attribute formula notifies
     that one of its dependents has changed.
     */
    dependentDidChange: function( iNotifier, iKey) {
      this.notifyPropertyChange( iKey);
    },

    /**
     Override to update our attribute map to include attributes loaded
     from documents.
     */
    didLoadRecord: function() {
      var id = this.get('id');
      DG.Attribute.idMap[ id] = this;
    },
    toArchive: function () {
      return {
        name: this.name,
        type: this.type,
        defaultMin: this.defaultMin,
        defaultMax: this.defaultMax,
        description: this.description,
        colormap: this.colormap || undefined,
        blockDisplayOfEmptyCategories: this.blockDisplayOfEmptyCategories || undefined,
        editable: this.editable,
        formula: this.hasFormula()? this.formula: undefined,
        guid: this.id,
        precision: this.precision,
        unit: this.unit
      };
    }
  });

/**
 Global map from attribute ID to attribute.
 More efficient than calling DG.store.find(DG.Attribute, attrID);
 */
DG.Attribute.idMap = {};

/**
 Retrieves an attribute by its ID using our internal map.
 @param  {Number}  iAttrID -- the ID of the attribute to be retrieved
 */
DG.Attribute.getAttributeByID = function( iAttrID) {
  return DG.Attribute.idMap[ iAttrID];
};

/**
 * Creates a new attribute with the specified properties.
 * @param {Object}  iProperties List of properties to apply to the newly-created DG.Attribute.
 * @return {DG.Attribute}   The newly-created DG.Attribute
 */
DG.Attribute.createAttribute = function( iProperties) {
  var collection = DG.store.resolve(iProperties.collection),
    newAttribute;

  iProperties.collection = collection;
  newAttribute = DG.Attribute.create(iProperties || {});
  if( iProperties.colormap) {
    newAttribute.colormap = SC.clone( iProperties.colormap);
  }

  DG.store.commitRecords();
  DG.Attribute.idMap[ newAttribute.get('id')] = newAttribute;
  return newAttribute;
};

/**
 * Destroys the specified DG.Attribute.
 * @param {DG.Attribute}  The DG.Attribute to destroy
 */
DG.Attribute.destroyAttribute = function( iAttribute) {
  iAttribute.destroy();
};
<|endoftext|>